-# 0.0.110 - 2022-07-26
+# 0.0.111 - Sep 12, 2022 - "Saturated with Messages"
+
+## API Updates
+ * Support for relaying onion messages has been added via a new
+ `OnionMessenger` struct when passed as the `OnionMessageHandler` to a
+ `PeerManager`. Pre-encoded onion messages can also be sent and received
+ (#1503, #1650, #1652, #1688).
+ * Rate-limiting of outbound gossip syncs has been rewritten to utilize less
+ buffering inside LDK. The new rate-limiting is also used for onion messages
+ to avoid delaying other messages (#1604. #1660, #1683).
+ * Rather than spawning a full OS thread, `lightning-background-processor` has
+ a new `process_events_async` method which takes the place of a
+ `BackgroundProcessor` for those using Rust's async (#1657).
+ * `ChannelManager::get_persistable_update_future` has been added to block on
+ a ChannelManager needing re-persistence in a Rust async environment (#1657).
+ * The `Filter::register_output` return value has been removed, as it was
+ very difficult to correctly implement (i.e., without blocking). Users
+ previously using it should instead pass dependent transactions in via
+ additional `chain::Confirm::transactions_confirmed` calls (#1663).
+ * `ChannelHandshakeConfig::their_channel_reserve_proportional_millionths` has
+ been added to allow configuring counterparty reserve values (#1619).
+ * `KeysInterface::ecdh` has been added as an ECDH oracle (#1503, #1658).
+ * The `rust-bitcoin` dependency has been updated 0.29 (#1658).
+ * The `bitcoin_hashes` dependency has been updated 0.11 (#1677).
+ * `ChannelManager::broadcast_node_announcement` has been moved to
+ `PeerManager` (#1699).
+ * `channel_` and `node_announcement`s are now rebroadcast automatically to all
+ new peers which connect (#1699).
+ * `{Init,Node}Features` sent to peers/broadcasted are now fetched via the
+ various `*MessageHandler` traits, rather than hard-coded (#1701, #1688).
+ * `Event::PaymentPathFailed::rejected_by_dest` has been renamed
+ `payment_failed_permanently` (#1702).
+ * `Invoice` now derives the std `Hash` trait (#1575).
+ * `{Signed,}RawInvoice::hash` have been renamed `signable_hash` (#1714).
+ * `chain::AccessError` now derives the std `Debug` trait (#1709).
+ * `ReadOnlyNetworkGraph::list_{channels,nodes}` have been added largely for
+ users of downstream bindings (#1651).
+ * `ChannelMonitor::get_counterparty_node_id` is now available (#1635).
+
+## Bug Fixes
+ * The script compared with that returned from `chain::Access` was incorrect
+ ~half of the time, causing spurious gossip rejection (#1666).
+ * Pending in-flight HTLCs are now considered when calculating new routes,
+ ensuring, e.g. MPP retries do not take known-saturated paths (#1643).
+ * Counterparty-revoked outputs are now included in `get_claimable_balance`
+ output via a new `Balance::CounterpartyRevokedOutputClaimable` (#1495).
+ * Inbound HTLCs for which we do not (yet) have a preimage are now included in
+ `get_claimable_balance` via a `Balance::MaybePreimageClaimableHTLC` (#1673).
+ * Probes that fail prior to being sent over their first hop are correctly
+ failed with a `Event::ProbeFailed` rather than a `PaymentPathFailed` (#1704).
+ * Pending `Event::HTLCHandlingFailed`s are no longer lost on restart (#1700).
+ * HTLCs that fail prior to being sent over their first hop are now marked as
+ retryable via `!PaymentPathFailed::payment_failed_permanently` (#1702).
+ * Dust HTLCs are now considered failed in the payment tracking logic after the
+ commitment transaction confirms, allowing retry on restart (#1691).
+ * On machines with buggy "monotonic" clocks, LDK will no longer panic if time
+ goes backwards (#1692).
+
+## Backwards Compatibility
+ * The new `current_time` argument to `PeerManager` constructors must be set to
+ a UNIX timestamp for upgraded nodes; new nodes may use a counter (#1699).
+ * `Balance::CounterpartyRevokedOutputClaimable` will never be generated for
+ channels that were observed to go on-chain with LDK versions prior to
+ 0.0.111 (#1495).
+ * `ChannelMonitor::get_counterparty_node_id` will return `None` for all
+ channels opened on a version of LDK prior to 0.0.110 (#1635).
+ * Setting `their_channel_reserve_proportional_millionths` to any value other
+ than the default will cause LDK versions prior to 0.0.104 to be unable to
+ read the serialized `ChannelManager` (#1619).
+
+## Security
+0.0.111 fixes a denial-of-service vulnerability which is reachable from
+untrusted input in deployments accepting 0conf channels, or via a race-condition
+in deployments creating outbound 0conf channels.
+
+ * LDK versions prior to 0.0.111 may spuriously panic when receiving a block if
+ they are awaiting the construction of a funding transaction for a 0-conf
+ channel (#1711). 0-conf support was added in LDK version 0.0.107.
+
+In total, this release features 84 files changed, 6306 insertions, 1960
+deletions in 121 commits from 11 authors, in alphabetical order:
+ * Arik Sosman
+ * Devrandom
+ * Duncan Dean
+ * Elias Rohrer
+ * Gursharan Singh
+ * Matt Corallo
+ * NicolaLS
+ * Valentine Wallace
+ * Viktor Tigerström
+ * jurvis
+ * ok300
+
+
+# 0.0.110 - 2022-07-26 - "Routing, With a Vengeance"
## API Updates
* `ChannelManager::send_probe` and `Score::probe_{failed,successful}` have
* Wilmer Paulino
* jurvis
-# 0.0.109 - 2022-07-01
+# 0.0.109 - 2022-07-01 - "The Kitchen Sink"
## API Updates
* `ChannelManager::update_channel_config` has been added to allow the fields
* Wilmer Paulino
-# 0.0.108 - 2022-06-10
+# 0.0.108 - 2022-06-10 - "You Wanted It To Build?! Why Didn't You Say So?"
## Bug Fixes
* Fixed `lightning-background-processor` build in release mode.
* Max Fang
* Viktor Tigerström
-# 0.0.107 - 2022-06-08
+# 0.0.107 - 2022-06-08 - "BlueWallet's Wishlist"
## API Updates
* Channels larger than 16777215 sats (Wumbo!) are now supported and can be
* vss96
-# 0.0.100 - 2021-08-17
+# 0.0.100 - 2021-08-17 - "Oh, so *that's* what's going on inside the box"
## API Updates
* The `lightning` crate can now be built in no_std mode, making it easy to
deletions in 95 commits from 6 authors.
-# 0.0.99 - 2021-07-09
+# 0.0.99 - 2021-07-09 - "It's a Bugz Life"
## API Updates
versions. If you have such a `ChannelManager` available, a simple patch will
allow it to deserialize. Please file an issue if you need assistance (#973).
-# 0.0.98 - 2021-06-11
+# 0.0.98 - 2021-06-11 - "It's ALIVVVVEEEEEEE"
0.0.98 should be considered a release candidate to the first alpha release of
Rust-Lightning and the broader LDK. It represents several years of work
don't hesitate to ask if the assigned party or previous commenters are still
working on it if it has been awhile.
+Any changes that have nontrivial backwards compatibility considerations should
+have an entry added in the `pending_changelog` folder which includes the
+CHANGELOG entries that should be added in the next release.
+
Peer review
-----------
"no-std-check",
]
-# Our tests do actual crypo and lots of work, the tradeoff for -O1 is well worth it.
+# Our tests do actual crypto and lots of work, the tradeoff for -O1 is well worth it.
# Ideally we would only do this in profile.test, but profile.test only applies to
# the test binary, not dependencies, which means most of the critical code still
# gets compiled as -O0. See
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
use lightning::chain::keysinterface::{KeyMaterial, KeysInterface, InMemorySigner, Recipient};
use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
-use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentSendFailure, ChannelManagerReadArgs};
+use lightning::ln::channelmanager::{self, 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;
use lightning::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState};
if let Err(err) = source.send_payment(&Route {
paths: vec![vec![RouteHop {
pubkey: dest.get_our_node_id(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: dest_chan_id,
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: amt,
cltv_expiry_delta: 200,
}]],
if let Err(err) = source.send_payment(&Route {
paths: vec![vec![RouteHop {
pubkey: middle.get_our_node_id(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: middle_chan_id,
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: 50000,
cltv_expiry_delta: 100,
},RouteHop {
pubkey: dest.get_our_node_id(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: dest_chan_id,
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: amt,
cltv_expiry_delta: 200,
}]],
let mut channel_txn = Vec::new();
macro_rules! make_channel {
($source: expr, $dest: expr, $chan_id: expr) => { {
- $source.peer_connected(&$dest.get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
- $dest.peer_connected(&$source.get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
+ $source.peer_connected(&$dest.get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ $dest.peer_connected(&$source.get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
$source.create_channel($dest.get_our_node_id(), 100_000, 42, 0, None).unwrap();
let open_channel = {
} else { panic!("Wrong event type"); }
};
- $dest.handle_open_channel(&$source.get_our_node_id(), InitFeatures::known(), &open_channel);
+ $dest.handle_open_channel(&$source.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
let accept_channel = {
let events = $dest.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
} else { panic!("Wrong event type"); }
};
- $source.handle_accept_channel(&$dest.get_our_node_id(), InitFeatures::known(), &accept_channel);
+ $source.handle_accept_channel(&$dest.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel);
let funding_output;
{
let events = $source.get_and_clear_pending_events();
},
0x0e => {
if chan_a_disconnected {
- nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
- nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
+ nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
chan_a_disconnected = false;
}
},
0x0f => {
if chan_b_disconnected {
- nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
- nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
+ nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
chan_b_disconnected = false;
}
},
// Next, make sure peers are all connected to each other
if chan_a_disconnected {
- nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
- nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
+ nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
chan_a_disconnected = false;
}
if chan_b_disconnected {
- nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
- nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
+ nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
chan_b_disconnected = false;
}
chan_handler: channelmanager.clone(),
route_handler: gossip_sync.clone(),
onion_message_handler: IgnoringMessageHandler {},
- }, our_network_key, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0], Arc::clone(&logger), IgnoringMessageHandler{}));
+ }, our_network_key, 0, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0], Arc::clone(&logger), IgnoringMessageHandler{}));
let mut should_forward = false;
let mut payments_received: Vec<PaymentHash> = Vec::new();
};
loop {
if get_slice!(1)[0] == 0 {
- crypter.encrypt_message(get_slice!(slice_to_be16(get_slice!(2))));
+ crypter.encrypt_buffer(get_slice!(slice_to_be16(get_slice!(2))));
} else {
let len = match crypter.decrypt_length_header(get_slice!(16+2)) {
Ok(len) => len,
use lightning::chain;
use lightning::chain::transaction::OutPoint;
-use lightning::ln::channelmanager::{ChannelDetails, ChannelCounterparty};
-use lightning::ln::features::InitFeatures;
+use lightning::ln::channelmanager::{self, ChannelDetails, ChannelCounterparty};
use lightning::ln::msgs;
use lightning::routing::gossip::{NetworkGraph, RoutingFees};
use lightning::routing::router::{find_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters};
channel_id: [0; 32],
counterparty: ChannelCounterparty {
node_id: *rnid,
- features: InitFeatures::known(),
+ features: channelmanager::provided_init_features(),
unspendable_punishment_reserve: 0,
forwarding_info: None,
outbound_htlc_minimum_msat: None,
[package]
name = "lightning-background-processor"
-version = "0.0.110"
+version = "0.0.111"
authors = ["Valentine Wallace <vwallace@protonmail.com>"]
license = "MIT OR Apache-2.0"
repository = "http://github.com/lightningdevkit/rust-lightning"
[dependencies]
bitcoin = "0.29.0"
-lightning = { version = "0.0.110", path = "../lightning", features = ["std"] }
-lightning-rapid-gossip-sync = { version = "0.0.110", path = "../lightning-rapid-gossip-sync" }
+lightning = { version = "0.0.111", path = "../lightning", features = ["std"] }
+lightning-rapid-gossip-sync = { version = "0.0.111", path = "../lightning-rapid-gossip-sync" }
+futures = { version = "0.3", optional = true }
[dev-dependencies]
-lightning = { version = "0.0.110", path = "../lightning", features = ["_test_utils"] }
-lightning-invoice = { version = "0.18.0", path = "../lightning-invoice" }
-lightning-persister = { version = "0.0.110", path = "../lightning-persister" }
+lightning = { version = "0.0.111", path = "../lightning", features = ["_test_utils"] }
+lightning-invoice = { version = "0.19.0", path = "../lightning-invoice" }
+lightning-persister = { version = "0.0.111", path = "../lightning-persister" }
use std::time::{Duration, Instant};
use std::ops::Deref;
+#[cfg(feature = "futures")]
+use futures::{select, future::FutureExt};
+
/// `BackgroundProcessor` takes care of tasks that (1) need to happen periodically to keep
/// Rust-Lightning running properly, and (2) either can or should be run in the background. Its
/// responsibilities are:
}
}
+macro_rules! define_run_body {
+ ($persister: ident, $event_handler: ident, $chain_monitor: ident, $channel_manager: ident,
+ $gossip_sync: ident, $peer_manager: ident, $logger: ident, $scorer: ident,
+ $loop_exit_check: expr, $await: expr)
+ => { {
+ let event_handler = DecoratingEventHandler {
+ event_handler: $event_handler,
+ gossip_sync: &$gossip_sync,
+ };
+
+ 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();
+ let mut last_prune_call = Instant::now();
+ let mut last_scorer_persist_call = Instant::now();
+ let mut have_pruned = false;
+
+ loop {
+ $channel_manager.process_pending_events(&event_handler);
+ $chain_monitor.process_pending_events(&event_handler);
+
+ // Note that the PeerManager::process_events may block on ChannelManager's locks,
+ // hence it comes last here. When the ChannelManager finishes whatever it's doing,
+ // we want to ensure we get into `persist_manager` as quickly as we can, especially
+ // without running the normal event processing above and handing events to users.
+ //
+ // Specifically, on an *extremely* slow machine, we may see ChannelManager start
+ // processing a message effectively at any point during this loop. In order to
+ // minimize the time between such processing completing and persisting the updated
+ // ChannelManager, we want to minimize methods blocking on a ChannelManager
+ // generally, and as a fallback place such blocking only immediately before
+ // persistence.
+ $peer_manager.process_events();
+
+ // We wait up to 100ms, but track how long it takes to detect being put to sleep,
+ // see `await_start`'s use below.
+ let await_start = Instant::now();
+ let updates_available = $await;
+ let await_time = await_start.elapsed();
+
+ if updates_available {
+ log_trace!($logger, "Persisting ChannelManager...");
+ $persister.persist_manager(&*$channel_manager)?;
+ log_trace!($logger, "Done persisting ChannelManager.");
+ }
+ // Exit the loop if the background processor was requested to stop.
+ if $loop_exit_check {
+ log_trace!($logger, "Terminating background processor.");
+ break;
+ }
+ if last_freshness_call.elapsed().as_secs() > FRESHNESS_TIMER {
+ log_trace!($logger, "Calling ChannelManager's timer_tick_occurred");
+ $channel_manager.timer_tick_occurred();
+ last_freshness_call = Instant::now();
+ }
+ if await_time > Duration::from_secs(1) {
+ // On various platforms, we may be starved of CPU cycles for several reasons.
+ // E.g. on iOS, if we've been in the background, we will be entirely paused.
+ // Similarly, if we're on a desktop platform and the device has been asleep, we
+ // may not get any cycles.
+ // We detect this by checking if our max-100ms-sleep, above, ran longer than a
+ // full second, at which point we assume sockets may have been killed (they
+ // appear to be at least on some platforms, even if it has only been a second).
+ // Note that we have to take care to not get here just because user event
+ // processing was slow at the top of the loop. For example, the sample client
+ // may call Bitcoin Core RPCs during event handling, which very often takes
+ // more than a handful of seconds to complete, and shouldn't disconnect all our
+ // peers.
+ log_trace!($logger, "100ms sleep took more than a second, disconnecting peers.");
+ $peer_manager.disconnect_all_peers();
+ last_ping_call = Instant::now();
+ } else if last_ping_call.elapsed().as_secs() > PING_TIMER {
+ log_trace!($logger, "Calling PeerManager's timer_tick_occurred");
+ $peer_manager.timer_tick_occurred();
+ last_ping_call = Instant::now();
+ }
+
+ // Note that we want to run a graph prune once not long after startup before
+ // falling back to our usual hourly prunes. This avoids short-lived clients never
+ // pruning their network graph. We run once 60 seconds after startup before
+ // continuing our normal cadence.
+ if last_prune_call.elapsed().as_secs() > if have_pruned { NETWORK_PRUNE_TIMER } else { FIRST_NETWORK_PRUNE_TIMER } {
+ // The network graph must not be pruned while rapid sync completion is pending
+ log_trace!($logger, "Assessing prunability of network graph");
+ if let Some(network_graph) = $gossip_sync.prunable_network_graph() {
+ network_graph.remove_stale_channels();
+
+ if let Err(e) = $persister.persist_graph(network_graph) {
+ log_error!($logger, "Error: Failed to persist network graph, check your disk and permissions {}", e)
+ }
+
+ last_prune_call = Instant::now();
+ have_pruned = true;
+ } else {
+ log_trace!($logger, "Not pruning network graph, either due to pending rapid gossip sync or absence of a prunable graph.");
+ }
+ }
+
+ if last_scorer_persist_call.elapsed().as_secs() > SCORER_PERSIST_TIMER {
+ if let Some(ref scorer) = $scorer {
+ log_trace!($logger, "Persisting scorer");
+ if let Err(e) = $persister.persist_scorer(&scorer) {
+ log_error!($logger, "Error: Failed to persist scorer, check your disk and permissions {}", e)
+ }
+ }
+ last_scorer_persist_call = Instant::now();
+ }
+ }
+
+ // After we exit, ensure we persist the ChannelManager one final time - this avoids
+ // some races where users quit while channel updates were in-flight, with
+ // ChannelMonitor update(s) persisted without a corresponding ChannelManager update.
+ $persister.persist_manager(&*$channel_manager)?;
+
+ // Persist Scorer on exit
+ if let Some(ref scorer) = $scorer {
+ $persister.persist_scorer(&scorer)?;
+ }
+
+ // Persist NetworkGraph on exit
+ if let Some(network_graph) = $gossip_sync.network_graph() {
+ $persister.persist_graph(network_graph)?;
+ }
+
+ Ok(())
+ } }
+}
+
+/// Processes background events in a future.
+///
+/// `sleeper` should return a future which completes in the given amount of time and returns a
+/// boolean indicating whether the background processing should continue. Once `sleeper` returns a
+/// future which outputs false, the loop will exit and this function's future will complete.
+///
+/// See [`BackgroundProcessor::start`] for information on which actions this handles.
+#[cfg(feature = "futures")]
+pub async fn process_events_async<
+ 'a,
+ Signer: 'static + Sign,
+ CA: 'static + Deref + Send + Sync,
+ CF: 'static + Deref + Send + Sync,
+ CW: 'static + Deref + Send + Sync,
+ T: 'static + Deref + Send + Sync,
+ K: 'static + Deref + Send + Sync,
+ F: 'static + Deref + Send + Sync,
+ G: 'static + Deref<Target = NetworkGraph<L>> + Send + Sync,
+ L: 'static + Deref + Send + Sync,
+ P: 'static + Deref + Send + Sync,
+ Descriptor: 'static + SocketDescriptor + Send + Sync,
+ CMH: 'static + Deref + Send + Sync,
+ RMH: 'static + Deref + Send + Sync,
+ EH: 'static + EventHandler + Send,
+ PS: 'static + Deref + Send,
+ M: 'static + Deref<Target = ChainMonitor<Signer, CF, T, F, L, P>> + Send + Sync,
+ CM: 'static + Deref<Target = ChannelManager<Signer, CW, T, K, F, L>> + Send + Sync,
+ PGS: 'static + Deref<Target = P2PGossipSync<G, CA, L>> + Send + Sync,
+ RGS: 'static + Deref<Target = RapidGossipSync<G, L>> + Send,
+ UMH: 'static + Deref + Send + Sync,
+ PM: 'static + Deref<Target = PeerManager<Descriptor, CMH, RMH, L, UMH>> + Send + Sync,
+ S: 'static + Deref<Target = SC> + Send + Sync,
+ SC: WriteableScore<'a>,
+ SleepFuture: core::future::Future<Output = bool>,
+ Sleeper: Fn(Duration) -> SleepFuture
+>(
+ persister: PS, event_handler: EH, chain_monitor: M, channel_manager: CM,
+ gossip_sync: GossipSync<PGS, RGS, G, CA, L>, peer_manager: PM, logger: L, scorer: Option<S>,
+ sleeper: Sleeper,
+) -> Result<(), std::io::Error>
+where
+ CA::Target: 'static + chain::Access,
+ CF::Target: 'static + chain::Filter,
+ CW::Target: 'static + chain::Watch<Signer>,
+ T::Target: 'static + BroadcasterInterface,
+ K::Target: 'static + KeysInterface<Signer = Signer>,
+ F::Target: 'static + FeeEstimator,
+ L::Target: 'static + Logger,
+ P::Target: 'static + Persist<Signer>,
+ CMH::Target: 'static + ChannelMessageHandler,
+ RMH::Target: 'static + RoutingMessageHandler,
+ UMH::Target: 'static + CustomMessageHandler,
+ PS::Target: 'static + Persister<'a, Signer, CW, T, K, F, L, SC>,
+{
+ let mut should_continue = true;
+ define_run_body!(persister, event_handler, chain_monitor, channel_manager,
+ gossip_sync, peer_manager, logger, scorer, should_continue, {
+ select! {
+ _ = channel_manager.get_persistable_update_future().fuse() => true,
+ cont = sleeper(Duration::from_millis(100)).fuse() => {
+ should_continue = cont;
+ false
+ }
+ }
+ })
+}
+
impl BackgroundProcessor {
/// Start a background thread that takes care of responsibilities enumerated in the [top-level
/// documentation].
let stop_thread = Arc::new(AtomicBool::new(false));
let stop_thread_clone = stop_thread.clone();
let handle = thread::spawn(move || -> Result<(), std::io::Error> {
- let event_handler = DecoratingEventHandler {
- event_handler,
- gossip_sync: &gossip_sync,
- };
-
- 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();
- let mut last_prune_call = Instant::now();
- let mut last_scorer_persist_call = Instant::now();
- let mut have_pruned = false;
-
- loop {
- channel_manager.process_pending_events(&event_handler);
- chain_monitor.process_pending_events(&event_handler);
-
- // Note that the PeerManager::process_events may block on ChannelManager's locks,
- // hence it comes last here. When the ChannelManager finishes whatever it's doing,
- // we want to ensure we get into `persist_manager` as quickly as we can, especially
- // without running the normal event processing above and handing events to users.
- //
- // Specifically, on an *extremely* slow machine, we may see ChannelManager start
- // processing a message effectively at any point during this loop. In order to
- // minimize the time between such processing completing and persisting the updated
- // ChannelManager, we want to minimize methods blocking on a ChannelManager
- // generally, and as a fallback place such blocking only immediately before
- // persistence.
- peer_manager.process_events();
-
- // We wait up to 100ms, but track how long it takes to detect being put to sleep,
- // see `await_start`'s use below.
- let await_start = Instant::now();
- let updates_available =
- channel_manager.await_persistable_update_timeout(Duration::from_millis(100));
- let await_time = await_start.elapsed();
-
- if updates_available {
- log_trace!(logger, "Persisting ChannelManager...");
- persister.persist_manager(&*channel_manager)?;
- log_trace!(logger, "Done persisting ChannelManager.");
- }
- // Exit the loop if the background processor was requested to stop.
- if stop_thread.load(Ordering::Acquire) == true {
- log_trace!(logger, "Terminating background processor.");
- break;
- }
- if last_freshness_call.elapsed().as_secs() > FRESHNESS_TIMER {
- log_trace!(logger, "Calling ChannelManager's timer_tick_occurred");
- channel_manager.timer_tick_occurred();
- last_freshness_call = Instant::now();
- }
- if await_time > Duration::from_secs(1) {
- // On various platforms, we may be starved of CPU cycles for several reasons.
- // E.g. on iOS, if we've been in the background, we will be entirely paused.
- // Similarly, if we're on a desktop platform and the device has been asleep, we
- // may not get any cycles.
- // We detect this by checking if our max-100ms-sleep, above, ran longer than a
- // full second, at which point we assume sockets may have been killed (they
- // appear to be at least on some platforms, even if it has only been a second).
- // Note that we have to take care to not get here just because user event
- // processing was slow at the top of the loop. For example, the sample client
- // may call Bitcoin Core RPCs during event handling, which very often takes
- // more than a handful of seconds to complete, and shouldn't disconnect all our
- // peers.
- log_trace!(logger, "100ms sleep took more than a second, disconnecting peers.");
- peer_manager.disconnect_all_peers();
- last_ping_call = Instant::now();
- } else if last_ping_call.elapsed().as_secs() > PING_TIMER {
- log_trace!(logger, "Calling PeerManager's timer_tick_occurred");
- peer_manager.timer_tick_occurred();
- last_ping_call = Instant::now();
- }
-
- // Note that we want to run a graph prune once not long after startup before
- // falling back to our usual hourly prunes. This avoids short-lived clients never
- // pruning their network graph. We run once 60 seconds after startup before
- // continuing our normal cadence.
- if last_prune_call.elapsed().as_secs() > if have_pruned { NETWORK_PRUNE_TIMER } else { FIRST_NETWORK_PRUNE_TIMER } {
- // The network graph must not be pruned while rapid sync completion is pending
- log_trace!(logger, "Assessing prunability of network graph");
- if let Some(network_graph) = gossip_sync.prunable_network_graph() {
- network_graph.remove_stale_channels();
-
- if let Err(e) = persister.persist_graph(network_graph) {
- log_error!(logger, "Error: Failed to persist network graph, check your disk and permissions {}", e)
- }
-
- last_prune_call = Instant::now();
- have_pruned = true;
- } else {
- log_trace!(logger, "Not pruning network graph, either due to pending rapid gossip sync or absence of a prunable graph.");
- }
- }
-
- if last_scorer_persist_call.elapsed().as_secs() > SCORER_PERSIST_TIMER {
- if let Some(ref scorer) = scorer {
- log_trace!(logger, "Persisting scorer");
- if let Err(e) = persister.persist_scorer(&scorer) {
- log_error!(logger, "Error: Failed to persist scorer, check your disk and permissions {}", e)
- }
- }
- last_scorer_persist_call = Instant::now();
- }
- }
-
- // After we exit, ensure we persist the ChannelManager one final time - this avoids
- // some races where users quit while channel updates were in-flight, with
- // ChannelMonitor update(s) persisted without a corresponding ChannelManager update.
- persister.persist_manager(&*channel_manager)?;
-
- // Persist Scorer on exit
- if let Some(ref scorer) = scorer {
- persister.persist_scorer(&scorer)?;
- }
-
- // Persist NetworkGraph on exit
- if let Some(network_graph) = gossip_sync.network_graph() {
- persister.persist_graph(network_graph)?;
- }
-
- Ok(())
+ define_run_body!(persister, event_handler, chain_monitor, channel_manager,
+ gossip_sync, peer_manager, logger, scorer, stop_thread.load(Ordering::Acquire),
+ channel_manager.await_persistable_update_timeout(Duration::from_millis(100)))
});
Self { stop_thread: stop_thread_clone, thread_handle: Some(handle) }
}
use lightning::chain::keysinterface::{InMemorySigner, Recipient, KeysInterface, KeysManager};
use lightning::chain::transaction::OutPoint;
use lightning::get_event_msg;
- use lightning::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChainParameters, ChannelManager, SimpleArcChannelManager};
- use lightning::ln::features::{ChannelFeatures, InitFeatures};
+ use lightning::ln::channelmanager::{self, BREAKDOWN_TIMEOUT, ChainParameters, ChannelManager, SimpleArcChannelManager};
+ use lightning::ln::features::ChannelFeatures;
use lightning::ln::msgs::{ChannelMessageHandler, Init};
use lightning::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor, IgnoringMessageHandler};
use lightning::routing::gossip::{NetworkGraph, P2PGossipSync};
let p2p_gossip_sync = Arc::new(P2PGossipSync::new(network_graph.clone(), Some(chain_source.clone()), logger.clone()));
let rapid_gossip_sync = Arc::new(RapidGossipSync::new(network_graph.clone()));
let msg_handler = MessageHandler { chan_handler: Arc::new(test_utils::TestChannelMessageHandler::new()), route_handler: Arc::new(test_utils::TestRoutingMessageHandler::new()), onion_message_handler: IgnoringMessageHandler{}};
- let peer_manager = Arc::new(PeerManager::new(msg_handler, keys_manager.get_node_secret(Recipient::Node).unwrap(), &seed, logger.clone(), IgnoringMessageHandler{}));
+ let peer_manager = Arc::new(PeerManager::new(msg_handler, keys_manager.get_node_secret(Recipient::Node).unwrap(), 0, &seed, logger.clone(), IgnoringMessageHandler{}));
let scorer = Arc::new(Mutex::new(test_utils::TestScorer::with_penalty(0)));
let node = Node { node: manager, p2p_gossip_sync, rapid_gossip_sync, peer_manager, chain_monitor, persister, tx_broadcaster, network_graph, logger, best_block, scorer };
nodes.push(node);
for i in 0..num_nodes {
for j in (i+1)..num_nodes {
- nodes[i].node.peer_connected(&nodes[j].node.get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
- nodes[j].node.peer_connected(&nodes[i].node.get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
+ nodes[i].node.peer_connected(&nodes[j].node.get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[j].node.peer_connected(&nodes[i].node.get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
}
}
macro_rules! begin_open_channel {
($node_a: expr, $node_b: expr, $channel_value: expr) => {{
$node_a.node.create_channel($node_b.node.get_our_node_id(), $channel_value, 100, 42, None).unwrap();
- $node_b.node.handle_open_channel(&$node_a.node.get_our_node_id(), InitFeatures::known(), &get_event_msg!($node_a, MessageSendEvent::SendOpenChannel, $node_b.node.get_our_node_id()));
- $node_a.node.handle_accept_channel(&$node_b.node.get_our_node_id(), InitFeatures::known(), &get_event_msg!($node_b, MessageSendEvent::SendAcceptChannel, $node_a.node.get_our_node_id()));
+ $node_b.node.handle_open_channel(&$node_a.node.get_our_node_id(), channelmanager::provided_init_features(), &get_event_msg!($node_a, MessageSendEvent::SendOpenChannel, $node_b.node.get_our_node_id()));
+ $node_a.node.handle_accept_channel(&$node_b.node.get_our_node_id(), channelmanager::provided_init_features(), &get_event_msg!($node_b, MessageSendEvent::SendAcceptChannel, $node_a.node.get_our_node_id()));
}}
}
[package]
name = "lightning-block-sync"
-version = "0.0.110"
+version = "0.0.111"
authors = ["Jeffrey Czyz", "Matt Corallo"]
license = "MIT OR Apache-2.0"
repository = "http://github.com/lightningdevkit/rust-lightning"
[dependencies]
bitcoin = "0.29.0"
-lightning = { version = "0.0.110", path = "../lightning" }
+lightning = { version = "0.0.111", path = "../lightning" }
futures = { version = "0.3" }
tokio = { version = "1.0", features = [ "io-util", "net", "time" ], optional = true }
serde = { version = "1.0", features = ["derive"], optional = true }
struct ChainListenerSet<'a, L: chain::Listen + ?Sized>(Vec<(u32, &'a L)>);
impl<'a, L: chain::Listen + ?Sized> chain::Listen for ChainListenerSet<'a, L> {
+ // Needed to differentiate test expectations.
+ #[cfg(test)]
+ fn block_connected(&self, block: &bitcoin::Block, height: u32) {
+ for (starting_height, chain_listener) in self.0.iter() {
+ if height > *starting_height {
+ chain_listener.block_connected(block, height);
+ }
+ }
+ }
+
fn filtered_block_connected(&self, header: &BlockHeader, txdata: &chain::transaction::TransactionData, height: u32) {
for (starting_height, chain_listener) in self.0.iter() {
if height > *starting_height {
/// Returns the block for a given hash. A headers-only block source should return a `Transient`
/// error.
- fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block>;
+ fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, BlockData>;
/// Returns the hash of the best block and, optionally, its height.
///
pub chainwork: Uint256,
}
+/// A block including either all its transactions or only the block header.
+///
+/// [`BlockSource`] may be implemented to either always return full blocks or, in the case of
+/// compact block filters (BIP 157/158), return header-only blocks when no pertinent transactions
+/// match. See [`chain::Filter`] for details on how to notify a source of such transactions.
+pub enum BlockData {
+ /// A block containing all its transactions.
+ FullBlock(Block),
+ /// A block header for when the block does not contain any pertinent transactions.
+ HeaderOnly(BlockHeader),
+}
+
/// A lightweight client for keeping a listener in sync with the chain, allowing for Simplified
/// Payment Verification (SPV).
///
chain_poller: &mut P,
) -> Result<(), (BlockSourceError, Option<ValidatedBlockHeader>)> {
for header in connected_blocks.drain(..).rev() {
- let block = chain_poller
+ let height = header.height;
+ let block_data = chain_poller
.fetch_block(&header).await
.or_else(|e| Err((e, Some(new_tip))))?;
- debug_assert_eq!(block.block_hash, header.block_hash);
+ debug_assert_eq!(block_data.block_hash, header.block_hash);
+
+ match block_data.deref() {
+ BlockData::FullBlock(block) => {
+ self.chain_listener.block_connected(&block, height);
+ },
+ BlockData::HeaderOnly(header) => {
+ self.chain_listener.filtered_block_connected(&header, &[], height);
+ },
+ }
self.header_cache.block_connected(header.block_hash, header);
- self.chain_listener.block_connected(&block, header.height);
new_tip = header;
}
Ok(_) => panic!("Expected error"),
}
}
+
+ #[tokio::test]
+ async fn sync_from_chain_with_filtered_blocks() {
+ let mut chain = Blockchain::default().with_height(3).filtered_blocks();
+
+ let new_tip = chain.tip();
+ let old_tip = chain.at_height(1);
+ let chain_listener = &MockChainListener::new()
+ .expect_filtered_block_connected(*chain.at_height(2))
+ .expect_filtered_block_connected(*new_tip);
+ let mut notifier = ChainNotifier {
+ header_cache: &mut chain.header_cache(0..=1),
+ chain_listener,
+ };
+ let mut poller = poll::ChainPoller::new(&mut chain, Network::Testnet);
+ match notifier.synchronize_listener(new_tip, &old_tip, &mut poller).await {
+ Err((e, _)) => panic!("Unexpected error: {:?}", e),
+ Ok(_) => {},
+ }
+ }
+
}
//! Adapters that make one or more [`BlockSource`]s simpler to poll for new chain tip transitions.
-use crate::{AsyncBlockSourceResult, BlockHeaderData, BlockSource, BlockSourceError, BlockSourceResult};
+use crate::{AsyncBlockSourceResult, BlockData, BlockHeaderData, BlockSource, BlockSourceError, BlockSourceResult};
-use bitcoin::blockdata::block::Block;
use bitcoin::hash_types::BlockHash;
use bitcoin::network::constants::Network;
}
}
-impl Validate for Block {
+impl Validate for BlockData {
type T = ValidatedBlock;
fn validate(self, block_hash: BlockHash) -> BlockSourceResult<Self::T> {
- let pow_valid_block_hash = self.header
- .validate_pow(&self.header.target())
+ let header = match &self {
+ BlockData::FullBlock(block) => &block.header,
+ BlockData::HeaderOnly(header) => header,
+ };
+
+ let pow_valid_block_hash = header
+ .validate_pow(&header.target())
.or_else(|e| Err(BlockSourceError::persistent(e)))?;
if pow_valid_block_hash != block_hash {
return Err(BlockSourceError::persistent("invalid block hash"));
}
- if !self.check_merkle_root() {
- return Err(BlockSourceError::persistent("invalid merkle root"));
- }
+ if let BlockData::FullBlock(block) = &self {
+ if !block.check_merkle_root() {
+ return Err(BlockSourceError::persistent("invalid merkle root"));
+ }
- if !self.check_witness_commitment() {
- return Err(BlockSourceError::persistent("invalid witness commitment"));
+ if !block.check_witness_commitment() {
+ return Err(BlockSourceError::persistent("invalid witness commitment"));
+ }
}
Ok(ValidatedBlock { block_hash, inner: self })
/// A block with validated data against its transaction list and corresponding block hash.
pub struct ValidatedBlock {
pub(crate) block_hash: BlockHash,
- inner: Block,
+ inner: BlockData,
}
impl std::ops::Deref for ValidatedBlock {
- type Target = Block;
+ type Target = BlockData;
fn deref(&self) -> &Self::Target {
&self.inner
pub trait Validate {}
impl Validate for crate::BlockHeaderData {}
- impl Validate for bitcoin::blockdata::block::Block {}
+ impl Validate for crate::BlockData {}
}
/// The canonical `Poll` implementation used for a single `BlockSource`.
//! Simple REST client implementation which implements [`BlockSource`] against a Bitcoin Core REST
//! endpoint.
-use crate::{BlockHeaderData, BlockSource, AsyncBlockSourceResult};
+use crate::{BlockData, BlockHeaderData, BlockSource, AsyncBlockSourceResult};
use crate::http::{BinaryResponse, HttpEndpoint, HttpClient, JsonResponse};
-use bitcoin::blockdata::block::Block;
use bitcoin::hash_types::BlockHash;
use bitcoin::hashes::hex::ToHex;
})
}
- fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block> {
+ fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, BlockData> {
Box::pin(async move {
let resource_path = format!("block/{}.bin", header_hash.to_hex());
- Ok(self.request_resource::<BinaryResponse, _>(&resource_path).await?)
+ Ok(BlockData::FullBlock(self.request_resource::<BinaryResponse, _>(&resource_path).await?))
})
}
//! Simple RPC client implementation which implements [`BlockSource`] against a Bitcoin Core RPC
//! endpoint.
-use crate::{BlockHeaderData, BlockSource, AsyncBlockSourceResult};
+use crate::{BlockData, BlockHeaderData, BlockSource, AsyncBlockSourceResult};
use crate::http::{HttpClient, HttpEndpoint, HttpError, JsonResponse};
-use bitcoin::blockdata::block::Block;
use bitcoin::hash_types::BlockHash;
use bitcoin::hashes::hex::ToHex;
})
}
- fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block> {
+ fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, BlockData> {
Box::pin(async move {
let header_hash = serde_json::json!(header_hash.to_hex());
let verbosity = serde_json::json!(0);
- Ok(self.call_method("getblock", &[header_hash, verbosity]).await?)
+ Ok(BlockData::FullBlock(self.call_method("getblock", &[header_hash, verbosity]).await?))
})
}
-use crate::{AsyncBlockSourceResult, BlockHeaderData, BlockSource, BlockSourceError, UnboundedCache};
+use crate::{AsyncBlockSourceResult, BlockData, BlockHeaderData, BlockSource, BlockSourceError, UnboundedCache};
use crate::poll::{Validate, ValidatedBlockHeader};
use bitcoin::blockdata::block::{Block, BlockHeader};
without_blocks: Option<std::ops::RangeFrom<usize>>,
without_headers: bool,
malformed_headers: bool,
+ filtered_blocks: bool,
}
impl Blockchain {
Self { malformed_headers: true, ..self }
}
+ pub fn filtered_blocks(self) -> Self {
+ Self { filtered_blocks: true, ..self }
+ }
+
pub fn fork_at_height(&self, height: usize) -> Self {
assert!(height + 1 < self.blocks.len());
let mut blocks = self.blocks.clone();
})
}
- fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block> {
+ fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, BlockData> {
Box::pin(async move {
for (height, block) in self.blocks.iter().enumerate() {
if block.header.block_hash() == *header_hash {
}
}
- return Ok(block.clone());
+ if self.filtered_blocks {
+ return Ok(BlockData::HeaderOnly(block.header.clone()));
+ } else {
+ return Ok(BlockData::FullBlock(block.clone()));
+ }
}
}
Err(BlockSourceError::transient("block not found"))
pub struct MockChainListener {
expected_blocks_connected: RefCell<VecDeque<BlockHeaderData>>,
+ expected_filtered_blocks_connected: RefCell<VecDeque<BlockHeaderData>>,
expected_blocks_disconnected: RefCell<VecDeque<BlockHeaderData>>,
}
pub fn new() -> Self {
Self {
expected_blocks_connected: RefCell::new(VecDeque::new()),
+ expected_filtered_blocks_connected: RefCell::new(VecDeque::new()),
expected_blocks_disconnected: RefCell::new(VecDeque::new()),
}
}
self
}
+ pub fn expect_filtered_block_connected(self, block: BlockHeaderData) -> Self {
+ self.expected_filtered_blocks_connected.borrow_mut().push_back(block);
+ self
+ }
+
pub fn expect_block_disconnected(self, block: BlockHeaderData) -> Self {
self.expected_blocks_disconnected.borrow_mut().push_back(block);
self
}
impl chain::Listen for MockChainListener {
- fn filtered_block_connected(&self, header: &BlockHeader, _txdata: &chain::transaction::TransactionData, height: u32) {
+ fn block_connected(&self, block: &Block, height: u32) {
match self.expected_blocks_connected.borrow_mut().pop_front() {
None => {
- panic!("Unexpected block connected: {:?}", header.block_hash());
+ panic!("Unexpected block connected: {:?}", block.block_hash());
+ },
+ Some(expected_block) => {
+ assert_eq!(block.block_hash(), expected_block.header.block_hash());
+ assert_eq!(height, expected_block.height);
+ },
+ }
+ }
+
+ fn filtered_block_connected(&self, header: &BlockHeader, _txdata: &chain::transaction::TransactionData, height: u32) {
+ match self.expected_filtered_blocks_connected.borrow_mut().pop_front() {
+ None => {
+ panic!("Unexpected filtered block connected: {:?}", header.block_hash());
},
Some(expected_block) => {
assert_eq!(header.block_hash(), expected_block.header.block_hash());
panic!("Expected blocks connected: {:?}", expected_blocks_connected);
}
+ let expected_filtered_blocks_connected = self.expected_filtered_blocks_connected.borrow();
+ if !expected_filtered_blocks_connected.is_empty() {
+ panic!("Expected filtered_blocks connected: {:?}", expected_filtered_blocks_connected);
+ }
+
let expected_blocks_disconnected = self.expected_blocks_disconnected.borrow();
if !expected_blocks_disconnected.is_empty() {
panic!("Expected blocks disconnected: {:?}", expected_blocks_disconnected);
[package]
name = "lightning-invoice"
description = "Data structures to parse and serialize BOLT11 lightning invoices"
-version = "0.18.0"
+version = "0.19.0"
authors = ["Sebastian Geisler <sgeisler@wh2.tu-dresden.de>"]
documentation = "https://docs.rs/lightning-invoice/"
license = "MIT OR Apache-2.0"
[dependencies]
bech32 = { version = "0.9.0", default-features = false }
-lightning = { version = "0.0.110", path = "../lightning", default-features = false }
+lightning = { version = "0.0.111", path = "../lightning", default-features = false }
secp256k1 = { version = "0.24.0", default-features = false, features = ["recovery", "alloc"] }
num-traits = { version = "0.2.8", default-features = false }
bitcoin_hashes = { version = "0.11", default-features = false }
serde = { version = "1.0.118", optional = true }
[dev-dependencies]
-lightning = { version = "0.0.110", path = "../lightning", default-features = false, features = ["_test_utils"] }
+lightning = { version = "0.0.111", path = "../lightning", default-features = false, features = ["_test_utils"] }
hex = "0.4"
serde_json = { version = "1"}
}
/// The hash of the `RawInvoice` that was signed.
- pub fn hash(&self) -> &[u8; 32] {
+ pub fn signable_hash(&self) -> &[u8; 32] {
&self.hash
}
hash
}
- /// Calculate the hash of the encoded `RawInvoice`
- pub fn hash(&self) -> [u8; 32] {
+ /// Calculate the hash of the encoded `RawInvoice` which should be signed.
+ pub fn signable_hash(&self) -> [u8; 32] {
use bech32::ToBase32;
RawInvoice::hash_from_parts(
pub fn sign<F, E>(self, sign_method: F) -> Result<SignedRawInvoice, E>
where F: FnOnce(&Message) -> Result<RecoverableSignature, E>
{
- let raw_hash = self.hash();
+ let raw_hash = self.signable_hash();
let hash = Message::from_slice(&raw_hash[..])
.expect("Hash is 32 bytes long, same as MESSAGE_SIZE");
let signature = sign_method(&hash)?;
0xd5, 0x18, 0xe1, 0xc9
];
- assert_eq!(invoice.hash(), expected_hash)
+ assert_eq!(invoice.signable_hash(), expected_hash)
}
#[test]
}.unwrap();
assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::InvalidFeatures));
+ let mut payment_secret_features = InvoiceFeatures::empty();
+ payment_secret_features.set_payment_secret_required();
+
// Including payment secret and feature bits
let invoice = {
let mut invoice = invoice_template.clone();
invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into());
- invoice.data.tagged_fields.push(Features(InvoiceFeatures::known()).into());
+ invoice.data.tagged_fields.push(Features(payment_secret_features.clone()).into());
invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
}.unwrap();
assert!(Invoice::from_signed(invoice).is_ok());
// Missing payment secret
let invoice = {
let mut invoice = invoice_template.clone();
- invoice.data.tagged_fields.push(Features(InvoiceFeatures::known()).into());
+ invoice.data.tagged_fields.push(Features(payment_secret_features).into());
invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
}.unwrap();
assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::NoPaymentSecret));
);
assert_eq!(invoice.payment_hash(), &sha256::Hash::from_slice(&[21;32][..]).unwrap());
assert_eq!(invoice.payment_secret(), &PaymentSecret([42; 32]));
- assert_eq!(invoice.features(), Some(&InvoiceFeatures::known()));
+
+ let mut expected_features = InvoiceFeatures::empty();
+ expected_features.set_variable_length_onion_required();
+ expected_features.set_payment_secret_required();
+ expected_features.set_basic_mpp_optional();
+ assert_eq!(invoice.features(), Some(&expected_features));
let raw_invoice = builder.build_raw().unwrap();
assert_eq!(raw_invoice, *invoice.into_signed_raw().raw_invoice())
match event {
Event::PaymentPathFailed {
- payment_id, payment_hash, rejected_by_dest, path, short_channel_id, retry, ..
+ payment_id, payment_hash, payment_failed_permanently, path, short_channel_id, retry, ..
} => {
if let Some(short_channel_id) = short_channel_id {
let path = path.iter().collect::<Vec<_>>();
if payment_id.is_none() {
log_trace!(self.logger, "Payment {} has no id; not retrying", log_bytes!(payment_hash.0));
- } else if *rejected_by_dest {
+ } else if *payment_failed_permanently {
log_trace!(self.logger, "Payment {} rejected by destination; not retrying", log_bytes!(payment_hash.0));
self.payer.abandon_payment(payment_id.unwrap());
} else if retry.is_none() {
use utils::{ScorerAccountingForInFlightHtlcs, create_invoice_from_channelmanager_and_duration_since_epoch};
use bitcoin_hashes::sha256::Hash as Sha256;
use lightning::ln::PaymentPreimage;
- use lightning::ln::features::{ChannelFeatures, NodeFeatures, InitFeatures};
+ use lightning::ln::channelmanager;
+ use lightning::ln::features::{ChannelFeatures, NodeFeatures};
use lightning::ln::functional_test_utils::*;
use lightning::ln::msgs::{ChannelMessageHandler, ErrorAction, LightningError};
use lightning::routing::gossip::{EffectiveCapacity, NodeId};
payment_id,
payment_hash,
network_update: None,
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: false,
path: TestRouter::path_for_value(final_value_msat),
short_channel_id: None,
payment_id,
payment_hash,
network_update: None,
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: false,
path: TestRouter::path_for_value(final_value_msat),
short_channel_id: None,
payment_id,
payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
network_update: None,
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: true,
path: TestRouter::path_for_value(final_value_msat),
short_channel_id: None,
payment_id,
payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
network_update: None,
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: false,
path: TestRouter::path_for_value(final_value_msat / 2),
short_channel_id: None,
payment_id,
payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
network_update: None,
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: true,
path: TestRouter::path_for_value(final_value_msat),
short_channel_id: None,
payment_id,
payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
network_update: None,
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: false,
path: vec![],
short_channel_id: None,
payment_id,
payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
network_update: None,
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: false,
path: vec![],
short_channel_id: None,
payment_id,
payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
network_update: None,
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: false,
path: TestRouter::path_for_value(final_value_msat / 2),
short_channel_id: None,
payment_id,
payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
network_update: None,
- rejected_by_dest: true,
+ payment_failed_permanently: true,
all_paths_failed: false,
path: vec![],
short_channel_id: None,
payment_id,
payment_hash,
network_update: None,
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: false,
path: vec![],
short_channel_id: None,
payment_id,
payment_hash,
network_update: None,
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: false,
path: vec![],
short_channel_id: None,
payment_id,
payment_hash,
network_update: None,
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: false,
path,
short_channel_id,
payment_id,
payment_hash,
network_update: None,
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: false,
path: TestRouter::path_for_value(final_value_msat),
short_channel_id: None,
payment_id,
payment_hash,
network_update: None,
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: false,
path: TestRouter::path_for_value(final_value_msat / 2),
short_channel_id: None,
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let chans = nodes[0].node.list_usable_channels();
let mut route = Route {
paths: vec![
vec![RouteHop {
pubkey: nodes[1].node.get_our_node_id(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: chans[0].short_channel_id.unwrap(),
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: 10_000,
cltv_expiry_delta: 100,
}],
vec![RouteHop {
pubkey: nodes[1].node.get_our_node_id(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: chans[1].short_channel_id.unwrap(),
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: 100_000_001, // Our default max-HTLC-value is 10% of the channel value, which this is one more than
cltv_expiry_delta: 100,
}],
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let chans = nodes[0].node.list_usable_channels();
let mut route = Route {
paths: vec![
vec![RouteHop {
pubkey: nodes[1].node.get_our_node_id(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: chans[0].short_channel_id.unwrap(),
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: 100_000_001, // Our default max-HTLC-value is 10% of the channel value, which this is one more than
cltv_expiry_delta: 100,
}],
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_1_scid = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
- let chan_2_scid = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 10_000_000, 0, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+ let chan_1_scid = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
+ let chan_2_scid = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 10_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
let mut route = Route {
paths: vec![
vec![RouteHop {
pubkey: nodes[1].node.get_our_node_id(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: chan_1_scid,
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: 0,
cltv_expiry_delta: 100,
}, RouteHop {
pubkey: nodes[2].node.get_our_node_id(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: chan_2_scid,
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: 100_000_000,
cltv_expiry_delta: 100,
}],
vec![RouteHop {
pubkey: nodes[1].node.get_our_node_id(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: chan_1_scid,
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: 0,
cltv_expiry_delta: 100,
}, RouteHop {
pubkey: nodes[2].node.get_our_node_id(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: chan_2_scid,
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: 100_000_000,
cltv_expiry_delta: 100,
}]
// treated this as "HTLC complete" and dropped the retry counter, causing us to retry again
// if the final HTLC failed.
expected_events.borrow_mut().push_back(&|ev: &Event| {
- if let Event::PaymentPathFailed { rejected_by_dest, all_paths_failed, .. } = ev {
- assert!(!rejected_by_dest);
+ if let Event::PaymentPathFailed { payment_failed_permanently, all_paths_failed, .. } = ev {
+ assert!(!payment_failed_permanently);
assert!(all_paths_failed);
} else { panic!("Unexpected event"); }
});
commitment_signed_dance!(nodes[0], nodes[1], &bs_fail_update.commitment_signed, false, true);
expected_events.borrow_mut().push_back(&|ev: &Event| {
- if let Event::PaymentPathFailed { rejected_by_dest, all_paths_failed, .. } = ev {
- assert!(!rejected_by_dest);
+ if let Event::PaymentPathFailed { payment_failed_permanently, all_paths_failed, .. } = ev {
+ assert!(!payment_failed_permanently);
assert!(all_paths_failed);
} else { panic!("Unexpected event"); }
});
use bitcoin_hashes::sha256::Hash as Sha256;
use lightning::chain::keysinterface::PhantomKeysManager;
use lightning::ln::{PaymentPreimage, PaymentHash};
- use lightning::ln::channelmanager::{PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY};
+ use lightning::ln::channelmanager::{self, PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY};
use lightning::ln::functional_test_utils::*;
- use lightning::ln::features::InitFeatures;
use lightning::ln::msgs::ChannelMessageHandler;
use lightning::routing::router::{PaymentParameters, RouteParameters, find_route};
use lightning::util::enforcing_trait_impls::EnforcingSigner;
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);
- create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let non_default_invoice_expiry_secs = 4200;
let invoice = create_invoice_from_channelmanager_and_duration_since_epoch(
&nodes[1].node, nodes[1].keys_manager, Currency::BitcoinTestnet, Some(10_000), "test".to_string(),
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_1_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001, InitFeatures::known(), InitFeatures::known());
- let chan_2_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 2, 0, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_1_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 2, 0, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let mut scid_aliases = HashSet::new();
scid_aliases.insert(chan_1_0.0.short_channel_id_alias.unwrap());
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_1_0_low_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100_000, 0, InitFeatures::known(), InitFeatures::known());
- let chan_1_0_high_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 10_000_000, 0, InitFeatures::known(), InitFeatures::known());
- let _chan_1_0_medium_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
+ let _chan_1_0_low_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_1_0_high_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 10_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let _chan_1_0_medium_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let mut scid_aliases = HashSet::new();
scid_aliases.insert(chan_1_0_high_inbound_capacity.0.short_channel_id_alias.unwrap());
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_1_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_1_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Create an unannonced channel between `nodes[2]` and `nodes[0]`, for which the
// `msgs::ChannelUpdate` is never handled for the node(s). As the `msgs::ChannelUpdate`
private_chan_cfg.channel_handshake_config.announced_channel = false;
let temporary_channel_id = nodes[2].node.create_channel(nodes[0].node.get_our_node_id(), 1_000_000, 500_000_000, 42, Some(private_chan_cfg)).unwrap();
let open_channel = get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_open_channel(&nodes[2].node.get_our_node_id(), InitFeatures::known(), &open_channel);
+ nodes[0].node.handle_open_channel(&nodes[2].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
let accept_channel = get_event_msg!(nodes[0], MessageSendEvent::SendAcceptChannel, nodes[2].node.get_our_node_id());
- nodes[2].node.handle_accept_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
+ nodes[2].node.handle_accept_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel);
let tx = sign_funding_transaction(&nodes[2], &nodes[0], 1_000_000, temporary_channel_id);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let _chan_1_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let _chan_1_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
- let chan_2_0 = create_announced_chan_between_nodes_with_value(&nodes, 2, 0, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_2_0 = create_announced_chan_between_nodes_with_value(&nodes, 2, 0, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[2].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_2_0.1);
nodes[0].node.handle_channel_update(&nodes[2].node.get_our_node_id(), &chan_2_0.0);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_1_0 = create_announced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_1_0 = create_announced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &chan_1_0.0);
nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_1_0.1);
- let chan_2_0 = create_announced_chan_between_nodes_with_value(&nodes, 2, 0, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_2_0 = create_announced_chan_between_nodes_with_value(&nodes, 2, 0, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[2].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_2_0.1);
nodes[0].node.handle_channel_update(&nodes[2].node.get_our_node_id(), &chan_2_0.0);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_1_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100_000, 0, InitFeatures::known(), InitFeatures::known());
- let chan_2_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 2, 0, 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
+ let chan_1_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 2, 0, 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// As the invoice amt is 1 msat above chan_1_0's inbound capacity, it shouldn't be included
let mut scid_aliases_99_000_001_msat = HashSet::new();
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_0_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_0_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &chan_0_1.1);
nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_1.0);
- let chan_0_2 = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_0_2 = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[0].node.handle_channel_update(&nodes[2].node.get_our_node_id(), &chan_0_2.1);
nodes[2].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_2.0);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
- create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_amt = 20_000;
let (payment_hash, _payment_secret) = nodes[1].node.create_inbound_payment(Some(payment_amt), 3600).unwrap();
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_0_1 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
- let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_0_1 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let mut scid_aliases = HashSet::new();
scid_aliases.insert(chan_0_1.0.short_channel_id_alias.unwrap());
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
- let chan_0_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 1000000, 10001, InitFeatures::known(), InitFeatures::known());
- let chan_1_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 3, 3_000_000, 10005, InitFeatures::known(), InitFeatures::known());
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_0_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 1000000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_1_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 3, 3_000_000, 10005, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let mut scid_aliases = HashSet::new();
scid_aliases.insert(chan_0_2.0.short_channel_id_alias.unwrap());
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
- let chan_0_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 1000000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_0_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 1000000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Create an unannonced channel between `nodes[1]` and `nodes[3]`, for which the
// `msgs::ChannelUpdate` is never handled for the node(s). As the `msgs::ChannelUpdate`
private_chan_cfg.channel_handshake_config.announced_channel = false;
let temporary_channel_id = nodes[1].node.create_channel(nodes[3].node.get_our_node_id(), 1_000_000, 500_000_000, 42, Some(private_chan_cfg)).unwrap();
let open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[3].node.get_our_node_id());
- nodes[3].node.handle_open_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &open_channel);
+ nodes[3].node.handle_open_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
let accept_channel = get_event_msg!(nodes[3], MessageSendEvent::SendAcceptChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_accept_channel(&nodes[3].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
+ nodes[1].node.handle_accept_channel(&nodes[3].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel);
let tx = sign_funding_transaction(&nodes[1], &nodes[3], 1_000_000, temporary_channel_id);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_0_1 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_0_1 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
- let chan_2_0 = create_announced_chan_between_nodes_with_value(&nodes, 2, 0, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_2_0 = create_announced_chan_between_nodes_with_value(&nodes, 2, 0, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[2].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_2_0.1);
nodes[0].node.handle_channel_update(&nodes[2].node.get_our_node_id(), &chan_2_0.0);
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- let chan_0_2 = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_0_2 = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[0].node.handle_channel_update(&nodes[2].node.get_our_node_id(), &chan_0_2.1);
nodes[2].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_2.0);
- let _chan_1_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let _chan_1_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
- let chan_0_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_0_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Hints should include `chan_0_3` from as `nodes[3]` only have private channels, and no
// channels for `nodes[2]` as it contains a mix of public and private channels.
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let _chan_0_1_low_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0, InitFeatures::known(), InitFeatures::known());
- let chan_0_1_high_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0, InitFeatures::known(), InitFeatures::known());
- let _chan_0_1_medium_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
- let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let _chan_0_1_low_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_0_1_high_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let _chan_0_1_medium_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let mut scid_aliases = HashSet::new();
scid_aliases.insert(chan_0_1_high_inbound_capacity.0.short_channel_id_alias.unwrap());
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
- let chan_0_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 100_000, 0, InitFeatures::known(), InitFeatures::known());
- let chan_1_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 3, 200_000, 0, InitFeatures::known(), InitFeatures::known());
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_0_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_1_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 3, 200_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Since the invoice 1 msat above chan_0_3's inbound capacity, it should be filtered out.
let mut scid_aliases_99_000_001_msat = HashSet::new();
[package]
name = "lightning-net-tokio"
-version = "0.0.110"
+version = "0.0.111"
authors = ["Matt Corallo"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/lightningdevkit/rust-lightning/"
[dependencies]
bitcoin = "0.29.0"
-lightning = { version = "0.0.110", path = "../lightning" }
+lightning = { version = "0.0.111", path = "../lightning" }
tokio = { version = "1.0", features = [ "io-util", "macros", "rt", "sync", "net", "time" ] }
[dev-dependencies]
use lightning::ln::features::*;
use lightning::ln::msgs::*;
use lightning::ln::peer_handler::{MessageHandler, PeerManager};
+ use lightning::ln::features::NodeFeatures;
use lightning::util::events::*;
use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey};
fn handle_channel_update(&self, _msg: &ChannelUpdate) -> Result<bool, LightningError> { Ok(false) }
fn get_next_channel_announcement(&self, _starting_point: u64) -> Option<(ChannelAnnouncement, Option<ChannelUpdate>, Option<ChannelUpdate>)> { None }
fn get_next_node_announcement(&self, _starting_point: Option<&PublicKey>) -> Option<NodeAnnouncement> { None }
- fn peer_connected(&self, _their_node_id: &PublicKey, _init_msg: &Init) { }
+ fn peer_connected(&self, _their_node_id: &PublicKey, _init_msg: &Init) -> Result<(), ()> { Ok(()) }
fn handle_reply_channel_range(&self, _their_node_id: &PublicKey, _msg: ReplyChannelRange) -> Result<(), LightningError> { Ok(()) }
fn handle_reply_short_channel_ids_end(&self, _their_node_id: &PublicKey, _msg: ReplyShortChannelIdsEnd) -> Result<(), LightningError> { Ok(()) }
fn handle_query_channel_range(&self, _their_node_id: &PublicKey, _msg: QueryChannelRange) -> Result<(), LightningError> { Ok(()) }
fn handle_query_short_channel_ids(&self, _their_node_id: &PublicKey, _msg: QueryShortChannelIds) -> Result<(), LightningError> { Ok(()) }
+ fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() }
+ fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { InitFeatures::empty() }
}
impl ChannelMessageHandler for MsgHandler {
fn handle_open_channel(&self, _their_node_id: &PublicKey, _their_features: InitFeatures, _msg: &OpenChannel) {}
self.pubkey_disconnected.clone().try_send(()).unwrap();
}
}
- fn peer_connected(&self, their_node_id: &PublicKey, _msg: &Init) {
+ fn peer_connected(&self, their_node_id: &PublicKey, _init_msg: &Init) -> Result<(), ()> {
if *their_node_id == self.expected_pubkey {
self.pubkey_connected.clone().try_send(()).unwrap();
}
+ Ok(())
}
fn handle_channel_reestablish(&self, _their_node_id: &PublicKey, _msg: &ChannelReestablish) {}
fn handle_error(&self, _their_node_id: &PublicKey, _msg: &ErrorMessage) {}
+ fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() }
+ fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { InitFeatures::empty() }
}
impl MessageSendEventsProvider for MsgHandler {
fn get_and_clear_pending_msg_events(&self) -> Vec<MessageSendEvent> {
chan_handler: Arc::clone(&a_handler),
route_handler: Arc::clone(&a_handler),
onion_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}),
- }, a_key.clone(), &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{})));
+ }, a_key.clone(), 0, &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{})));
let (b_connected_sender, mut b_connected) = mpsc::channel(1);
let (b_disconnected_sender, mut b_disconnected) = mpsc::channel(1);
chan_handler: Arc::clone(&b_handler),
route_handler: Arc::clone(&b_handler),
onion_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}),
- }, b_key.clone(), &[2; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{})));
+ }, b_key.clone(), 0, &[2; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{})));
// We bind on localhost, hoping the environment is properly configured with a local
// address. This may not always be the case in containers and the like, so if this test is
chan_handler: Arc::new(lightning::ln::peer_handler::ErroringMessageHandler::new()),
onion_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}),
route_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}),
- }, a_key, &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{})));
+ }, a_key, 0, &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{})));
// Make two connections, one for an inbound and one for an outbound connection
let conn_a = {
[package]
name = "lightning-persister"
-version = "0.0.110"
+version = "0.0.111"
authors = ["Valentine Wallace", "Matt Corallo"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/lightningdevkit/rust-lightning/"
[dependencies]
bitcoin = "0.29.0"
-lightning = { version = "0.0.110", path = "../lightning" }
+lightning = { version = "0.0.111", path = "../lightning" }
libc = "0.2"
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["winbase"] }
[dev-dependencies]
-lightning = { version = "0.0.110", path = "../lightning", features = ["_test_utils"] }
+lightning = { version = "0.0.111", path = "../lightning", features = ["_test_utils"] }
use lightning::chain::chainmonitor::Persist;
use lightning::chain::transaction::OutPoint;
use lightning::{check_closed_broadcast, check_closed_event, check_added_monitors};
- use lightning::ln::features::InitFeatures;
+ use lightning::ln::channelmanager;
use lightning::ln::functional_test_utils::*;
use lightning::util::events::{ClosureReason, MessageSendEventsProvider};
use lightning::util::test_utils;
}
// Create some initial channel and check that a channel was persisted.
- let _ = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let _ = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
check_persisted_data!(0);
// Send a few payments and make sure the monitors are updated to the latest.
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 chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()).unwrap();
check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed);
let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
let mut 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 chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()).unwrap();
check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed);
let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
[package]
name = "lightning-rapid-gossip-sync"
-version = "0.0.110"
+version = "0.0.111"
authors = ["Arik Sosman <git@arik.io>"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/lightningdevkit/rust-lightning"
"""
[features]
+default = ["std"]
+no-std = ["lightning/no-std"]
+std = ["lightning/std"]
_bench_unstable = []
[dependencies]
-lightning = { version = "0.0.110", path = "../lightning" }
+lightning = { version = "0.0.111", path = "../lightning" }
bitcoin = { version = "0.29.0", default-features = false }
[dev-dependencies]
-lightning = { version = "0.0.110", path = "../lightning", features = ["_test_utils"] }
+lightning = { version = "0.0.111", path = "../lightning", features = ["_test_utils"] }
#![deny(unused_mut)]
#![deny(unused_variables)]
#![deny(unused_imports)]
-//! This crate exposes functionality to rapidly sync gossip data, aimed primarily at mobile
+//! This crate exposes client functionality to rapidly sync gossip data, aimed primarily at mobile
//! devices.
//!
-//! The server sends a compressed response containing differential gossip data. The gossip data is
-//! formatted compactly, omitting signatures and opportunistically incremental where previous
-//! channel updates are known (a mechanism that is enabled when the timestamp of the last known
-//! channel update is communicated). A reference server implementation can be found
-//! [here](https://github.com/lightningdevkit/rapid-gossip-sync-server).
+//! The rapid gossip sync server will provide a compressed response containing differential gossip
+//! data. The gossip data is formatted compactly, omitting signatures and opportunistically
+//! incremental where previous channel updates are known. This mechanism is enabled when the
+//! timestamp of the last known channel update is communicated. A reference server implementation
+//! can be found [on Github](https://github.com/lightningdevkit/rapid-gossip-sync-server).
//!
-//! An example server request could look as simple as the following. Note that the first ever rapid
-//! sync should use `0` for `last_sync_timestamp`:
+//! The primary benefit of this syncing mechanism is that it allows a low-powered client to offload
+//! the validation of gossip signatures to a semi-trusted server. This enables the client to
+//! privately calculate routes for payments, and to do so much faster than requiring a full
+//! peer-to-peer gossip sync to complete.
+//!
+//! The server calculates its response on the basis of a client-provided `latest_seen` timestamp,
+//! i.e., the server will return all rapid gossip sync data it has seen after the given timestamp.
+//!
+//! # Getting Started
+//! Firstly, the data needs to be retrieved from the server. For example, you could use the server
+//! at <https://rapidsync.lightningdevkit.org> with the following request format:
//!
//! ```shell
//! curl -o rapid_sync.lngossip https://rapidsync.lightningdevkit.org/snapshot/<last_sync_timestamp>
//! ```
+//! Note that the first ever rapid sync should use `0` for `last_sync_timestamp`.
//!
-//! Then, call the network processing function. In this example, we process the update by reading
-//! its contents from disk, which we do by calling the `sync_network_graph_with_file_path` method:
+//! After the gossip data snapshot has been downloaded, one of the client's graph processing
+//! functions needs to be called. In this example, we process the update by reading its contents
+//! from disk, which we do by calling [sync_network_graph_with_file_path]:
//!
//! ```
//! use bitcoin::blockdata::constants::genesis_block;
//! let rapid_sync = RapidGossipSync::new(&network_graph);
//! let new_last_sync_timestamp_result = rapid_sync.sync_network_graph_with_file_path("./rapid_sync.lngossip");
//! ```
-//!
-//! The primary benefit this syncing mechanism provides is that given a trusted server, a
-//! low-powered client can offload the validation of gossip signatures. This enables a client to
-//! privately calculate routes for payments, and do so much faster and earlier than requiring a full
-//! peer-to-peer gossip sync to complete.
-//!
-//! The reason the rapid sync server requires trust is that it could provide bogus data, though at
-//! worst, all that would result in is a fake network topology, which wouldn't enable the server to
-//! steal or siphon off funds. It could, however, reduce the client's privacy by forcing all
-//! payments to be routed via channels the server controls.
-//!
-//! The way a server is meant to calculate this rapid gossip sync data is by using a `latest_seen`
-//! timestamp provided by the client. It's not included in either channel announcement or update,
-//! (not least due to announcements not including any timestamps at all, but only a block height)
-//! but rather, it's a timestamp of when the server saw a particular message.
+//! [sync_network_graph_with_file_path]: RapidGossipSync::sync_network_graph_with_file_path
// Allow and import test features for benching
#![cfg_attr(all(test, feature = "_bench_unstable"), feature(test))]
#[cfg(all(test, feature = "_bench_unstable"))]
extern crate test;
+#[cfg(feature = "std")]
use std::fs::File;
-use std::ops::Deref;
-use std::sync::atomic::{AtomicBool, Ordering};
+use core::ops::Deref;
+use core::sync::atomic::{AtomicBool, Ordering};
+use lightning::io;
use lightning::routing::gossip::NetworkGraph;
use lightning::util::logger::Logger;
-use crate::error::GraphSyncError;
+pub use crate::error::GraphSyncError;
/// Error types that these functions can return
-pub mod error;
+mod error;
/// Core functionality of this crate
-pub mod processing;
+mod processing;
-/// Rapid Gossip Sync struct
+/// The main Rapid Gossip Sync object.
+///
/// See [crate-level documentation] for usage.
///
/// [crate-level documentation]: crate
}
impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L::Target: Logger {
- /// Instantiate a new [`RapidGossipSync`] instance
+ /// Instantiate a new [`RapidGossipSync`] instance.
pub fn new(network_graph: NG) -> Self {
Self {
network_graph,
}
}
- /// Sync gossip data from a file
+ /// Sync gossip data from a file.
/// Returns the last sync timestamp to be used the next time rapid sync data is queried.
///
/// `network_graph`: The network graph to apply the updates to
///
/// `sync_path`: Path to the file where the gossip update data is located
///
+ #[cfg(feature = "std")]
pub fn sync_network_graph_with_file_path(
&self,
sync_path: &str,
self.update_network_graph_from_byte_stream(&mut file)
}
+ /// Update network graph from binary data.
+ /// Returns the last sync timestamp to be used the next time rapid sync data is queried.
+ ///
+ /// `network_graph`: network graph to be updated
+ ///
+ /// `update_data`: `&[u8]` binary stream that comprises the update data
+ pub fn update_network_graph(&self, update_data: &[u8]) -> Result<u32, GraphSyncError> {
+ let mut read_cursor = io::Cursor::new(update_data);
+ self.update_network_graph_from_byte_stream(&mut read_cursor)
+ }
+
/// Gets a reference to the underlying [`NetworkGraph`] which was provided in
/// [`RapidGossipSync::new`].
///
&self.network_graph
}
- /// Returns whether a rapid gossip sync has completed at least once
+ /// Returns whether a rapid gossip sync has completed at least once.
pub fn is_initial_sync_complete(&self) -> bool {
self.is_initial_sync_complete.load(Ordering::Acquire)
}
-use std::cmp::max;
-use std::io;
-use std::io::Read;
-use std::ops::Deref;
-use std::sync::atomic::Ordering;
+use core::cmp::max;
+use core::ops::Deref;
+use core::sync::atomic::Ordering;
use bitcoin::BlockHash;
use bitcoin::secp256k1::PublicKey;
use lightning::routing::gossip::NetworkGraph;
use lightning::util::logger::Logger;
use lightning::util::ser::{BigSize, Readable};
+use lightning::io;
use crate::error::GraphSyncError;
use crate::RapidGossipSync;
const MAX_INITIAL_NODE_ID_VECTOR_CAPACITY: u32 = 50_000;
impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L::Target: Logger {
- /// Update network graph from binary data.
- /// Returns the last sync timestamp to be used the next time rapid sync data is queried.
- ///
- /// `network_graph`: network graph to be updated
- ///
- /// `update_data`: `&[u8]` binary stream that comprises the update data
- pub fn update_network_graph(&self, update_data: &[u8]) -> Result<u32, GraphSyncError> {
- let mut read_cursor = io::Cursor::new(update_data);
- self.update_network_graph_from_byte_stream(&mut read_cursor)
- }
-
-
- pub(crate) fn update_network_graph_from_byte_stream<R: Read>(
+ pub(crate) fn update_network_graph_from_byte_stream<R: io::Read>(
&self,
mut read_cursor: &mut R,
) -> Result<u32, GraphSyncError> {
[package]
name = "lightning"
-version = "0.0.110"
+version = "0.0.111"
authors = ["Matt Corallo"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/lightningdevkit/rust-lightning/"
use ::{get_htlc_update_msgs, get_local_commitment_txn, get_revoke_commit_msgs, get_route_and_payment_hash, unwrap_send_err};
use chain::{ChannelMonitorUpdateErr, Confirm, Watch};
use chain::channelmonitor::LATENCY_GRACE_PERIOD_BLOCKS;
- use ln::channelmanager::PaymentSendFailure;
- use ln::features::InitFeatures;
+ use ln::channelmanager::{self, PaymentSendFailure};
use ln::functional_test_utils::*;
use ln::msgs::ChannelMessageHandler;
use util::errors::APIError;
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);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Route two payments to be claimed at the same time.
let (payment_preimage_1, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let channel = create_announced_chan_between_nodes(
- &nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ &nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Get a route for later and rebalance the channel somewhat
send_payment(&nodes[0], &[&nodes[1]], 10_000_000);
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);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
chanmon_cfgs[0].persister.chain_sync_monitor_persistences.lock().unwrap().clear();
chanmon_cfgs[0].persister.set_update_ret(Err(ChannelMonitorUpdateErr::PermanentFailure));
use ln::{PaymentHash, PaymentPreimage};
use ln::msgs::DecodeError;
use ln::chan_utils;
-use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCType, ChannelTransactionParameters, HolderCommitmentTransaction};
+use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCClaim, ChannelTransactionParameters, HolderCommitmentTransaction};
use ln::channelmanager::HTLCSource;
use chain;
use chain::{BestBlock, WatchedOutput};
/// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY.
#[derive(PartialEq)]
struct IrrevocablyResolvedHTLC {
- commitment_tx_output_idx: u32,
+ commitment_tx_output_idx: Option<u32>,
/// The txid of the transaction which resolved the HTLC, this may be a commitment (if the HTLC
/// was not present in the confirmed commitment transaction), HTLC-Success, or HTLC-Timeout
/// transaction.
payment_preimage: Option<PaymentPreimage>,
}
-impl_writeable_tlv_based!(IrrevocablyResolvedHTLC, {
- (0, commitment_tx_output_idx, required),
- (1, resolving_txid, option),
- (2, payment_preimage, option),
-});
+// In LDK versions prior to 0.0.111 commitment_tx_output_idx was not Option-al and
+// IrrevocablyResolvedHTLC objects only existed for non-dust HTLCs. This was a bug, but to maintain
+// backwards compatibility we must ensure we always write out a commitment_tx_output_idx field,
+// using `u32::max_value()` as a sentinal to indicate the HTLC was dust.
+impl Writeable for IrrevocablyResolvedHTLC {
+ fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+ let mapped_commitment_tx_output_idx = self.commitment_tx_output_idx.unwrap_or(u32::max_value());
+ write_tlv_fields!(writer, {
+ (0, mapped_commitment_tx_output_idx, required),
+ (1, self.resolving_txid, option),
+ (2, self.payment_preimage, option),
+ });
+ Ok(())
+ }
+}
+
+impl Readable for IrrevocablyResolvedHTLC {
+ fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+ let mut mapped_commitment_tx_output_idx = 0;
+ let mut resolving_txid = None;
+ let mut payment_preimage = None;
+ read_tlv_fields!(reader, {
+ (0, mapped_commitment_tx_output_idx, required),
+ (1, resolving_txid, option),
+ (2, payment_preimage, option),
+ });
+ Ok(Self {
+ commitment_tx_output_idx: if mapped_commitment_tx_output_idx == u32::max_value() { None } else { Some(mapped_commitment_tx_output_idx) },
+ resolving_txid,
+ payment_preimage,
+ })
+ }
+}
/// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates
/// on-chain transactions to ensure no loss of funds occurs.
// of block connection between ChannelMonitors and the ChannelManager.
funding_spend_seen: bool,
+ /// Set to `Some` of the confirmed transaction spending the funding input of the channel after
+ /// reaching `ANTI_REORG_DELAY` confirmations.
funding_spend_confirmed: Option<Txid>,
+
confirmed_commitment_tx_counterparty_output: CommitmentTxCounterpartyOutputInfo,
/// The set of HTLCs which have been either claimed or failed on chain and have reached
/// the requisite confirmations on the claim/fail transaction (either ANTI_REORG_DELAY or the
}
}
let htlc_resolved = self.htlcs_resolved_on_chain.iter()
- .find(|v| if v.commitment_tx_output_idx == htlc_commitment_tx_output_idx {
+ .find(|v| if v.commitment_tx_output_idx == Some(htlc_commitment_tx_output_idx) {
debug_assert!(htlc_spend_txid_opt.is_none());
htlc_spend_txid_opt = v.resolving_txid;
true
/// confirmations on the claim transaction.
///
/// Note that for `ChannelMonitors` which track a channel which went on-chain with versions of
- /// LDK prior to 0.0.108, balances may not be fully captured if our counterparty broadcasted
+ /// LDK prior to 0.0.111, balances may not be fully captured if our counterparty broadcasted
/// a revoked state.
///
/// See [`Balance`] for additional details on the types of claimable balances which
macro_rules! walk_htlcs {
($holder_commitment: expr, $htlc_iter: expr) => {
for (htlc, source) in $htlc_iter {
- if us.htlcs_resolved_on_chain.iter().any(|v| Some(v.commitment_tx_output_idx) == htlc.transaction_output_index) {
+ if us.htlcs_resolved_on_chain.iter().any(|v| v.commitment_tx_output_idx == htlc.transaction_output_index) {
// We should assert that funding_spend_confirmed is_some() here, but we
// have some unit tests which violate HTLC transaction CSVs entirely and
// would fail.
let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript);
let txid = commitment_tx.txid();
let mut holder_transactions = vec![commitment_tx];
+ // When anchor outputs are present, the HTLC transactions are only valid once the commitment
+ // transaction confirms.
+ if self.onchain_tx_handler.opt_anchors() {
+ return holder_transactions;
+ }
for htlc in self.current_holder_commitment_tx.htlc_outputs.iter() {
if let Some(vout) = htlc.0.transaction_output_index {
let preimage = if !htlc.0.offered {
let commitment_tx = self.onchain_tx_handler.get_fully_signed_copy_holder_tx(&self.funding_redeemscript);
let txid = commitment_tx.txid();
let mut holder_transactions = vec![commitment_tx];
+ // When anchor outputs are present, the HTLC transactions are only final once the commitment
+ // transaction confirms due to the CSV 1 encumberance.
+ if self.onchain_tx_handler.opt_anchors() {
+ return holder_transactions;
+ }
for htlc in self.current_holder_commitment_tx.htlc_outputs.iter() {
if let Some(vout) = htlc.0.transaction_output_index {
let preimage = if !htlc.0.offered {
source: source.clone(),
htlc_value_satoshis,
}));
- if let Some(idx) = commitment_tx_output_idx {
- self.htlcs_resolved_on_chain.push(IrrevocablyResolvedHTLC {
- commitment_tx_output_idx: idx, resolving_txid: Some(entry.txid),
- payment_preimage: None,
- });
- }
+ self.htlcs_resolved_on_chain.push(IrrevocablyResolvedHTLC {
+ commitment_tx_output_idx, resolving_txid: Some(entry.txid),
+ payment_preimage: None,
+ });
},
OnchainEvent::MaturingOutput { descriptor } => {
log_debug!(logger, "Descriptor {} has got enough confirmations to be passed upstream", log_spendable!(descriptor));
},
OnchainEvent::HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } => {
self.htlcs_resolved_on_chain.push(IrrevocablyResolvedHTLC {
- commitment_tx_output_idx, resolving_txid: Some(entry.txid),
+ commitment_tx_output_idx: Some(commitment_tx_output_idx), resolving_txid: Some(entry.txid),
payment_preimage: preimage,
});
},
}
fn should_broadcast_holder_commitment_txn<L: Deref>(&self, logger: &L) -> bool where L::Target: Logger {
+ // There's no need to broadcast our commitment transaction if we've seen one confirmed (even
+ // with 1 confirmation) as it'll be rejected as duplicate/conflicting.
+ if self.funding_spend_confirmed.is_some() ||
+ self.onchain_events_awaiting_threshold_conf.iter().find(|event| match event.event {
+ OnchainEvent::FundingSpendConfirmation { .. } => true,
+ _ => false,
+ }).is_some()
+ {
+ return false;
+ }
// We need to consider all HTLCs which are:
// * in any unrevoked counterparty commitment transaction, as they could broadcast said
// transactions and we'd end up in a race, or
fn is_resolving_htlc_output<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) where L::Target: Logger {
'outer_loop: for input in &tx.input {
let mut payment_data = None;
- let witness_items = input.witness.len();
- let htlctype = input.witness.last().map(|w| w.len()).and_then(HTLCType::scriptlen_to_htlctype);
- let prev_last_witness_len = input.witness.second_to_last().map(|w| w.len()).unwrap_or(0);
- let revocation_sig_claim = (witness_items == 3 && htlctype == Some(HTLCType::OfferedHTLC) && prev_last_witness_len == 33)
- || (witness_items == 3 && htlctype == Some(HTLCType::AcceptedHTLC) && prev_last_witness_len == 33);
- let accepted_preimage_claim = witness_items == 5 && htlctype == Some(HTLCType::AcceptedHTLC)
- && input.witness.second_to_last().unwrap().len() == 32;
+ let htlc_claim = HTLCClaim::from_witness(&input.witness);
+ let revocation_sig_claim = htlc_claim == Some(HTLCClaim::Revocation);
+ let accepted_preimage_claim = htlc_claim == Some(HTLCClaim::AcceptedPreimage);
#[cfg(not(fuzzing))]
- let accepted_timeout_claim = witness_items == 3 && htlctype == Some(HTLCType::AcceptedHTLC) && !revocation_sig_claim;
- let offered_preimage_claim = witness_items == 3 && htlctype == Some(HTLCType::OfferedHTLC) &&
- !revocation_sig_claim && input.witness.second_to_last().unwrap().len() == 32;
-
+ let accepted_timeout_claim = htlc_claim == Some(HTLCClaim::AcceptedTimeout);
+ let offered_preimage_claim = htlc_claim == Some(HTLCClaim::OfferedPreimage);
#[cfg(not(fuzzing))]
- let offered_timeout_claim = witness_items == 5 && htlctype == Some(HTLCType::OfferedHTLC);
+ let offered_timeout_claim = htlc_claim == Some(HTLCClaim::OfferedTimeout);
let mut payment_preimage = PaymentPreimage([0; 32]);
- if accepted_preimage_claim {
- payment_preimage.0.copy_from_slice(input.witness.second_to_last().unwrap());
- } else if offered_preimage_claim {
+ if offered_preimage_claim || accepted_preimage_claim {
payment_preimage.0.copy_from_slice(input.witness.second_to_last().unwrap());
}
use ln::{PaymentPreimage, PaymentHash};
use ln::chan_utils;
use ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
- use ln::channelmanager::PaymentSendFailure;
- use ln::features::InitFeatures;
+ use ln::channelmanager::{self, PaymentSendFailure};
use ln::functional_test_utils::*;
use ln::script::ShutdownScript;
use util::errors::APIError;
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
let channel = create_announced_chan_between_nodes(
- &nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ &nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
create_announced_chan_between_nodes(
- &nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ &nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Rebalance somewhat
send_payment(&nodes[0], &[&nodes[1]], 10_000_000);
}
/// An error when accessing the chain via [`Access`].
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub enum AccessError {
/// The requested chain is unknown.
UnknownChain,
use util::crypto::sign;
pub(crate) const MAX_HTLCS: u16 = 483;
+pub(crate) const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
+pub(crate) const OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS: usize = 136;
+// The weight of `accepted_htlc_script` can vary in function of its CLTV argument value. We define a
+// range that encompasses both its non-anchors and anchors variants.
+pub(crate) const MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 136;
+pub(crate) const MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 143;
/// Gets the weight for an HTLC-Success transaction.
#[inline]
}
#[derive(PartialEq)]
-pub(crate) enum HTLCType {
- AcceptedHTLC,
- OfferedHTLC
+pub(crate) enum HTLCClaim {
+ OfferedTimeout,
+ OfferedPreimage,
+ AcceptedTimeout,
+ AcceptedPreimage,
+ Revocation,
}
-impl HTLCType {
- /// Check if a given tx witnessScript len matchs one of a pre-signed HTLC
- pub(crate) fn scriptlen_to_htlctype(witness_script_len: usize) -> Option<HTLCType> {
- if witness_script_len == 133 {
- Some(HTLCType::OfferedHTLC)
- } else if witness_script_len >= 136 && witness_script_len <= 139 {
- Some(HTLCType::AcceptedHTLC)
+impl HTLCClaim {
+ /// Check if a given input witness attempts to claim a HTLC.
+ pub(crate) fn from_witness(witness: &Witness) -> Option<Self> {
+ debug_assert_eq!(OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS, MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT);
+ if witness.len() < 2 {
+ return None;
+ }
+ let witness_script = witness.last().unwrap();
+ let second_to_last = witness.second_to_last().unwrap();
+ if witness_script.len() == OFFERED_HTLC_SCRIPT_WEIGHT {
+ if witness.len() == 3 && second_to_last.len() == 33 {
+ // <revocation sig> <revocationpubkey> <witness_script>
+ Some(Self::Revocation)
+ } else if witness.len() == 3 && second_to_last.len() == 32 {
+ // <remotehtlcsig> <payment_preimage> <witness_script>
+ Some(Self::OfferedPreimage)
+ } else if witness.len() == 5 && second_to_last.len() == 0 {
+ // 0 <remotehtlcsig> <localhtlcsig> <> <witness_script>
+ Some(Self::OfferedTimeout)
+ } else {
+ None
+ }
+ } else if witness_script.len() == OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS {
+ // It's possible for the weight of `offered_htlc_script` and `accepted_htlc_script` to
+ // match so we check for both here.
+ if witness.len() == 3 && second_to_last.len() == 33 {
+ // <revocation sig> <revocationpubkey> <witness_script>
+ Some(Self::Revocation)
+ } else if witness.len() == 3 && second_to_last.len() == 32 {
+ // <remotehtlcsig> <payment_preimage> <witness_script>
+ Some(Self::OfferedPreimage)
+ } else if witness.len() == 5 && second_to_last.len() == 0 {
+ // 0 <remotehtlcsig> <localhtlcsig> <> <witness_script>
+ Some(Self::OfferedTimeout)
+ } else if witness.len() == 3 && second_to_last.len() == 0 {
+ // <remotehtlcsig> <> <witness_script>
+ Some(Self::AcceptedTimeout)
+ } else if witness.len() == 5 && second_to_last.len() == 32 {
+ // 0 <remotehtlcsig> <localhtlcsig> <payment_preimage> <witness_script>
+ Some(Self::AcceptedPreimage)
+ } else {
+ None
+ }
+ } else if witness_script.len() > MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT &&
+ witness_script.len() <= MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT {
+ // Handle remaining range of ACCEPTED_HTLC_SCRIPT_WEIGHT.
+ if witness.len() == 3 && second_to_last.len() == 33 {
+ // <revocation sig> <revocationpubkey> <witness_script>
+ Some(Self::Revocation)
+ } else if witness.len() == 3 && second_to_last.len() == 0 {
+ // <remotehtlcsig> <> <witness_script>
+ Some(Self::AcceptedTimeout)
+ } else if witness.len() == 5 && second_to_last.len() == 32 {
+ // 0 <remotehtlcsig> <localhtlcsig> <payment_preimage> <witness_script>
+ Some(Self::AcceptedPreimage)
+ } else {
+ None
+ }
} else {
None
}
/// Derives a per-commitment-transaction revocation key from its constituent parts.
///
-/// Only the cheating participant owns a valid witness to propagate a revoked
+/// Only the cheating participant owns a valid witness to propagate a revoked
/// commitment transaction, thus per_commitment_secret always come from cheater
/// and revocation_base_secret always come from punisher, which is the broadcaster
/// of the transaction spending with this key knowledge.
/// the public equivalend of derive_private_revocation_key - using only public keys to derive a
/// public key instead of private keys.
///
-/// Only the cheating participant owns a valid witness to propagate a revoked
+/// Only the cheating participant owns a valid witness to propagate a revoked
/// commitment transaction, thus per_commitment_point always come from cheater
/// and revocation_base_point always come from punisher, which is the broadcaster
/// of the transaction spending with this key knowledge.
} else {
htlc_success_tx_weight(opt_anchors)
};
- let total_fee = feerate_per_kw as u64 * weight / 1000;
+ let output_value = if opt_anchors {
+ htlc.amount_msat / 1000
+ } else {
+ let total_fee = feerate_per_kw as u64 * weight / 1000;
+ htlc.amount_msat / 1000 - total_fee
+ };
let mut txouts: Vec<TxOut> = Vec::new();
txouts.push(TxOut {
script_pubkey: get_revokeable_redeemscript(revocation_key, contest_delay, broadcaster_delayed_payment_key).to_v0_p2wsh(),
- value: htlc.amount_msat / 1000 - total_fee //TODO: BOLT 3 does not specify if we should add amount_msat before dividing or if we should divide by 1000 before subtracting (as we do here)
+ value: output_value,
});
Transaction {
pub counterparty_parameters: Option<CounterpartyChannelTransactionParameters>,
/// The late-bound funding outpoint
pub funding_outpoint: Option<chain::transaction::OutPoint>,
- /// Are anchors used for this channel. Boolean is serialization backwards-compatible
+ /// Are anchors (zero fee HTLC transaction variant) used for this channel. Boolean is
+ /// serialization backwards-compatible.
pub opt_anchors: Option<()>
}
use chain::channelmonitor::{ANTI_REORG_DELAY, ChannelMonitor};
use chain::transaction::OutPoint;
use chain::{ChannelMonitorUpdateErr, Listen, Watch};
-use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure};
+use ln::channelmanager::{self, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure};
use ln::channel::AnnouncementSigsState;
-use ln::features::InitFeatures;
use ln::msgs;
use ln::msgs::{ChannelMessageHandler, RoutingMessageHandler};
use util::config::UserConfig;
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());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, payment_hash_1, _, payment_secret_1) = get_route_and_payment_hash!(&nodes[0], nodes[1], 1000000);
chanmon_cfgs[0].persister.set_update_ret(Err(ChannelMonitorUpdateErr::PermanentFailure));
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some initial channel
- let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let outpoint = OutPoint { txid: chan.3.txid(), index: 0 };
// Rebalance the network to generate htlc in the two directions
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 channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(&nodes[0], nodes[1], 1000000);
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 channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
let (payment_preimage_1, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
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::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
assert_eq!(reestablish_1.len(), 1);
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
assert_eq!(reestablish_2.len(), 1);
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
- nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
assert_eq!(reestablish_1.len(), 1);
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
assert_eq!(reestablish_2.len(), 1);
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 channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
let (route, our_payment_hash, payment_preimage, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
{
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 channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
let (route, our_payment_hash, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
{
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 channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
send_payment(&nodes[0], &[&nodes[1]], 5000000);
let (route, our_payment_hash_1, payment_preimage_1, our_payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Rebalance a bit so that we can send backwards from 2 to 1.
send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 5000000);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000);
commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false);
chanmon_cfgs[1].persister.set_update_ret(Err(ChannelMonitorUpdateErr::TemporaryFailure));
- nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
- let as_reestablish = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
- let bs_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
+ let as_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
+ let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
- nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
- assert!(as_reestablish == get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id()));
- assert!(bs_reestablish == get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id()));
+ assert_eq!(get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap(), as_reestablish);
+ assert_eq!(get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(), bs_reestablish);
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
assert_eq!(
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 channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[1]);
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 channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
// Forward a payment for B to claim
let (payment_preimage_1, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
check_added_monitors!(nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
- nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
- let as_reconnect = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
- let bs_reconnect = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
+ let as_reconnect = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
+ let bs_reconnect = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reconnect);
let _as_channel_update = get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
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 channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
{
let mut lock;
get_channel_ref!(nodes[0], lock, channel_id).announcement_sigs_state = AnnouncementSigsState::PeerReceived;
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::empty(), remote_network_address: None });
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
- let as_reconnect = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
- let bs_reconnect = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
+ let as_reconnect = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
+ let bs_reconnect = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &as_reconnect);
let _bs_channel_update = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id());
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 channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
// Route the first payment outbound, holding the last RAA for B until we are set up so that we
// can deliver it and fail the monitor update.
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Rebalance a bit so that we can send backwards from 3 to 2.
send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 5000000);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Rebalance a bit so that we can send backwards from 3 to 1.
send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 5000000);
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 2);
- if let Event::PaymentPathFailed { payment_hash, rejected_by_dest, .. } = events[0] {
+ if let Event::PaymentPathFailed { payment_hash, payment_failed_permanently, .. } = events[0] {
assert_eq!(payment_hash, payment_hash_1);
- assert!(rejected_by_dest);
+ assert!(payment_failed_permanently);
} else { panic!("Unexpected event!"); }
match events[1] {
Event::PendingHTLCsForwardable { .. } => { },
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 channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
// Forward a payment for B to claim
let (payment_preimage_1, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 43, None).unwrap();
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()));
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()));
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
let (temporary_channel_id, funding_tx, funding_output) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 43);
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
- let (chan_2_ann, _, chan_2_id, _) = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::known(), InitFeatures::known());
- let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
- let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+ let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
+ let (chan_2_ann, _, chan_2_id, _) = create_announced_chan_between_nodes(&nodes, 0, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
+ let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[3], 100000);
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());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
send_payment(&nodes[0], &[&nodes[1]], 100_000_00);
let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[1], nodes[0], 1_000_000);
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(), remote_network_address: None });
- 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(), remote_network_address: None });
- let bs_connect_msg = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let as_connect_msg = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let bs_connect_msg = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
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();
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_id_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known()).2;
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_id_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 2000);
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());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
send_payment(&nodes[0], &[&nodes[1]], 1000);
{
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(), remote_network_address: None });
- 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(), remote_network_address: None });
- let bs_connect_msg = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let as_connect_msg = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let bs_connect_msg = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
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());
let nodes_0_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let chan_id = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 15_000_000, 7_000_000_000, InitFeatures::known(), InitFeatures::known()).2;
+ let chan_id = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 15_000_000, 7_000_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(&nodes[0], nodes[1], 100000);
let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(&nodes[1]);
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
// Now reconnect the two
- nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
assert_eq!(reestablish_1.len(), 1);
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
assert_eq!(reestablish_2.len(), 1);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_id_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known()).2;
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_id_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config), Some(config)]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let (_, _, channel_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let (_, _, channel_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
chanmon_cfgs[0].persister.set_update_ret(Err(ChannelMonitorUpdateErr::TemporaryFailure));
chanmon_cfgs[1].persister.set_update_ret(Err(ChannelMonitorUpdateErr::TemporaryFailure));
nodes[0].node.close_channel(&channel_id, &nodes[1].node.get_our_node_id()).unwrap();
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()));
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()));
check_added_monitors!(nodes[1], 1);
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()));
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()));
check_added_monitors!(nodes[0], 1);
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config), None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
chanmon_cfgs[0].persister.set_update_ret(Err(ChannelMonitorUpdateErr::PermanentFailure));
assert!(nodes[0].node.close_channel(&channel_id, &nodes[1].node.get_our_node_id()).is_ok());
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(config)]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
chanmon_cfgs[1].persister.set_update_ret(Err(ChannelMonitorUpdateErr::PermanentFailure));
assert!(nodes[0].node.close_channel(&channel_id, &nodes[1].node.get_our_node_id()).is_ok());
let shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &shutdown);
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &shutdown);
check_closed_broadcast!(nodes[1], true);
check_added_monitors!(nodes[1], 2);
check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "ChannelMonitor storage failure".to_string() });
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let (_, _, channel_id, _) = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let (_, _, channel_id, _) = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage_1, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
let (payment_preimage_2, payment_hash_2, _) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
use bitcoin::secp256k1;
use ln::{PaymentPreimage, PaymentHash};
-use ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures};
+use ln::features::{ChannelTypeFeatures, InitFeatures};
use ln::msgs;
use ln::msgs::{DecodeError, OptionalField, DataLossProtect};
use ln::script::{self, ShutdownScript};
-use ln::channelmanager::{CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
+use ln::channelmanager::{self, CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
use ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, htlc_success_tx_weight, htlc_timeout_tx_weight, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, ClosingTransaction};
use ln::chan_utils;
use chain::BestBlock;
($htlc: expr, $outbound: expr, $source: expr, $state_name: expr) => {
if $outbound == local { // "offered HTLC output"
let htlc_in_tx = get_htlc_in_commitment!($htlc, true);
- if $htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + (feerate_per_kw as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) {
+ let htlc_tx_fee = if self.opt_anchors() {
+ 0
+ } else {
+ feerate_per_kw as u64 * htlc_timeout_tx_weight(false) / 1000
+ };
+ if $htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + htlc_tx_fee {
log_trace!(logger, " ...including {} {} HTLC {} (hash {}) with value {}", if $outbound { "outbound" } else { "inbound" }, $state_name, $htlc.htlc_id, log_bytes!($htlc.payment_hash.0), $htlc.amount_msat);
included_non_dust_htlcs.push((htlc_in_tx, $source));
} else {
}
} else {
let htlc_in_tx = get_htlc_in_commitment!($htlc, false);
- if $htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + (feerate_per_kw as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) {
+ let htlc_tx_fee = if self.opt_anchors() {
+ 0
+ } else {
+ feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000
+ };
+ if $htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + htlc_tx_fee {
log_trace!(logger, " ...including {} {} HTLC {} (hash {}) with value {}", if $outbound { "outbound" } else { "inbound" }, $state_name, $htlc.htlc_id, log_bytes!($htlc.payment_hash.0), $htlc.amount_msat);
included_non_dust_htlcs.push((htlc_in_tx, $source));
} else {
on_holder_tx_holding_cell_htlcs_count: 0,
};
- let counterparty_dust_limit_timeout_sat = (self.get_dust_buffer_feerate(outbound_feerate_update) as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) + self.counterparty_dust_limit_satoshis;
- let holder_dust_limit_success_sat = (self.get_dust_buffer_feerate(outbound_feerate_update) as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) + self.holder_dust_limit_satoshis;
+ let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.opt_anchors() {
+ (0, 0)
+ } else {
+ let dust_buffer_feerate = self.get_dust_buffer_feerate(outbound_feerate_update) as u64;
+ (dust_buffer_feerate * htlc_timeout_tx_weight(false) / 1000,
+ dust_buffer_feerate * htlc_success_tx_weight(false) / 1000)
+ };
+ let counterparty_dust_limit_timeout_sat = htlc_timeout_dust_limit + self.counterparty_dust_limit_satoshis;
+ let holder_dust_limit_success_sat = htlc_success_dust_limit + self.holder_dust_limit_satoshis;
for ref htlc in self.pending_inbound_htlcs.iter() {
stats.pending_htlcs_value_msat += htlc.amount_msat;
if htlc.amount_msat / 1000 < counterparty_dust_limit_timeout_sat {
on_holder_tx_holding_cell_htlcs_count: 0,
};
- let counterparty_dust_limit_success_sat = (self.get_dust_buffer_feerate(outbound_feerate_update) as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) + self.counterparty_dust_limit_satoshis;
- let holder_dust_limit_timeout_sat = (self.get_dust_buffer_feerate(outbound_feerate_update) as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) + self.holder_dust_limit_satoshis;
+ let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.opt_anchors() {
+ (0, 0)
+ } else {
+ let dust_buffer_feerate = self.get_dust_buffer_feerate(outbound_feerate_update) as u64;
+ (dust_buffer_feerate * htlc_timeout_tx_weight(false) / 1000,
+ dust_buffer_feerate * htlc_success_tx_weight(false) / 1000)
+ };
+ let counterparty_dust_limit_success_sat = htlc_success_dust_limit + self.counterparty_dust_limit_satoshis;
+ let holder_dust_limit_timeout_sat = htlc_timeout_dust_limit + self.holder_dust_limit_satoshis;
for ref htlc in self.pending_outbound_htlcs.iter() {
stats.pending_htlcs_value_msat += htlc.amount_msat;
if htlc.amount_msat / 1000 < counterparty_dust_limit_success_sat {
fn next_local_commit_tx_fee_msat(&self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>) -> u64 {
assert!(self.is_outbound());
- let real_dust_limit_success_sat = (self.feerate_per_kw as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) + self.holder_dust_limit_satoshis;
- let real_dust_limit_timeout_sat = (self.feerate_per_kw as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) + self.holder_dust_limit_satoshis;
+ let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if self.opt_anchors() {
+ (0, 0)
+ } else {
+ (self.feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000,
+ self.feerate_per_kw as u64 * htlc_timeout_tx_weight(false) / 1000)
+ };
+ let real_dust_limit_success_sat = htlc_success_dust_limit + self.holder_dust_limit_satoshis;
+ let real_dust_limit_timeout_sat = htlc_timeout_dust_limit + self.holder_dust_limit_satoshis;
let mut addl_htlcs = 0;
if fee_spike_buffer_htlc.is_some() { addl_htlcs += 1; }
fn next_remote_commit_tx_fee_msat(&self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>) -> u64 {
assert!(!self.is_outbound());
- let real_dust_limit_success_sat = (self.feerate_per_kw as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) + self.counterparty_dust_limit_satoshis;
- let real_dust_limit_timeout_sat = (self.feerate_per_kw as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) + self.counterparty_dust_limit_satoshis;
+ let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if self.opt_anchors() {
+ (0, 0)
+ } else {
+ (self.feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000,
+ self.feerate_per_kw as u64 * htlc_timeout_tx_weight(false) / 1000)
+ };
+ let real_dust_limit_success_sat = htlc_success_dust_limit + self.counterparty_dust_limit_satoshis;
+ let real_dust_limit_timeout_sat = htlc_timeout_dust_limit + self.counterparty_dust_limit_satoshis;
let mut addl_htlcs = 0;
if fee_spike_buffer_htlc.is_some() { addl_htlcs += 1; }
}
}
- let exposure_dust_limit_timeout_sats = (self.get_dust_buffer_feerate(None) as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) + self.counterparty_dust_limit_satoshis;
+ let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.opt_anchors() {
+ (0, 0)
+ } else {
+ let dust_buffer_feerate = self.get_dust_buffer_feerate(None) as u64;
+ (dust_buffer_feerate * htlc_timeout_tx_weight(false) / 1000,
+ dust_buffer_feerate * htlc_success_tx_weight(false) / 1000)
+ };
+ let exposure_dust_limit_timeout_sats = htlc_timeout_dust_limit + self.counterparty_dust_limit_satoshis;
if msg.amount_msat / 1000 < exposure_dust_limit_timeout_sats {
let on_counterparty_tx_dust_htlc_exposure_msat = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat + msg.amount_msat;
if on_counterparty_tx_dust_htlc_exposure_msat > self.get_max_dust_htlc_exposure_msat() {
}
}
- let exposure_dust_limit_success_sats = (self.get_dust_buffer_feerate(None) as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) + self.holder_dust_limit_satoshis;
+ let exposure_dust_limit_success_sats = htlc_success_dust_limit + self.holder_dust_limit_satoshis;
if msg.amount_msat / 1000 < exposure_dust_limit_success_sats {
let on_holder_tx_dust_htlc_exposure_msat = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat + msg.amount_msat;
if on_holder_tx_dust_htlc_exposure_msat > self.get_max_dust_htlc_exposure_msat() {
return;
}
+ if self.channel_state & (ChannelState::PeerDisconnected as u32) == (ChannelState::PeerDisconnected as u32) {
+ // While the below code should be idempotent, it's simpler to just return early, as
+ // redundant disconnect events can fire, though they should be rare.
+ return;
+ }
+
if self.announcement_sigs_state == AnnouncementSigsState::MessageSent || self.announcement_sigs_state == AnnouncementSigsState::Committed {
self.announcement_sigs_state = AnnouncementSigsState::NotSent;
}
}
fn check_get_channel_ready(&mut self, height: u32) -> Option<msgs::ChannelReady> {
+ // Called:
+ // * always when a new block/transactions are confirmed with the new height
+ // * when funding is signed with a height of 0
if self.funding_tx_confirmation_height == 0 && self.minimum_depth != Some(0) {
return None;
}
// We got a reorg but not enough to trigger a force close, just ignore.
false
} else {
- if self.channel_state < ChannelState::ChannelFunded as u32 {
+ if self.funding_tx_confirmation_height != 0 && self.channel_state < ChannelState::ChannelFunded as u32 {
// We should never see a funding transaction on-chain until we've received
// funding_signed (if we're an outbound channel), or seen funding_generated (if we're
// an inbound channel - before that we have no known funding TXID). The fuzzer,
let were_node_one = node_id.serialize()[..] < self.counterparty_node_id.serialize()[..];
let msg = msgs::UnsignedChannelAnnouncement {
- features: ChannelFeatures::known(),
+ features: channelmanager::provided_channel_features(),
chain_hash,
short_channel_id: self.get_short_channel_id().unwrap(),
node_id_1: if were_node_one { node_id } else { self.get_counterparty_node_id() },
}
}
- let exposure_dust_limit_success_sats = (self.get_dust_buffer_feerate(None) as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) + self.counterparty_dust_limit_satoshis;
+ let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if self.opt_anchors() {
+ (0, 0)
+ } else {
+ let dust_buffer_feerate = self.get_dust_buffer_feerate(None) as u64;
+ (dust_buffer_feerate * htlc_success_tx_weight(false) / 1000,
+ dust_buffer_feerate * htlc_timeout_tx_weight(false) / 1000)
+ };
+ let exposure_dust_limit_success_sats = htlc_success_dust_limit + self.counterparty_dust_limit_satoshis;
if amount_msat / 1000 < exposure_dust_limit_success_sats {
let on_counterparty_dust_htlc_exposure_msat = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat + amount_msat;
if on_counterparty_dust_htlc_exposure_msat > self.get_max_dust_htlc_exposure_msat() {
}
}
- let exposure_dust_limit_timeout_sats = (self.get_dust_buffer_feerate(None) as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) + self.holder_dust_limit_satoshis;
+ let exposure_dust_limit_timeout_sats = htlc_timeout_dust_limit + self.holder_dust_limit_satoshis;
if amount_msat / 1000 < exposure_dust_limit_timeout_sats {
let on_holder_dust_htlc_exposure_msat = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat + amount_msat;
if on_holder_dust_htlc_exposure_msat > self.get_max_dust_htlc_exposure_msat() {
use bitcoin::network::constants::Network;
use hex;
use ln::PaymentHash;
- use ln::channelmanager::{HTLCSource, PaymentId};
+ use ln::channelmanager::{self, HTLCSource, PaymentId};
use ln::channel::{Channel, InboundHTLCOutput, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator};
use ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
- use ln::features::{InitFeatures, ChannelTypeFeatures};
+ use ln::features::ChannelTypeFeatures;
use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate, MAX_VALUE_MSAT};
use ln::script::ShutdownScript;
use ln::chan_utils;
#[test]
fn upfront_shutdown_script_incompatibility() {
- let features = InitFeatures::known().clear_shutdown_anysegwit();
+ let features = channelmanager::provided_init_features().clear_shutdown_anysegwit();
let non_v0_segwit_shutdown_script =
ShutdownScript::new_witness_program(WitnessVersion::V16, &[0, 40]).unwrap();
let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let config = UserConfig::default();
- let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&bounded_fee_estimator, &&keys_provider, node_a_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+ let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&bounded_fee_estimator, &&keys_provider, node_a_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config, 0, 42).unwrap();
// Now change the fee so we can check that the fee in the open_channel message is the
// same as the old fee.
// Create Node A's channel pointing to Node B's pubkey
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let config = UserConfig::default();
- let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+ let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config, 0, 42).unwrap();
// Create Node B's channel by receiving Node A's open_channel message
// Make sure A's dust limit is as we expect.
let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash());
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
- let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
+ let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
// Node B --> Node A: accept channel, explicitly setting B's dust limit.
let mut accept_channel_msg = node_b_chan.accept_inbound_channel(0);
accept_channel_msg.dust_limit_satoshis = 546;
- node_a_chan.accept_channel(&accept_channel_msg, &config.channel_handshake_limits, &InitFeatures::known()).unwrap();
+ node_a_chan.accept_channel(&accept_channel_msg, &config.channel_handshake_limits, &channelmanager::provided_init_features()).unwrap();
node_a_chan.holder_dust_limit_satoshis = 1560;
// Put some inbound and outbound HTLCs in A's channel.
let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let config = UserConfig::default();
- let mut chan = Channel::<EnforcingSigner>::new_outbound(&fee_est, &&keys_provider, node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+ let mut chan = Channel::<EnforcingSigner>::new_outbound(&fee_est, &&keys_provider, node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config, 0, 42).unwrap();
let commitment_tx_fee_0_htlcs = Channel::<EnforcingSigner>::commit_tx_fee_msat(chan.feerate_per_kw, 0, chan.opt_anchors());
let commitment_tx_fee_1_htlc = Channel::<EnforcingSigner>::commit_tx_fee_msat(chan.feerate_per_kw, 1, chan.opt_anchors());
// Create Node A's channel pointing to Node B's pubkey
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let config = UserConfig::default();
- let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+ let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config, 0, 42).unwrap();
// Create Node B's channel by receiving Node A's open_channel message
let open_channel_msg = node_a_chan.get_open_channel(chain_hash);
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
- let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
+ let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
// Node B --> Node A: accept channel
let accept_channel_msg = node_b_chan.accept_inbound_channel(0);
- node_a_chan.accept_channel(&accept_channel_msg, &config.channel_handshake_limits, &InitFeatures::known()).unwrap();
+ node_a_chan.accept_channel(&accept_channel_msg, &config.channel_handshake_limits, &channelmanager::provided_init_features()).unwrap();
// Node A --> Node B: funding created
let output_script = node_a_chan.get_funding_redeemscript();
// Test that `new_outbound` creates a channel with the correct value for
// `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value,
// which is set to the lower bound + 1 (2%) of the `channel_value`.
- let chan_1 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_2_percent, 0, 42).unwrap();
+ let chan_1 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config_2_percent, 0, 42).unwrap();
let chan_1_value_msat = chan_1.channel_value_satoshis * 1000;
assert_eq!(chan_1.holder_max_htlc_value_in_flight_msat, (chan_1_value_msat as f64 * 0.02) as u64);
// Test with the upper bound - 1 of valid values (99%).
- let chan_2 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_99_percent, 0, 42).unwrap();
+ let chan_2 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config_99_percent, 0, 42).unwrap();
let chan_2_value_msat = chan_2.channel_value_satoshis * 1000;
assert_eq!(chan_2.holder_max_htlc_value_in_flight_msat, (chan_2_value_msat as f64 * 0.99) as u64);
// Test that `new_from_req` creates a channel with the correct value for
// `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value,
// which is set to the lower bound - 1 (2%) of the `channel_value`.
- let chan_3 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_2_percent, 0, &&logger, 42).unwrap();
+ let chan_3 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(), &chan_1_open_channel_msg, 7, &config_2_percent, 0, &&logger, 42).unwrap();
let chan_3_value_msat = chan_3.channel_value_satoshis * 1000;
assert_eq!(chan_3.holder_max_htlc_value_in_flight_msat, (chan_3_value_msat as f64 * 0.02) as u64);
// Test with the upper bound - 1 of valid values (99%).
- let chan_4 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_99_percent, 0, &&logger, 42).unwrap();
+ let chan_4 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(), &chan_1_open_channel_msg, 7, &config_99_percent, 0, &&logger, 42).unwrap();
let chan_4_value_msat = chan_4.channel_value_satoshis * 1000;
assert_eq!(chan_4.holder_max_htlc_value_in_flight_msat, (chan_4_value_msat as f64 * 0.99) as u64);
// Test that `new_outbound` uses the lower bound of the configurable percentage values (1%)
// if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a value less than 1.
- let chan_5 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_0_percent, 0, 42).unwrap();
+ let chan_5 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config_0_percent, 0, 42).unwrap();
let chan_5_value_msat = chan_5.channel_value_satoshis * 1000;
assert_eq!(chan_5.holder_max_htlc_value_in_flight_msat, (chan_5_value_msat as f64 * 0.01) as u64);
// Test that `new_outbound` uses the upper bound of the configurable percentage values
// (100%) if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a larger value
// than 100.
- let chan_6 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_101_percent, 0, 42).unwrap();
+ let chan_6 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config_101_percent, 0, 42).unwrap();
let chan_6_value_msat = chan_6.channel_value_satoshis * 1000;
assert_eq!(chan_6.holder_max_htlc_value_in_flight_msat, chan_6_value_msat);
// Test that `new_from_req` uses the lower bound of the configurable percentage values (1%)
// if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a value less than 1.
- let chan_7 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_0_percent, 0, &&logger, 42).unwrap();
+ let chan_7 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(), &chan_1_open_channel_msg, 7, &config_0_percent, 0, &&logger, 42).unwrap();
let chan_7_value_msat = chan_7.channel_value_satoshis * 1000;
assert_eq!(chan_7.holder_max_htlc_value_in_flight_msat, (chan_7_value_msat as f64 * 0.01) as u64);
// Test that `new_from_req` uses the upper bound of the configurable percentage values
// (100%) if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a larger value
// than 100.
- let chan_8 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_101_percent, 0, &&logger, 42).unwrap();
+ let chan_8 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(), &chan_1_open_channel_msg, 7, &config_101_percent, 0, &&logger, 42).unwrap();
let chan_8_value_msat = chan_8.channel_value_satoshis * 1000;
assert_eq!(chan_8.holder_max_htlc_value_in_flight_msat, chan_8_value_msat);
}
let mut outbound_node_config = UserConfig::default();
outbound_node_config.channel_handshake_config.their_channel_reserve_proportional_millionths = (outbound_selected_channel_reserve_perc * 1_000_000.0) as u32;
- let chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, outbound_node_id, &InitFeatures::known(), channel_value_satoshis, 100_000, 42, &outbound_node_config, 0, 42).unwrap();
+ let chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(), channel_value_satoshis, 100_000, 42, &outbound_node_config, 0, 42).unwrap();
let expected_outbound_selected_chan_reserve = cmp::max(MIN_THEIR_CHAN_RESERVE_SATOSHIS, (chan.channel_value_satoshis as f64 * outbound_selected_channel_reserve_perc) as u64);
assert_eq!(chan.holder_selected_channel_reserve_satoshis, expected_outbound_selected_chan_reserve);
inbound_node_config.channel_handshake_config.their_channel_reserve_proportional_millionths = (inbound_selected_channel_reserve_perc * 1_000_000.0) as u32;
if outbound_selected_channel_reserve_perc + inbound_selected_channel_reserve_perc < 1.0 {
- let chan_inbound_node = Channel::<EnforcingSigner>::new_from_req(&&fee_est, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, 42).unwrap();
+ let chan_inbound_node = Channel::<EnforcingSigner>::new_from_req(&&fee_est, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, 42).unwrap();
let expected_inbound_selected_chan_reserve = cmp::max(MIN_THEIR_CHAN_RESERVE_SATOSHIS, (chan.channel_value_satoshis as f64 * inbound_selected_channel_reserve_perc) as u64);
assert_eq!(chan_inbound_node.counterparty_selected_channel_reserve_satoshis.unwrap(), expected_outbound_selected_chan_reserve);
} else {
// Channel Negotiations failed
- let result = Channel::<EnforcingSigner>::new_from_req(&&fee_est, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, 42);
+ let result = Channel::<EnforcingSigner>::new_from_req(&&fee_est, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, 42);
assert!(result.is_err());
}
}
// Create a channel.
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let config = UserConfig::default();
- let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+ let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config, 0, 42).unwrap();
assert!(node_a_chan.counterparty_forwarding_info.is_none());
assert_eq!(node_a_chan.holder_htlc_minimum_msat, 1); // the default
assert!(node_a_chan.counterparty_forwarding_info().is_none());
let counterparty_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let mut config = UserConfig::default();
config.channel_handshake_config.announced_channel = false;
- let mut chan = Channel::<InMemorySigner>::new_outbound(&LowerBoundedFeeEstimator::new(&feeest), &&keys_provider, counterparty_node_id, &InitFeatures::known(), 10_000_000, 100000, 42, &config, 0, 42).unwrap(); // Nothing uses their network key in this test
+ let mut chan = Channel::<InMemorySigner>::new_outbound(&LowerBoundedFeeEstimator::new(&feeest), &&keys_provider, counterparty_node_id, &channelmanager::provided_init_features(), 10_000_000, 100000, 42, &config, 0, 42).unwrap(); // Nothing uses their network key in this test
chan.holder_dust_limit_satoshis = 546;
chan.counterparty_selected_channel_reserve_satoshis = Some(0); // Filled in in accept_channel
"020000000001012cfb3e4788c206881d38f2996b6cb2109b5935acb527d14bdaa7b908afa9b2fe04000000000000000001da0d0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004830450221009acd6a827a76bfee50806178dfe0495cd4e1d9c58279c194c7b01520fe68cb8d022024d439047c368883e570997a7d40f0b430cb5a742f507965e7d3063ae3feccca01473044022048762cf546bbfe474f1536365ea7c416e3c0389d60558bc9412cb148fb6ab68202207215d7083b75c96ff9d2b08c59c34e287b66820f530b486a9aa4cdd9c347d5b9012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000" }
} );
- // anchors: commitment tx with seven outputs untrimmed (maximum feerate)
- chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
- chan.feerate_per_kw = 644;
-
- test_commitment_with_anchors!("3045022100e0106830467a558c07544a3de7715610c1147062e7d091deeebe8b5c661cda9402202ad049c1a6d04834317a78483f723c205c9f638d17222aafc620800cc1b6ae35",
- "3045022100ef82a405364bfc4007e63a7cc82925a513d79065bdbc216d60b6a4223a323f8a02200716730b8561f3c6d362eaf47f202e99fb30d0557b61b92b5f9134f8e2de3681",
- "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80094a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994e80300000000000022002010f88bf09e56f14fb4543fd26e47b0db50ea5de9cf3fc46434792471082621aed0070000000000002200203e68115ae0b15b8de75b6c6bc9af5ac9f01391544e0870dae443a1e8fe7837ead007000000000000220020fe0598d74fee2205cc3672e6e6647706b4f3099713b4661b62482c3addd04a5eb80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a4f996a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100ef82a405364bfc4007e63a7cc82925a513d79065bdbc216d60b6a4223a323f8a02200716730b8561f3c6d362eaf47f202e99fb30d0557b61b92b5f9134f8e2de368101483045022100e0106830467a558c07544a3de7715610c1147062e7d091deeebe8b5c661cda9402202ad049c1a6d04834317a78483f723c205c9f638d17222aafc620800cc1b6ae3501475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", {
-
- { 0,
- "304402205912d91c58016f593d9e46fefcdb6f4125055c41a17b03101eaaa034b9028ab60220520d4d239c85c66e4c75c5b413620b62736e227659d7821b308e2b8ced3e728e",
- "30440220473166a5adcca68550bab80403f410a726b5bd855030527e3fefa8c1e4b4fd7b02203b1dc91d8d69039473036cb5c34398b99e8eb90ae500c22130a557b62294b188",
- "02000000000101b8cefef62ea66f5178b9361b2371be0759cbc8c689bcfa7a8e6746d497ec221a0200000000010000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402205912d91c58016f593d9e46fefcdb6f4125055c41a17b03101eaaa034b9028ab60220520d4d239c85c66e4c75c5b413620b62736e227659d7821b308e2b8ced3e728e834730440220473166a5adcca68550bab80403f410a726b5bd855030527e3fefa8c1e4b4fd7b02203b1dc91d8d69039473036cb5c34398b99e8eb90ae500c22130a557b62294b188012000000000000000000000000000000000000000000000000000000000000000008d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f401b175ac6851b2756800000000" },
-
- { 1,
- "3045022100c6b4113678039ee1e43a6cba5e3224ed2355ffc05e365a393afe8843dc9a76860220566d01fd52d65a89ba8595023884f9e8f2e9a310a6b9b85281c0bce06863430c",
- "3045022100d0d86307ea55d5daa80f453ad6d64b78fe8a6504aac25407c73e8502c0702c1602206a0809a02aa00c8dc4a53d976bb05d4605d8bb0b7b26b973a5c4e2734d8afbb4",
- "02000000000101b8cefef62ea66f5178b9361b2371be0759cbc8c689bcfa7a8e6746d497ec221a0300000000010000000124060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100c6b4113678039ee1e43a6cba5e3224ed2355ffc05e365a393afe8843dc9a76860220566d01fd52d65a89ba8595023884f9e8f2e9a310a6b9b85281c0bce06863430c83483045022100d0d86307ea55d5daa80f453ad6d64b78fe8a6504aac25407c73e8502c0702c1602206a0809a02aa00c8dc4a53d976bb05d4605d8bb0b7b26b973a5c4e2734d8afbb401008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6851b27568f6010000" },
-
- { 2,
- "304402203c3a699fb80a38112aafd73d6e3a9b7d40bc2c3ed8b7fbc182a20f43b215172202204e71821b984d1af52c4b8e2cd4c572578c12a965866130c2345f61e4c2d3fef4",
- "304402205bcfa92f83c69289a412b0b6dd4f2a0fe0b0fc2d45bd74706e963257a09ea24902203783e47883e60b86240e877fcbf33d50b1742f65bc93b3162d1be26583b367ee",
- "02000000000101b8cefef62ea66f5178b9361b2371be0759cbc8c689bcfa7a8e6746d497ec221a040000000001000000010a060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402203c3a699fb80a38112aafd73d6e3a9b7d40bc2c3ed8b7fbc182a20f43b215172202204e71821b984d1af52c4b8e2cd4c572578c12a965866130c2345f61e4c2d3fef48347304402205bcfa92f83c69289a412b0b6dd4f2a0fe0b0fc2d45bd74706e963257a09ea24902203783e47883e60b86240e877fcbf33d50b1742f65bc93b3162d1be26583b367ee012001010101010101010101010101010101010101010101010101010101010101018d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac6851b2756800000000" },
-
- { 3,
- "304402200f089bcd20f25475216307d32aa5b6c857419624bfba1da07335f51f6ba4645b02206ce0f7153edfba23b0d4b2afc26bb3157d404368cb8ea0ca7cf78590dcdd28cf",
- "3045022100e4516da08f72c7a4f7b2f37aa84a0feb54ae2cc5b73f0da378e81ae0ca8119bf02207751b2628d8e2f62b4b9abccda4866246c1bfcc82e3d416ad562fd212102c28f",
- "02000000000101b8cefef62ea66f5178b9361b2371be0759cbc8c689bcfa7a8e6746d497ec221a050000000001000000010c0a0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402200f089bcd20f25475216307d32aa5b6c857419624bfba1da07335f51f6ba4645b02206ce0f7153edfba23b0d4b2afc26bb3157d404368cb8ea0ca7cf78590dcdd28cf83483045022100e4516da08f72c7a4f7b2f37aa84a0feb54ae2cc5b73f0da378e81ae0ca8119bf02207751b2628d8e2f62b4b9abccda4866246c1bfcc82e3d416ad562fd212102c28f01008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000" },
-
- { 4,
- "3045022100aa72cfaf0965020c73a12c77276c6411ca68c4de36ac1998adf86c917a899a43022060da0a159fecfe0bed37c3962d767f12f90e30fed8a8f34b1301775c21a2bd3a",
- "304402203cd12065c2a42963c762e6b1a981e17695616ecb6f9fb33d8b0717cdd7ca0ee4022065500005c491c1dcf2fe9c4024f74b1c90785d572527055a491278f901143904",
- "02000000000101b8cefef62ea66f5178b9361b2371be0759cbc8c689bcfa7a8e6746d497ec221a06000000000100000001da0d0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100aa72cfaf0965020c73a12c77276c6411ca68c4de36ac1998adf86c917a899a43022060da0a159fecfe0bed37c3962d767f12f90e30fed8a8f34b1301775c21a2bd3a8347304402203cd12065c2a42963c762e6b1a981e17695616ecb6f9fb33d8b0717cdd7ca0ee4022065500005c491c1dcf2fe9c4024f74b1c90785d572527055a491278f901143904012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000" }
- } );
-
// commitment tx with six outputs untrimmed (minimum feerate)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 648;
"020000000001010f44041fdfba175987cf4e6135ba2a154e3b7fb96483dc0ed5efc0678e5b6bf103000000000000000001d90d0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500473044022024cd52e4198c8ae0e414a86d86b5a65ea7450f2eb4e783096736d93395eca5ce022078f0094745b45be4d4b2b04dd5978c9e66ba49109e5704403e84aaf5f387d6be01483045022100bbfb9d0a946d420807c86e985d636cceb16e71c3694ed186316251a00cbd807202207773223f9a337e145f64673825be9b30d07ef1542c82188b264bedcf7cda78c6012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000" }
} );
- // anchors: commitment tx with six outputs untrimmed (minimum feerate)
+ // anchors: commitment tx with six outputs untrimmed (minimum dust limit)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 645;
+ chan.holder_dust_limit_satoshis = 1001;
test_commitment_with_anchors!("3044022025d97466c8049e955a5afce28e322f4b34d2561118e52332fb400f9b908cc0a402205dc6fba3a0d67ee142c428c535580cd1f2ff42e2f89b47e0c8a01847caffc312",
"3045022100d57697c707b6f6d053febf24b98e8989f186eea42e37e9e91663ec2c70bb8f70022079b0715a472118f262f43016a674f59c015d9cafccec885968e76d9d9c5d0051",
"02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80084a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994d0070000000000002200203e68115ae0b15b8de75b6c6bc9af5ac9f01391544e0870dae443a1e8fe7837ead007000000000000220020fe0598d74fee2205cc3672e6e6647706b4f3099713b4661b62482c3addd04a5eb80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994abc996a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100d57697c707b6f6d053febf24b98e8989f186eea42e37e9e91663ec2c70bb8f70022079b0715a472118f262f43016a674f59c015d9cafccec885968e76d9d9c5d005101473044022025d97466c8049e955a5afce28e322f4b34d2561118e52332fb400f9b908cc0a402205dc6fba3a0d67ee142c428c535580cd1f2ff42e2f89b47e0c8a01847caffc31201475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", {
{ 0,
- "30440220446f9e5c375db6a61d6eeee8b59219a30a4a37372afc2670a1a2889c78e9b943022061895f6088fb48b490ab2140a4842c277b64bf25ff591625dd0356e0c96ab7a8",
- "3045022100c1621ba26a99c263fd885feff5fda5ca2cc73df080b3a49ecf15164ee244d2a5022037f4cc7fd4441af39a83a0e44c3b1db7d64a4c8080e8697f9e952f85421a34d8",
- "02000000000101104f394af4c4fad78337f95e3e9f802f4c0d86ab231853af09b28534856132000200000000010000000123060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220446f9e5c375db6a61d6eeee8b59219a30a4a37372afc2670a1a2889c78e9b943022061895f6088fb48b490ab2140a4842c277b64bf25ff591625dd0356e0c96ab7a883483045022100c1621ba26a99c263fd885feff5fda5ca2cc73df080b3a49ecf15164ee244d2a5022037f4cc7fd4441af39a83a0e44c3b1db7d64a4c8080e8697f9e952f85421a34d801008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6851b27568f6010000" },
+ "3045022100e04d160a326432659fe9fb127304c1d348dfeaba840081bdc57d8efd902a48d8022008a824e7cf5492b97e4d9e03c06a09f822775a44f6b5b2533a2088904abfc282",
+ "3045022100b7c49846466b13b190ff739bbe3005c105482fc55539e55b1c561f76b6982b6c02200e5c35808619cf543c8405cff9fedd25f333a4a2f6f6d5e8af8150090c40ef09",
+ "02000000000101104f394af4c4fad78337f95e3e9f802f4c0d86ab231853af09b285348561320002000000000100000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100e04d160a326432659fe9fb127304c1d348dfeaba840081bdc57d8efd902a48d8022008a824e7cf5492b97e4d9e03c06a09f822775a44f6b5b2533a2088904abfc28283483045022100b7c49846466b13b190ff739bbe3005c105482fc55539e55b1c561f76b6982b6c02200e5c35808619cf543c8405cff9fedd25f333a4a2f6f6d5e8af8150090c40ef0901008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6851b27568f6010000" },
{ 1,
- "3044022027a3ffcb8a007e3349d75382efbd4b3fb99fcbd479a18555e58697bd1278d5c402205c8303d46211c3ae8975fe84a0df08b4623119fecd03bc93b49d7f7a0c64c710",
- "3045022100b697aca55c6fb15e5348bb7387b584815fd15e8dd306afe0c477cb550d0c2d40022050b0f7e370f7604d2fec781fefe86715dbe95dff4dab88d628f509d62f854de1",
- "02000000000101104f394af4c4fad78337f95e3e9f802f4c0d86ab231853af09b28534856132000300000000010000000109060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500473044022027a3ffcb8a007e3349d75382efbd4b3fb99fcbd479a18555e58697bd1278d5c402205c8303d46211c3ae8975fe84a0df08b4623119fecd03bc93b49d7f7a0c64c71083483045022100b697aca55c6fb15e5348bb7387b584815fd15e8dd306afe0c477cb550d0c2d40022050b0f7e370f7604d2fec781fefe86715dbe95dff4dab88d628f509d62f854de1012001010101010101010101010101010101010101010101010101010101010101018d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac6851b2756800000000" },
+ "3045022100fbdc3c367ce3bf30796025cc590ee1f2ce0e72ae1ac19f5986d6d0a4fc76211f02207e45ae9267e8e820d188569604f71d1abd11bd385d58853dd7dc034cdb3e9a6e",
+ "3045022100d29330f24db213b262068706099b39c15fa7e070c3fcdf8836c09723fc4d365602203ce57d01e9f28601e461a0b5c4a50119b270bde8b70148d133a6849c70b115ac",
+ "02000000000101104f394af4c4fad78337f95e3e9f802f4c0d86ab231853af09b285348561320003000000000100000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100fbdc3c367ce3bf30796025cc590ee1f2ce0e72ae1ac19f5986d6d0a4fc76211f02207e45ae9267e8e820d188569604f71d1abd11bd385d58853dd7dc034cdb3e9a6e83483045022100d29330f24db213b262068706099b39c15fa7e070c3fcdf8836c09723fc4d365602203ce57d01e9f28601e461a0b5c4a50119b270bde8b70148d133a6849c70b115ac012001010101010101010101010101010101010101010101010101010101010101018d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac6851b2756800000000" },
{ 2,
- "30440220013975ae356e6daf22a86a29f21c4f35aca82ed8f731a1103c60c74f5ed1c5aa02200350d4e5455cdbcacb7ccf174db5bed8286019e509a113f6b4c5e606ee12c9d7",
- "3045022100e69a29f78779577830e73f327073c93168896f1b89432124b7846f5def9cd9cb02204433db3697e6ed7ac89574ca066a749640e0c9e114ac2e0ee4545741fcf7b7e9",
- "02000000000101104f394af4c4fad78337f95e3e9f802f4c0d86ab231853af09b2853485613200040000000001000000010b0a0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220013975ae356e6daf22a86a29f21c4f35aca82ed8f731a1103c60c74f5ed1c5aa02200350d4e5455cdbcacb7ccf174db5bed8286019e509a113f6b4c5e606ee12c9d783483045022100e69a29f78779577830e73f327073c93168896f1b89432124b7846f5def9cd9cb02204433db3697e6ed7ac89574ca066a749640e0c9e114ac2e0ee4545741fcf7b7e901008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000" },
+ "3044022066c5ef625cee3ddd2bc7b6bfb354b5834cf1cc6d52dd972fb41b7b225437ae4a022066cb85647df65c6b87a54e416dcdcca778a776c36a9643d2b5dc793c9b29f4c1",
+ "304402202d4ce515cd9000ec37575972d70b8d24f73909fb7012e8ebd8c2066ef6fe187902202830b53e64ea565fecd0f398100691da6bb2a5cf9bb0d1926f1d71d05828a11e",
+ "02000000000101104f394af4c4fad78337f95e3e9f802f4c0d86ab231853af09b285348561320004000000000100000001b80b0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500473044022066c5ef625cee3ddd2bc7b6bfb354b5834cf1cc6d52dd972fb41b7b225437ae4a022066cb85647df65c6b87a54e416dcdcca778a776c36a9643d2b5dc793c9b29f4c18347304402202d4ce515cd9000ec37575972d70b8d24f73909fb7012e8ebd8c2066ef6fe187902202830b53e64ea565fecd0f398100691da6bb2a5cf9bb0d1926f1d71d05828a11e01008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000" },
{ 3,
- "304402205257017423644c7e831f30bc0c334eecfe66e9a6d2e92d157c5bece576b2be4f022047b21cf8e955e22b7471940563922d1a5852fb95459ca32905c7d46a19141664",
- "304402204f5de65a624e3f757adffb678bd887eb4e656538c5ea7044922f6ee3eed8a06202206ff6f7bfe73b565343cae76131ac658f1a9c60d3ca2343358cda60b9e35f94c8",
- "02000000000101104f394af4c4fad78337f95e3e9f802f4c0d86ab231853af09b285348561320005000000000100000001d90d0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402205257017423644c7e831f30bc0c334eecfe66e9a6d2e92d157c5bece576b2be4f022047b21cf8e955e22b7471940563922d1a5852fb95459ca32905c7d46a191416648347304402204f5de65a624e3f757adffb678bd887eb4e656538c5ea7044922f6ee3eed8a06202206ff6f7bfe73b565343cae76131ac658f1a9c60d3ca2343358cda60b9e35f94c8012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000" }
+ "3044022022c7e11595c53ee89a57ca76baf0aed730da035952d6ab3fe6459f5eff3b337a022075e10cc5f5fd724a35ce4087a5d03cd616698626c69814032132b50bb97dc615",
+ "3045022100b20cd63e0587d1711beaebda4730775c4ac8b8b2ec78fe18a0c44c3f168c25230220079abb7fc4924e2fca5950842e5b9e416735585026914570078c4ef62f286226",
+ "02000000000101104f394af4c4fad78337f95e3e9f802f4c0d86ab231853af09b285348561320005000000000100000001a00f0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500473044022022c7e11595c53ee89a57ca76baf0aed730da035952d6ab3fe6459f5eff3b337a022075e10cc5f5fd724a35ce4087a5d03cd616698626c69814032132b50bb97dc61583483045022100b20cd63e0587d1711beaebda4730775c4ac8b8b2ec78fe18a0c44c3f168c25230220079abb7fc4924e2fca5950842e5b9e416735585026914570078c4ef62f286226012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000" }
} );
// commitment tx with six outputs untrimmed (maximum feerate)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 2069;
+ chan.holder_dust_limit_satoshis = 546;
test_commitment!("304502210090b96a2498ce0c0f2fadbec2aab278fed54c1a7838df793ec4d2c78d96ec096202204fdd439c50f90d483baa7b68feeef4bd33bc277695405447bcd0bfb2ca34d7bc",
"3045022100ad9a9bbbb75d506ca3b716b336ee3cf975dd7834fcf129d7dd188146eb58a8b4022061a759ee417339f7fe2ea1e8deb83abb6a74db31a09b7648a932a639cda23e33",
"02000000000101adbe717a63fb658add30ada1e6e12ed257637581898abe475c11d7bbcd65bd4d03000000000000000001f2090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402207475aeb0212ef9bf5130b60937817ad88c9a87976988ef1f323f026148cc4a850220739fea17ad3257dcad72e509c73eebe86bee30b178467b9fdab213d631b109df01483045022100d315522e09e7d53d2a659a79cb67fef56d6c4bddf3f46df6772d0d20a7beb7c8022070bcc17e288607b6a72be0bd83368bb6d53488db266c1cdb4d72214e4f02ac33012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000" }
} );
- // anchors: commitment tx with six outputs untrimmed (maximum feerate)
- chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
- chan.feerate_per_kw = 2060;
-
- test_commitment_with_anchors!("304402206208aeb34e404bd052ce3f298dfa832891c9d42caec99fe2a0d2832e9690b94302201b034bfcc6fa9faec667a9b7cbfe0b8d85e954aa239b66277887b5088aff08c3",
- "304402201ce37a44b95213358c20f44404d6db7a6083bea6f58de6c46547ae41a47c9f8202206db1d45be41373e92f90d346381febbea8c78671b28c153e30ad1db3441a9497",
- "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80084a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994d0070000000000002200203e68115ae0b15b8de75b6c6bc9af5ac9f01391544e0870dae443a1e8fe7837ead007000000000000220020fe0598d74fee2205cc3672e6e6647706b4f3099713b4661b62482c3addd04a5eb80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994ab88f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402201ce37a44b95213358c20f44404d6db7a6083bea6f58de6c46547ae41a47c9f8202206db1d45be41373e92f90d346381febbea8c78671b28c153e30ad1db3441a94970147304402206208aeb34e404bd052ce3f298dfa832891c9d42caec99fe2a0d2832e9690b94302201b034bfcc6fa9faec667a9b7cbfe0b8d85e954aa239b66277887b5088aff08c301475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", {
-
- { 0,
- "30440220011f999016570bbab9f3125377d0f35096b4dbe155f97c20f71829ead2817d1602201f23f7e17f6928734601c5d8613431eed5c90aa41c3106e8c1cb02ce32aacb5d",
- "3044022017da96dfb0eb4061fa0162dc6fa6b2e07ecc5040ab5e6cb07be59838460b3e58022079371ffc95002cc1dc2891ec38198c9c25aca8164304fe114f1b55e2ffd1ddd5",
- "02000000000101e7f364cf3a554b670767e723ef14b2af7a3eac70bd79dbde9256f384369c062d0200000000010000000175020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220011f999016570bbab9f3125377d0f35096b4dbe155f97c20f71829ead2817d1602201f23f7e17f6928734601c5d8613431eed5c90aa41c3106e8c1cb02ce32aacb5d83473044022017da96dfb0eb4061fa0162dc6fa6b2e07ecc5040ab5e6cb07be59838460b3e58022079371ffc95002cc1dc2891ec38198c9c25aca8164304fe114f1b55e2ffd1ddd501008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6851b27568f6010000" },
-
- { 1,
- "304402202d2d9681409b0a0987bd4a268ffeb112df85c4c988ac2a3a2475cb00a61912c302206aa4f4d1388b7d3282bc847871af3cca30766cc8f1064e3a41ec7e82221e10f7",
- "304402206426d67911aa6ff9b1cb147b093f3f65a37831a86d7c741d999afc0666e1773d022000bb71821650c70ea58d9bcdd03af736c41a5a8159d436c3ee0408a07394dcce",
- "02000000000101e7f364cf3a554b670767e723ef14b2af7a3eac70bd79dbde9256f384369c062d0300000000010000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402202d2d9681409b0a0987bd4a268ffeb112df85c4c988ac2a3a2475cb00a61912c302206aa4f4d1388b7d3282bc847871af3cca30766cc8f1064e3a41ec7e82221e10f78347304402206426d67911aa6ff9b1cb147b093f3f65a37831a86d7c741d999afc0666e1773d022000bb71821650c70ea58d9bcdd03af736c41a5a8159d436c3ee0408a07394dcce012001010101010101010101010101010101010101010101010101010101010101018d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac6851b2756800000000" },
-
- { 2,
- "3045022100f51cdaa525b7d4304548c642bb7945215eb5ae7d32874517cde67ca23ab0a12202206286d59e4b19926c6ac844be6f3ab8149a1ddb9c70f5026b7e83e40a6c08e6e1",
- "304502210091b16b1ac63b867e7a5ca0344f7b2aa1cdd49d4b72eac86a31e7ec6f069e20640220402bfb571ba3a9c49e3b0061c89303453803d0241059d899222aaac4799b5076",
- "02000000000101e7f364cf3a554b670767e723ef14b2af7a3eac70bd79dbde9256f384369c062d040000000001000000015d060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100f51cdaa525b7d4304548c642bb7945215eb5ae7d32874517cde67ca23ab0a12202206286d59e4b19926c6ac844be6f3ab8149a1ddb9c70f5026b7e83e40a6c08e6e18348304502210091b16b1ac63b867e7a5ca0344f7b2aa1cdd49d4b72eac86a31e7ec6f069e20640220402bfb571ba3a9c49e3b0061c89303453803d0241059d899222aaac4799b507601008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000" },
-
- { 3,
- "304402202f058d99cb5a54f90773d43ba4e7a0089efd9f8269ef2da1b85d48a3e230555402205acc4bd6561830867d45cd7b84bba9fa35ad2b345016471c1737142bc99782c4",
- "304402202913f9cacea54efd2316cffa91219def9e0e111977216c1e76e9da80befab14f022000a9a69e8f37ebe4a39107ab50fab0dde537334588f8f412bbaca57b179b87a6",
- "02000000000101e7f364cf3a554b670767e723ef14b2af7a3eac70bd79dbde9256f384369c062d05000000000100000001f2090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402202f058d99cb5a54f90773d43ba4e7a0089efd9f8269ef2da1b85d48a3e230555402205acc4bd6561830867d45cd7b84bba9fa35ad2b345016471c1737142bc99782c48347304402202913f9cacea54efd2316cffa91219def9e0e111977216c1e76e9da80befab14f022000a9a69e8f37ebe4a39107ab50fab0dde537334588f8f412bbaca57b179b87a6012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000" }
- } );
-
// commitment tx with five outputs untrimmed (minimum feerate)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 2070;
"02000000000101403ad7602b43293497a3a2235a12ecefda4f3a1f1d06e49b1786d945685de1ff02000000000000000001f1090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100ae5fc7717ae684bc1fcf9020854e5dbe9842c9e7472879ac06ff95ac2bb10e4e022057728ada4c00083a3e65493fb5d50a232165948a1a0f530ef63185c2c8c56504014730440220408ad3009827a8fccf774cb285587686bfb2ed041f89a89453c311ce9c8ee0f902203c7392d9f8306d3a46522a66bd2723a7eb2628cb2d9b34d4c104f1766bf37502012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000" }
} );
- // anchors: commitment tx with five outputs untrimmed (minimum feerate)
- chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
- chan.feerate_per_kw = 2061;
-
- test_commitment_with_anchors!("3045022100a2faf2ad7e323b2a82e07dc40b6847207ca6ad7b089f2c21dea9a4d37e52d59d02204c9480ce0358eb51d92a4342355a97e272e3cc45f86c612a76a3fe32fc3c4cb4",
- "304402204ab07c659412dd2cd6043b1ad811ab215e901b6b5653e08cb3d2fe63d3e3dc57022031c7b3d130f9380ef09581f4f5a15cb6f359a2e0a597146b96c3533a26d6f4cd",
- "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80074a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994d0070000000000002200203e68115ae0b15b8de75b6c6bc9af5ac9f01391544e0870dae443a1e8fe7837eab80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a18916a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402204ab07c659412dd2cd6043b1ad811ab215e901b6b5653e08cb3d2fe63d3e3dc57022031c7b3d130f9380ef09581f4f5a15cb6f359a2e0a597146b96c3533a26d6f4cd01483045022100a2faf2ad7e323b2a82e07dc40b6847207ca6ad7b089f2c21dea9a4d37e52d59d02204c9480ce0358eb51d92a4342355a97e272e3cc45f86c612a76a3fe32fc3c4cb401475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", {
-
- { 0,
- "3045022100e10744f572a2cd1d787c969e894b792afaed21217ee0480df0112d2fa3ef96ea02202af4f66eb6beebc36d8e98719ed6b4be1b181659fcb561fc491d8cfebff3aa85",
- "3045022100c3dc3ea50a0ca20e350f97b50c52c5514717cfa36cb9600918caac5cb556842b022049af018d676dde0c8e28ecf325f3ff5c1594261c4f7511d501f9d62d0594d2a2",
- "02000000000101cf32732fe2d1387ed4e2335f69ddd3c0f337dabc03269e742531f89d35e161d10200000000010000000174020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100e10744f572a2cd1d787c969e894b792afaed21217ee0480df0112d2fa3ef96ea02202af4f66eb6beebc36d8e98719ed6b4be1b181659fcb561fc491d8cfebff3aa8583483045022100c3dc3ea50a0ca20e350f97b50c52c5514717cfa36cb9600918caac5cb556842b022049af018d676dde0c8e28ecf325f3ff5c1594261c4f7511d501f9d62d0594d2a201008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6851b27568f6010000" },
-
- { 1,
- "3045022100e1f51fb72fec604b029b348a3bb6363454e1869f5b1e24fd736f860c8039f8070220030a2c90186437d8c9b47d4897798c024521b1274991c4cdc125970b346094b1",
- "3045022100ec7ade6037e531629f24390ca9713782a04d648065d17fbe6b015981cdb296c202202d61049a6ecba2fb5314f3edcda2361cad187a89bea6e5d15185354d80c0c085",
- "02000000000101cf32732fe2d1387ed4e2335f69ddd3c0f337dabc03269e742531f89d35e161d1030000000001000000015c060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100e1f51fb72fec604b029b348a3bb6363454e1869f5b1e24fd736f860c8039f8070220030a2c90186437d8c9b47d4897798c024521b1274991c4cdc125970b346094b183483045022100ec7ade6037e531629f24390ca9713782a04d648065d17fbe6b015981cdb296c202202d61049a6ecba2fb5314f3edcda2361cad187a89bea6e5d15185354d80c0c08501008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000" },
-
- { 2,
- "304402203479f81a1d83c516957679dc98bf91d35deada967739a8e3869e3e8db08246130220053c8e154b97e3019048dcec3d51bfaf396f36861fbda6d33f0e2a57155c8b9f",
- "3045022100a558eb5caa04e35a4417c1f0123ac12eec5f6badee28f5764dc6b69486e594f802201589b12784e242f205832d2d032149bd4e79433ec304c05394241fc7dcba5a71",
- "02000000000101cf32732fe2d1387ed4e2335f69ddd3c0f337dabc03269e742531f89d35e161d104000000000100000001f1090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402203479f81a1d83c516957679dc98bf91d35deada967739a8e3869e3e8db08246130220053c8e154b97e3019048dcec3d51bfaf396f36861fbda6d33f0e2a57155c8b9f83483045022100a558eb5caa04e35a4417c1f0123ac12eec5f6badee28f5764dc6b69486e594f802201589b12784e242f205832d2d032149bd4e79433ec304c05394241fc7dcba5a71012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000" }
- } );
-
// commitment tx with five outputs untrimmed (maximum feerate)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 2194;
"02000000000101153cd825fdb3aa624bfe513e8031d5d08c5e582fb3d1d1fe8faf27d3eed410cd020000000000000000019a090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100c9e6f0454aa598b905a35e641a70cc9f67b5f38cc4b00843a041238c4a9f1c4a0220260a2822a62da97e44583e837245995ca2e36781769c52f19e498efbdcca262b014830450221008a9f2ea24cd455c2b64c1472a5fa83865b0a5f49a62b661801e884cf2849af8302204d44180e50bf6adfcf1c1e581d75af91aba4e28681ce4a5ee5f3cbf65eca10f3012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000" }
} );
- // anchors: commitment tx with five outputs untrimmed (maximum feerate)
- chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
- chan.feerate_per_kw = 2184;
-
- test_commitment_with_anchors!("3044022013d326f80ff7607cf366c823fcbbcb7a2b10322484825f151e6c4c756af24b8f02201ba05b9d8beb7cea2947f9f4d9e03f90435e93db2dd48b32eb9ca3f3dd042c79",
- "30440220555c05261f72c5b4702d5c83a608630822b473048724b08640d6e75e345094250220448950b74a96a56963928ba5db8b457661a742c855e69d239b3b6ab73de307a3",
- "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80074a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994d0070000000000002200203e68115ae0b15b8de75b6c6bc9af5ac9f01391544e0870dae443a1e8fe7837eab80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a4f906a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e04004730440220555c05261f72c5b4702d5c83a608630822b473048724b08640d6e75e345094250220448950b74a96a56963928ba5db8b457661a742c855e69d239b3b6ab73de307a301473044022013d326f80ff7607cf366c823fcbbcb7a2b10322484825f151e6c4c756af24b8f02201ba05b9d8beb7cea2947f9f4d9e03f90435e93db2dd48b32eb9ca3f3dd042c7901475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", {
-
- { 0,
- "304402202e03ba1390998b3487e9a7fefcb66814c09abea0ef1bcc915dbaefbcf310569a02206bd10493a105ac69048e9bcedcb8e3301ef81b55018d911a4afd297297f98d30",
- "304402200c3952ca04be0c60dcc0b7873a0829f560607524943554ae4a27d8d967166199022021a68657b88e22f9bf9ac6065be412685aff643d17049f04f2e99e86197dabb1",
- "020000000001015b03043e20eb467029305a22af4c3b915e793743f192c5d225cf1d3c6e8c03010200000000010000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402202e03ba1390998b3487e9a7fefcb66814c09abea0ef1bcc915dbaefbcf310569a02206bd10493a105ac69048e9bcedcb8e3301ef81b55018d911a4afd297297f98d308347304402200c3952ca04be0c60dcc0b7873a0829f560607524943554ae4a27d8d967166199022021a68657b88e22f9bf9ac6065be412685aff643d17049f04f2e99e86197dabb101008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6851b27568f6010000" },
-
- { 1,
- "304402201f8a6adda2403bc400c919ea69d72d315337291e00d02cde085ea32953dbc50002202d65230da98df7af8ebefd2b60b457d0945232988ee2d7460a94a77d414a9acc",
- "3045022100ea69c9273b8914ac62b5b7082d6ac1da2b7b065ebf2ef3cd6403f5305ce3f26802203d98736ea97638895a898dfcc5ee0d0c55eb496b3964df0bb25d223688ea8b87",
- "020000000001015b03043e20eb467029305a22af4c3b915e793743f192c5d225cf1d3c6e8c0301030000000001000000010a060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402201f8a6adda2403bc400c919ea69d72d315337291e00d02cde085ea32953dbc50002202d65230da98df7af8ebefd2b60b457d0945232988ee2d7460a94a77d414a9acc83483045022100ea69c9273b8914ac62b5b7082d6ac1da2b7b065ebf2ef3cd6403f5305ce3f26802203d98736ea97638895a898dfcc5ee0d0c55eb496b3964df0bb25d223688ea8b8701008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000" },
-
- { 2,
- "3045022100ea6e4c9b8f56dd9cf5799492a201cdd65b8bc9bc089c3cff34107896ae313f90022034760f7760975cc68e8917a7f62894e25583da7be11af557c4fc402661d0cbf8",
- "30440220717012f2f7ef6cac590aaf66c2109132c93ffba245959ac62d82e394ba80191302203f00fd9cb37c92c6b0ad4b33e62c3e55b04e5c2cfa0adcca5a9bc49774eeca8a",
- "020000000001015b03043e20eb467029305a22af4c3b915e793743f192c5d225cf1d3c6e8c0301040000000001000000019b090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100ea6e4c9b8f56dd9cf5799492a201cdd65b8bc9bc089c3cff34107896ae313f90022034760f7760975cc68e8917a7f62894e25583da7be11af557c4fc402661d0cbf8834730440220717012f2f7ef6cac590aaf66c2109132c93ffba245959ac62d82e394ba80191302203f00fd9cb37c92c6b0ad4b33e62c3e55b04e5c2cfa0adcca5a9bc49774eeca8a012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000" }
- } );
-
// commitment tx with four outputs untrimmed (minimum feerate)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 2195;
"020000000001018130a10f09b13677ba2885a8bca32860f3a952e5912b829a473639b5a2c07b900100000000000000000199090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100d193b7ecccad8057571620a0b1ffa6c48e9483311723b59cf536043b20bc51550220546d4bd37b3b101ecda14f6c907af46ec391abce1cd9c7ce22b1a62b534f2f2a01473044022014d66f11f9cacf923807eba49542076c5fe5cccf252fb08fe98c78ef3ca6ab5402201b290dbe043cc512d9d78de074a5a129b8759bc6a6c546b190d120b690bd6e82012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000" }
} );
- // anchors: commitment tx with four outputs untrimmed (minimum feerate)
+ // anchors: commitment tx with four outputs untrimmed (minimum dust limit)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 2185;
+ chan.holder_dust_limit_satoshis = 2001;
test_commitment_with_anchors!("3044022040f63a16148cf35c8d3d41827f5ae7f7c3746885bb64d4d1b895892a83812b3e02202fcf95c2bf02c466163b3fa3ced6a24926fbb4035095a96842ef516e86ba54c0",
"3045022100cd8479cfe1edb1e5a1d487391e0451a469c7171e51e680183f19eb4321f20e9b02204eab7d5a6384b1b08e03baa6e4d9748dfd2b5ab2bae7e39604a0d0055bbffdd5",
"02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80064a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994b80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994ac5916a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100cd8479cfe1edb1e5a1d487391e0451a469c7171e51e680183f19eb4321f20e9b02204eab7d5a6384b1b08e03baa6e4d9748dfd2b5ab2bae7e39604a0d0055bbffdd501473044022040f63a16148cf35c8d3d41827f5ae7f7c3746885bb64d4d1b895892a83812b3e02202fcf95c2bf02c466163b3fa3ced6a24926fbb4035095a96842ef516e86ba54c001475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", {
{ 0,
- "304502210094480e38afb41d10fae299224872f19c53abe23c7033a1c0642c48713e7863a10220726dd9456407682667dc4bd9c66975acb3744961770b5002f7eb9c0df9ef2f3e",
- "304402203148dac61513dc0361738cba30cb341a1e580f8acd5ab0149bf65bd670688cf002207e5d9a0fcbbea2c263bc714fa9e9c44d7f582ea447f366119fc614a23de32f1f",
- "02000000000101ac13a7715f80b8e52dda43c6929cade5521bdced3a405da02b443f1ffb1e33cc0200000000010000000109060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050048304502210094480e38afb41d10fae299224872f19c53abe23c7033a1c0642c48713e7863a10220726dd9456407682667dc4bd9c66975acb3744961770b5002f7eb9c0df9ef2f3e8347304402203148dac61513dc0361738cba30cb341a1e580f8acd5ab0149bf65bd670688cf002207e5d9a0fcbbea2c263bc714fa9e9c44d7f582ea447f366119fc614a23de32f1f01008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000" },
+ "304402206870514a72ad6e723ff7f1e0370d7a33c1cd2a0b9272674143ebaf6a1d02dee102205bd953c34faf5e7322e9a1c0103581cb090280fda4f1039ee8552668afa90ebb",
+ "30440220669de9ca7910eff65a7773ebd14a9fc371fe88cde5b8e2a81609d85c87ac939b02201ac29472fa4067322e92d75b624942d60be5050139b20bb363db75be79eb946f",
+ "02000000000101ac13a7715f80b8e52dda43c6929cade5521bdced3a405da02b443f1ffb1e33cc02000000000100000001b80b0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402206870514a72ad6e723ff7f1e0370d7a33c1cd2a0b9272674143ebaf6a1d02dee102205bd953c34faf5e7322e9a1c0103581cb090280fda4f1039ee8552668afa90ebb834730440220669de9ca7910eff65a7773ebd14a9fc371fe88cde5b8e2a81609d85c87ac939b02201ac29472fa4067322e92d75b624942d60be5050139b20bb363db75be79eb946f01008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000" },
{ 1,
- "304402200dbde868dbc20c6a2433fe8979ba5e3f966b1c2d1aeb615f1c42e9c938b3495402202eec5f663c8b601c2061c1453d35de22597c137d1907a2feaf714d551035cb6e",
- "3045022100b896bded41d7feac7af25c19e35c53037c53b50e73cfd01eb4ba139c7fdf231602203a3be049d3d89396c4dc766d82ce31e237da8bc3a93e2c7d35992d1932d9cfeb",
- "02000000000101ac13a7715f80b8e52dda43c6929cade5521bdced3a405da02b443f1ffb1e33cc030000000001000000019a090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402200dbde868dbc20c6a2433fe8979ba5e3f966b1c2d1aeb615f1c42e9c938b3495402202eec5f663c8b601c2061c1453d35de22597c137d1907a2feaf714d551035cb6e83483045022100b896bded41d7feac7af25c19e35c53037c53b50e73cfd01eb4ba139c7fdf231602203a3be049d3d89396c4dc766d82ce31e237da8bc3a93e2c7d35992d1932d9cfeb012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000" }
+ "3045022100949e8dd938da56445b1cdfdebe1b7efea086edd05d89910d205a1e2e033ce47102202cbd68b5262ab144d9ec12653f87dfb0bb6bd05d1f58ae1e523f028eaefd7271",
+ "3045022100e3104ed8b239f8019e5f0a1a73d7782a94a8c36e7984f476c3a0b3cb0e62e27902207e3d52884600985f8a2098e53a5c30dd6a5e857733acfaa07ab2162421ed2688",
+ "02000000000101ac13a7715f80b8e52dda43c6929cade5521bdced3a405da02b443f1ffb1e33cc03000000000100000001a00f0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100949e8dd938da56445b1cdfdebe1b7efea086edd05d89910d205a1e2e033ce47102202cbd68b5262ab144d9ec12653f87dfb0bb6bd05d1f58ae1e523f028eaefd727183483045022100e3104ed8b239f8019e5f0a1a73d7782a94a8c36e7984f476c3a0b3cb0e62e27902207e3d52884600985f8a2098e53a5c30dd6a5e857733acfaa07ab2162421ed2688012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000" }
} );
// commitment tx with four outputs untrimmed (maximum feerate)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 3702;
+ chan.holder_dust_limit_satoshis = 546;
test_commitment!("304502210092a587aeb777f869e7ff0d7898ea619ee26a3dacd1f3672b945eea600be431100220077ee9eae3528d15251f2a52b607b189820e57a6ccfac8d1af502b132ee40169",
"3045022100e5efb73c32d32da2d79702299b6317de6fb24a60476e3855926d78484dd1b3c802203557cb66a42c944ef06e00bcc4da35a5bcb2f185aab0f8e403e519e1d66aaf75",
"020000000001018db483bff65c70ee71d8282aeec5a880e2e2b39e45772bda5460403095c62e3f0100000000000000000176050000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500473044022057649739b0eb74d541ead0dfdb3d4b2c15aa192720031044c3434c67812e5ca902201e5ede42d960ae551707f4a6b34b09393cf4dee2418507daa022e3550dbb58170147304402207faad26678c8850e01b4a0696d60841f7305e1832b786110ee9075cb92ed14a30220516ef8ee5dfa80824ea28cbcec0dd95f8b847146257c16960db98507db15ffdc012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000" }
} );
- // anchors: commitment tx with four outputs untrimmed (maximum feerate)
- chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
- chan.feerate_per_kw = 3686;
-
- test_commitment_with_anchors!("30440220784485cf7a0ad7979daf2c858ffdaf5298d0020cea7aea466843e7948223bd9902206031b81d25e02a178c64e62f843577fdcdfc7a1decbbfb54cd895de692df85ca",
- "3045022100c268496aad5c3f97f25cf41c1ba5483a12982de29b222051b6de3daa2229413b02207f3c82d77a2c14f0096ed9bb4c34649483bb20fa71f819f71af44de6593e8bb2",
- "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80064a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994b80b000000000000220020f96d0334feb64a4f40eb272031d07afcb038db56aa57446d60308c9f8ccadef9a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a29896a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100c268496aad5c3f97f25cf41c1ba5483a12982de29b222051b6de3daa2229413b02207f3c82d77a2c14f0096ed9bb4c34649483bb20fa71f819f71af44de6593e8bb2014730440220784485cf7a0ad7979daf2c858ffdaf5298d0020cea7aea466843e7948223bd9902206031b81d25e02a178c64e62f843577fdcdfc7a1decbbfb54cd895de692df85ca01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", {
-
- { 0,
- "304402202cfe6618926ca9f1574f8c4659b425e9790b4677ba2248d77901290806130ffe02204ab37bb0287abcdb8b750b018d41a09effe37cb65ff801fa70d3f1a416599841",
- "3044022030b318139715e3b34f19be852cc01c1c0e1599e8b926a73df2bfb70dd186ddee022062a2b7398aed9f563b4014da04a1a99debd0ff663ceece68a547df5982dc2d72",
- "020000000001012c32e55722e4b96324d8e5b398d583a20780b25202816adc32dc3157dee731c90200000000010000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402202cfe6618926ca9f1574f8c4659b425e9790b4677ba2248d77901290806130ffe02204ab37bb0287abcdb8b750b018d41a09effe37cb65ff801fa70d3f1a41659984183473044022030b318139715e3b34f19be852cc01c1c0e1599e8b926a73df2bfb70dd186ddee022062a2b7398aed9f563b4014da04a1a99debd0ff663ceece68a547df5982dc2d7201008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6851b27568f7010000" },
-
- { 1,
- "30440220687af8544d335376620a6f4b5412bfd0da48de047c1785674f26e669d4a3ff82022058591c1e3a6c50017427d38a8f756eb685bdab88ec73838eed3530048861f9d5",
- "30440220109f1a62b5a13d28d5b7634dd7693b1d5994eb404c4bb4a9a80aa540d3984d170220307251107ff8499a23e99abce7dda4f1c707c98abddb9405a83de0081cde8ace",
- "020000000001012c32e55722e4b96324d8e5b398d583a20780b25202816adc32dc3157dee731c90300000000010000000176050000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220687af8544d335376620a6f4b5412bfd0da48de047c1785674f26e669d4a3ff82022058591c1e3a6c50017427d38a8f756eb685bdab88ec73838eed3530048861f9d5834730440220109f1a62b5a13d28d5b7634dd7693b1d5994eb404c4bb4a9a80aa540d3984d170220307251107ff8499a23e99abce7dda4f1c707c98abddb9405a83de0081cde8ace012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000" }
- } );
-
// commitment tx with three outputs untrimmed (minimum feerate)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 3703;
"0200000000010120060e4a29579d429f0f27c17ee5f1ee282f20d706d6f90b63d35946d8f3029a0000000000000000000175050000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100c34c61735f93f2e324cc873c3b248111ccf8f6db15d5969583757010d4ad2b4602207867bb919b2ddd6387873e425345c9b7fd18d1d66aba41f3607bc2896ef3c30a01483045022100988c143e2110067117d2321bdd4bd16ca1734c98b29290d129384af0962b634e02206c1b02478878c5f547018b833986578f90c3e9be669fe5788ad0072a55acbb05012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000" }
} );
- // anchors: commitment tx with three outputs untrimmed (minimum feerate)
+ // anchors: commitment tx with three outputs untrimmed (minimum dust limit)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 3687;
+ chan.holder_dust_limit_satoshis = 3001;
test_commitment_with_anchors!("3045022100ad6c71569856b2d7ff42e838b4abe74a713426b37f22fa667a195a4c88908c6902202b37272b02a42dc6d9f4f82cab3eaf84ac882d9ed762859e1e75455c2c228377",
"3045022100c970799bcb33f43179eb43b3378a0a61991cf2923f69b36ef12548c3df0e6d500220413dc27d2e39ee583093adfcb7799be680141738babb31cc7b0669a777a31f5d",
"02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80054a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994aa28b6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100c970799bcb33f43179eb43b3378a0a61991cf2923f69b36ef12548c3df0e6d500220413dc27d2e39ee583093adfcb7799be680141738babb31cc7b0669a777a31f5d01483045022100ad6c71569856b2d7ff42e838b4abe74a713426b37f22fa667a195a4c88908c6902202b37272b02a42dc6d9f4f82cab3eaf84ac882d9ed762859e1e75455c2c22837701475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", {
{ 0,
- "3045022100b287bb8e079a62dcb3aaa8b6c67c0f434a87ebf64ab0bcfb2fc14b55576b859f02206d37c2eb5fd04cfc9eb0534c76a28a98da251b84a931377cce307af39dfaed74",
- "3045022100a497c64faea286ec4221f48628086dc6403fd7b60a23c4176e8ebbca15ae70dc0220754e20e968e96cf6421fd2a672c8c26d3bc6e19218cfc8fc2aa51fce026c14b1",
- "02000000000101542562b326c08e3a076d9cfca2be175041366591da334d8d513ff1686fd95a600200000000010000000175050000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100b287bb8e079a62dcb3aaa8b6c67c0f434a87ebf64ab0bcfb2fc14b55576b859f02206d37c2eb5fd04cfc9eb0534c76a28a98da251b84a931377cce307af39dfaed7483483045022100a497c64faea286ec4221f48628086dc6403fd7b60a23c4176e8ebbca15ae70dc0220754e20e968e96cf6421fd2a672c8c26d3bc6e19218cfc8fc2aa51fce026c14b1012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000" }
+ "3044022017b558a3cf5f0cb94269e2e927b29ed22bd2416abb8a7ce6de4d1256f359b93602202e9ca2b1a23ea3e69f433c704e327739e219804b8c188b1d52f74fd5a9de954c",
+ "3045022100af7a8b7c7ff2080c68995254cb66d64d9954edcc5baac3bb4f27ed2d29aaa6120220421c27da7a60574a9263f271e0f3bd34594ec6011095190022b3b54596ea03de",
+ "02000000000101542562b326c08e3a076d9cfca2be175041366591da334d8d513ff1686fd95a6002000000000100000001a00f0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500473044022017b558a3cf5f0cb94269e2e927b29ed22bd2416abb8a7ce6de4d1256f359b93602202e9ca2b1a23ea3e69f433c704e327739e219804b8c188b1d52f74fd5a9de954c83483045022100af7a8b7c7ff2080c68995254cb66d64d9954edcc5baac3bb4f27ed2d29aaa6120220421c27da7a60574a9263f271e0f3bd34594ec6011095190022b3b54596ea03de012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000" }
} );
// commitment tx with three outputs untrimmed (maximum feerate)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 4914;
+ chan.holder_dust_limit_satoshis = 546;
test_commitment!("3045022100b4b16d5f8cc9fc4c1aff48831e832a0d8990e133978a66e302c133550954a44d022073573ce127e2200d316f6b612803a5c0c97b8d20e1e44dbe2ac0dd2fb8c95244",
"3045022100d72638bc6308b88bb6d45861aae83e5b9ff6e10986546e13bce769c70036e2620220320be7c6d66d22f30b9fcd52af66531505b1310ca3b848c19285b38d8a1a8c19",
"02000000000101a9172908eace869cc35128c31fc2ab502f72e4dff31aab23e0244c4b04b11ab00000000000000000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100f43591c156038ba217756006bb3c55f7d113a325cdd7d9303c82115372858d68022016355b5aadf222bc8d12e426c75f4a03423917b2443a103eb2a498a3a2234374014730440220585dee80fafa264beac535c3c0bb5838ac348b156fdc982f86adc08dfc9bfd250220130abb82f9f295cc9ef423dcfef772fde2acd85d9df48cc538981d26a10a9c10012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000" }
} );
- // anchors: commitment tx with three outputs untrimmed (maximum feerate)
- chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
- chan.feerate_per_kw = 4893;
-
- test_commitment_with_anchors!("3045022100a8771147109e4d3f44a5976c3c3de98732bbb77308d21444dbe0d76faf06480e02200b4e916e850c3d1f918de87bbbbb07843ffea1d4658dfe060b6f9ccd96d34be8",
- "30440220086288faceab47461eb2d808e9e9b0cb3ffc24a03c2f18db7198247d38f10e58022031d1c2782a58c8c6ce187d0019eb47a83babdf3040e2caff299ab48f7e12b1fa",
- "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80054a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994a00f000000000000220020ce6e751274836ff59622a0d1e07f8831d80bd6730bd48581398bfadd2bb8da9ac0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a87856a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e04004730440220086288faceab47461eb2d808e9e9b0cb3ffc24a03c2f18db7198247d38f10e58022031d1c2782a58c8c6ce187d0019eb47a83babdf3040e2caff299ab48f7e12b1fa01483045022100a8771147109e4d3f44a5976c3c3de98732bbb77308d21444dbe0d76faf06480e02200b4e916e850c3d1f918de87bbbbb07843ffea1d4658dfe060b6f9ccd96d34be801475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", {
-
- { 0,
- "30450221008db80f8531104820b3e894492b4463f074f965b542e1b5c153ddfb108a5ea642022030b203d857a2b3581c2087a7bf17c95d04fadc1c6cdae88c620477f2dccb1ee4",
- "3045022100e5fbae857c47dbfc050a05924bd449fc9804798bd6442002c578437dc34450810220296589bc387645512345299e307116aaac4ce9fc752abcd1936b802d03526312",
- "02000000000101d515a15e9175fd315bb8d4e768f28684801a9e5a9acdfeba34f7b3b3b3a9ba1d0200000000010000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004830450221008db80f8531104820b3e894492b4463f074f965b542e1b5c153ddfb108a5ea642022030b203d857a2b3581c2087a7bf17c95d04fadc1c6cdae88c620477f2dccb1ee483483045022100e5fbae857c47dbfc050a05924bd449fc9804798bd6442002c578437dc34450810220296589bc387645512345299e307116aaac4ce9fc752abcd1936b802d03526312012004040404040404040404040404040404040404040404040404040404040404048d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6851b2756800000000" }
- } );
-
// commitment tx with two outputs untrimmed (minimum feerate)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 4915;
+ chan.holder_dust_limit_satoshis = 546;
test_commitment!("304402203a286936e74870ca1459c700c71202af0381910a6bfab687ef494ef1bc3e02c902202506c362d0e3bee15e802aa729bf378e051644648253513f1c085b264cc2a720",
"30450221008a953551f4d67cb4df3037207fc082ddaf6be84d417b0bd14c80aab66f1b01a402207508796dc75034b2dee876fe01dc05a08b019f3e5d689ac8842ade2f1befccf5",
"02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8002c0c62d0000000000160014cc1b07838e387deacd0e5232e1e8b49f4c29e484fa926a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e04004830450221008a953551f4d67cb4df3037207fc082ddaf6be84d417b0bd14c80aab66f1b01a402207508796dc75034b2dee876fe01dc05a08b019f3e5d689ac8842ade2f1befccf50147304402203a286936e74870ca1459c700c71202af0381910a6bfab687ef494ef1bc3e02c902202506c362d0e3bee15e802aa729bf378e051644648253513f1c085b264cc2a72001475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", {});
- // anchors: commitment tx with two outputs untrimmed (minimum feerate)
+ // anchors: commitment tx with two outputs untrimmed (minimum dust limit)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 4894;
+ chan.holder_dust_limit_satoshis = 4001;
test_commitment_with_anchors!("3045022100e784a66b1588575801e237d35e510fd92a81ae3a4a2a1b90c031ad803d07b3f3022021bc5f16501f167607d63b681442da193eb0a76b4b7fd25c2ed4f8b28fd35b95",
"30450221009f16ac85d232e4eddb3fcd750a68ebf0b58e3356eaada45d3513ede7e817bf4c02207c2b043b4e5f971261975406cb955219fa56bffe5d834a833694b5abc1ce4cfd",
// commitment tx with two outputs untrimmed (maximum feerate)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 9651180;
+ chan.holder_dust_limit_satoshis = 546;
test_commitment!("304402200a8544eba1d216f5c5e530597665fa9bec56943c0f66d98fc3d028df52d84f7002201e45fa5c6bc3a506cc2553e7d1c0043a9811313fc39c954692c0d47cfce2bbd3",
"3045022100e11b638c05c650c2f63a421d36ef8756c5ce82f2184278643520311cdf50aa200220259565fb9c8e4a87ccaf17f27a3b9ca4f20625754a0920d9c6c239d8156a11de",
"304402207e8d51e0c570a5868a78414f4e0cbfaed1106b171b9581542c30718ee4eb95ba02203af84194c97adf98898c9afe2f2ed4a7f8dba05a2dfab28ac9d9c604aa49a379",
"02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8001c0c62d0000000000160014cc1b07838e387deacd0e5232e1e8b49f4c29e484040047304402207e8d51e0c570a5868a78414f4e0cbfaed1106b171b9581542c30718ee4eb95ba02203af84194c97adf98898c9afe2f2ed4a7f8dba05a2dfab28ac9d9c604aa49a3790147304402202ade0142008309eb376736575ad58d03e5b115499709c6db0b46e36ff394b492022037b63d78d66404d6504d4c4ac13be346f3d1802928a6d3ad95a6a944227161a201475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", {});
- // anchors: commitment tx with one output untrimmed (minimum feerate)
+ // anchors: commitment tx with one output untrimmed (minimum dust limit)
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 6216010;
+ chan.holder_dust_limit_satoshis = 4001;
test_commitment_with_anchors!("30450221008fd5dbff02e4b59020d4cd23a3c30d3e287065fda75a0a09b402980adf68ccda022001e0b8b620cd915ddff11f1de32addf23d81d51b90e6841b2cb8dcaf3faa5ecf",
"30450221009ad80792e3038fe6968d12ff23e6888a565c3ddd065037f357445f01675d63f3022018384915e5f1f4ae157e15debf4f49b61c8d9d2b073c7d6f97c4a68caa3ed4c1",
// commitment tx with fee greater than funder amount
chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
chan.feerate_per_kw = 9651936;
+ chan.holder_dust_limit_satoshis = 546;
test_commitment!("304402202ade0142008309eb376736575ad58d03e5b115499709c6db0b46e36ff394b492022037b63d78d66404d6504d4c4ac13be346f3d1802928a6d3ad95a6a944227161a2",
"304402207e8d51e0c570a5868a78414f4e0cbfaed1106b171b9581542c30718ee4eb95ba02203af84194c97adf98898c9afe2f2ed4a7f8dba05a2dfab28ac9d9c604aa49a379",
"02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80074a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994d007000000000000220020fe0598d74fee2205cc3672e6e6647706b4f3099713b4661b62482c3addd04a5e881300000000000022002018e40f9072c44350f134bdc887bab4d9bdfc8aa468a25616c80e21757ba5dac7881300000000000022002018e40f9072c44350f134bdc887bab4d9bdfc8aa468a25616c80e21757ba5dac7c0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994aae9c6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100c37ac4fc8538677631230c4b286f36b6f54c51fb4b34ef0bd0ba219ba47452630220278e09a745454ea380f3694392ed113762c68dd209b48360f547541088be9e4501483045022100c592f6b80d35b4f5d1e3bc9788f51141a0065be6013bad53a1977f7c444651660220278ac06ead9016bfb8dc476f186eabace2b02793b2f308442f5b0d5f24a6894801475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", {
{ 0,
- "304402202060a5acb12105e92f27d7b86e6caf1e003d9d82068338e5a8a9a0d14cba11260220030ca4dba8fad24a2e395906220c991eccd5369bc4b0f216d217b5f86d1fc61d",
- "3044022044f5425fe630fa614f349f55642e4a0b76e2583054b21543821660d9e8f3735702207f70424835b541874ca8bf0443cca4028afa2f6c03a17b0688df85d5c44eeefc",
- "02000000000101aa443fb63abc1e8c754f98a7b96c27cb02b21d891d1242a16b630dc32c2afe29020000000001000000011e070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402202060a5acb12105e92f27d7b86e6caf1e003d9d82068338e5a8a9a0d14cba11260220030ca4dba8fad24a2e395906220c991eccd5369bc4b0f216d217b5f86d1fc61d83473044022044f5425fe630fa614f349f55642e4a0b76e2583054b21543821660d9e8f3735702207f70424835b541874ca8bf0443cca4028afa2f6c03a17b0688df85d5c44eeefc012001010101010101010101010101010101010101010101010101010101010101018d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac6851b2756800000000" },
+ "3045022100de8a0649d54fd2e4fc04502c77df9b65da839bbd01854f818f129338b99564b2022009528dbb12c00e874cb2149b1dccc600c69ea5e4042ebf584984fcb029c2d1ec",
+ "304402203e7c2622fa3ca29355d37a0ea991bfd7cdb54e6122a1d98d3229d092131f55cd022055263f7f8f32f4cd2f86da63ca106bd7badf0b19ee9833d80cd3b9216eeafd74",
+ "02000000000101aa443fb63abc1e8c754f98a7b96c27cb02b21d891d1242a16b630dc32c2afe2902000000000100000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100de8a0649d54fd2e4fc04502c77df9b65da839bbd01854f818f129338b99564b2022009528dbb12c00e874cb2149b1dccc600c69ea5e4042ebf584984fcb029c2d1ec8347304402203e7c2622fa3ca29355d37a0ea991bfd7cdb54e6122a1d98d3229d092131f55cd022055263f7f8f32f4cd2f86da63ca106bd7badf0b19ee9833d80cd3b9216eeafd74012001010101010101010101010101010101010101010101010101010101010101018d76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac6851b2756800000000" },
{ 1,
- "304402206fde7eb6d7a47fdc63705d3db2169054e229f10342dea66f150b163381f48a0802201be28509c2de9be4b7ab72c569c6fd51c0ce0904fea459142f31d442cd043eb8",
- "3045022100ad0236a78dbd029d3a8f583f7f82ee62892273d45303d00ef5a03fecf8903a36022004b2db33f8ff2f4a08ca6127c9cbfd9144c691a2feb9287e36ae6bc7c83c5a5f",
- "02000000000101aa443fb63abc1e8c754f98a7b96c27cb02b21d891d1242a16b630dc32c2afe2903000000000100000001e0120000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402206fde7eb6d7a47fdc63705d3db2169054e229f10342dea66f150b163381f48a0802201be28509c2de9be4b7ab72c569c6fd51c0ce0904fea459142f31d442cd043eb883483045022100ad0236a78dbd029d3a8f583f7f82ee62892273d45303d00ef5a03fecf8903a36022004b2db33f8ff2f4a08ca6127c9cbfd9144c691a2feb9287e36ae6bc7c83c5a5f01008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9142002cc93ebefbb1b73f0af055dcc27a0b504ad7688ac6851b27568f9010000" },
+ "3045022100de6eee8474376ea316d007b33103b4543a46bdf6fda5cbd5902b28a5bc14584f022002989e7b4f7813b77acbe4babcf96d7ffbbe0bf14cba24672364f8e591479edb",
+ "3045022100c10688346a9d84647bde7027da07f0d79c6d4129307e4c6c9aea7bdbf25ac3350220269104209793c32c47491698c4e46ebea9c3293a1e4403f9abda39f79698f6b5",
+ "02000000000101aa443fb63abc1e8c754f98a7b96c27cb02b21d891d1242a16b630dc32c2afe290300000000010000000188130000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100de6eee8474376ea316d007b33103b4543a46bdf6fda5cbd5902b28a5bc14584f022002989e7b4f7813b77acbe4babcf96d7ffbbe0bf14cba24672364f8e591479edb83483045022100c10688346a9d84647bde7027da07f0d79c6d4129307e4c6c9aea7bdbf25ac3350220269104209793c32c47491698c4e46ebea9c3293a1e4403f9abda39f79698f6b501008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9142002cc93ebefbb1b73f0af055dcc27a0b504ad7688ac6851b27568f9010000" },
{ 2,
- "304402205eebc78d8ae6a36c27ef80172359eb757fb18e99fa75b28c37ffe3444b967bc7022060a01c33398d4d8244c42c762fb699e9f61c1f034ff976df2c94350c5a6032a7",
- "3045022100ad3fd523594e1b876316401774a30ee6c48bb7fa0efd768bf9a2d022201311ff02207bed627ed8e01041137f03dbaf03c836970be27a4d50f69d90cf1282ff2815e3",
- "02000000000101aa443fb63abc1e8c754f98a7b96c27cb02b21d891d1242a16b630dc32c2afe2904000000000100000001e0120000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402205eebc78d8ae6a36c27ef80172359eb757fb18e99fa75b28c37ffe3444b967bc7022060a01c33398d4d8244c42c762fb699e9f61c1f034ff976df2c94350c5a6032a783483045022100ad3fd523594e1b876316401774a30ee6c48bb7fa0efd768bf9a2d022201311ff02207bed627ed8e01041137f03dbaf03c836970be27a4d50f69d90cf1282ff2815e301008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9142002cc93ebefbb1b73f0af055dcc27a0b504ad7688ac6851b27568fa010000" }
+ "3045022100fe87da8124ceecbcabb9d599c5339f40277c7c7406514fafbccbf180c7c09cf40220429c7fb6d0fd3705e931ab1219ab0432af38ae4d676008cc1964fbeb8cd35d2e",
+ "3044022040ac769a851da31d8e4863e5f94719204f716c82a1ce6d6c52193d9a33b84bce022035df97b078ce80f20dca2109e4c6075af0b50148811452e7290e68b2680fced4",
+ "02000000000101aa443fb63abc1e8c754f98a7b96c27cb02b21d891d1242a16b630dc32c2afe290400000000010000000188130000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100fe87da8124ceecbcabb9d599c5339f40277c7c7406514fafbccbf180c7c09cf40220429c7fb6d0fd3705e931ab1219ab0432af38ae4d676008cc1964fbeb8cd35d2e83473044022040ac769a851da31d8e4863e5f94719204f716c82a1ce6d6c52193d9a33b84bce022035df97b078ce80f20dca2109e4c6075af0b50148811452e7290e68b2680fced401008876a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9142002cc93ebefbb1b73f0af055dcc27a0b504ad7688ac6851b27568fa010000" }
} );
}
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let config = UserConfig::default();
let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider,
- node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+ node_b_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config, 0, 42).unwrap();
let mut channel_type_features = ChannelTypeFeatures::only_static_remote_key();
channel_type_features.set_zero_conf_required();
open_channel_msg.channel_type = Some(channel_type_features);
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
let res = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider,
- node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42);
+ node_b_node_id, &channelmanager::provided_init_features(), &open_channel_msg, 7, &config, 0, &&logger, 42);
assert!(res.is_ok());
}
}
// construct one themselves.
use ln::{inbound_payment, PaymentHash, PaymentPreimage, PaymentSecret};
use ln::channel::{Channel, ChannelError, ChannelUpdateStatus, UpdateFulfillCommitFetch};
-use ln::features::{ChannelTypeFeatures, InitFeatures, NodeFeatures};
+use ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
+#[cfg(any(feature = "_test_utils", test))]
+use ln::features::InvoiceFeatures;
use routing::router::{PaymentParameters, Route, RouteHop, RoutePath, RouteParameters};
use ln::msgs;
-use ln::msgs::NetAddress;
use ln::onion_utils;
use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, MAX_VALUE_MSAT};
use ln::wire::Encode;
use util::config::{UserConfig, ChannelConfig};
use util::events::{EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination};
use util::{byte_utils, events};
+use util::wakers::{Future, Notifier};
use util::scid_utils::fake_scid;
use util::ser::{BigSize, FixedLengthReader, Readable, ReadableArgs, MaybeReadable, Writeable, Writer, VecWriter};
use util::logger::{Level, Logger};
use core::{cmp, mem};
use core::cell::RefCell;
use io::Read;
-use sync::{Arc, Condvar, Mutex, MutexGuard, RwLock, RwLockReadGuard};
+use sync::{Arc, Mutex, MutexGuard, RwLock, RwLockReadGuard};
use core::sync::atomic::{AtomicUsize, Ordering};
use core::time::Duration;
use core::ops::Deref;
-#[cfg(any(test, feature = "std"))]
-use std::time::Instant;
-use util::crypto::sign;
-
// We hold various information about HTLC relay in the HTLC objects in Channel itself:
//
// Upon receipt of an HTLC from a peer, we'll give it a PendingHTLCStatus indicating if it should
/// keeping additional state.
probing_cookie_secret: [u8; 32],
- /// Used to track the last value sent in a node_announcement "timestamp" field. We ensure this
- /// value increases strictly since we don't assume access to a time source.
- last_node_announcement_serial: AtomicUsize,
-
/// The highest block timestamp we've seen, which is usually a good guess at the current time.
/// Assuming most miners are generating blocks with reasonable timestamps, this shouldn't be
/// very far in the past, and can only ever be up to two hours in the future.
/// Taken first everywhere where we are making changes before any other locks.
/// When acquiring this lock in read mode, rather than acquiring it directly, call
/// `PersistenceNotifierGuard::notify_on_drop(..)` and pass the lock to it, to ensure the
- /// PersistenceNotifier the lock contains sends out a notification when the lock is released.
+ /// Notifier the lock contains sends out a notification when the lock is released.
total_consistency_lock: RwLock<()>,
- persistence_notifier: PersistenceNotifier,
+ persistence_notifier: Notifier,
keys_manager: K,
/// notify or not based on whether relevant changes have been made, providing a closure to
/// `optionally_notify` which returns a `NotifyOption`.
struct PersistenceNotifierGuard<'a, F: Fn() -> NotifyOption> {
- persistence_notifier: &'a PersistenceNotifier,
+ persistence_notifier: &'a Notifier,
should_persist: F,
// We hold onto this result so the lock doesn't get released immediately.
_read_guard: RwLockReadGuard<'a, ()>,
}
impl<'a> PersistenceNotifierGuard<'a, fn() -> NotifyOption> { // We don't care what the concrete F is here, it's unused
- fn notify_on_drop(lock: &'a RwLock<()>, notifier: &'a PersistenceNotifier) -> PersistenceNotifierGuard<'a, impl Fn() -> NotifyOption> {
+ fn notify_on_drop(lock: &'a RwLock<()>, notifier: &'a Notifier) -> PersistenceNotifierGuard<'a, impl Fn() -> NotifyOption> {
PersistenceNotifierGuard::optionally_notify(lock, notifier, || -> NotifyOption { NotifyOption::DoPersist })
}
- fn optionally_notify<F: Fn() -> NotifyOption>(lock: &'a RwLock<()>, notifier: &'a PersistenceNotifier, persist_check: F) -> PersistenceNotifierGuard<'a, F> {
+ fn optionally_notify<F: Fn() -> NotifyOption>(lock: &'a RwLock<()>, notifier: &'a Notifier, persist_check: F) -> PersistenceNotifierGuard<'a, F> {
let read_guard = lock.read().unwrap();
PersistenceNotifierGuard {
probing_cookie_secret: keys_manager.get_secure_random_bytes(),
- last_node_announcement_serial: AtomicUsize::new(0),
highest_seen_timestamp: AtomicUsize::new(0),
per_peer_state: RwLock::new(HashMap::new()),
pending_events: Mutex::new(Vec::new()),
pending_background_events: Mutex::new(Vec::new()),
total_consistency_lock: RwLock::new(()),
- persistence_notifier: PersistenceNotifier::new(),
+ persistence_notifier: Notifier::new(),
keys_manager,
})
}
- #[allow(dead_code)]
- // Messages of up to 64KB should never end up more than half full with addresses, as that would
- // be absurd. We ensure this by checking that at least 100 (our stated public contract on when
- // broadcast_node_announcement panics) of the maximum-length addresses would fit in a 64KB
- // message...
- const HALF_MESSAGE_IS_ADDRS: u32 = ::core::u16::MAX as u32 / (NetAddress::MAX_LEN as u32 + 1) / 2;
- #[deny(const_err)]
- #[allow(dead_code)]
- // ...by failing to compile if the number of addresses that would be half of a message is
- // smaller than 100:
- const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 100;
-
- /// Regenerates channel_announcements and generates a signed node_announcement from the given
- /// arguments, providing them in corresponding events via
- /// [`get_and_clear_pending_msg_events`], if at least one public channel has been confirmed
- /// on-chain. This effectively re-broadcasts all channel announcements and sends our node
- /// announcement to ensure that the lightning P2P network is aware of the channels we have and
- /// our network addresses.
- ///
- /// `rgb` is a node "color" and `alias` is a printable human-readable string to describe this
- /// node to humans. They carry no in-protocol meaning.
- ///
- /// `addresses` represent the set (possibly empty) of socket addresses on which this node
- /// accepts incoming connections. These will be included in the node_announcement, publicly
- /// tying these addresses together and to this node. If you wish to preserve user privacy,
- /// addresses should likely contain only Tor Onion addresses.
- ///
- /// Panics if `addresses` is absurdly large (more than 100).
- ///
- /// [`get_and_clear_pending_msg_events`]: MessageSendEventsProvider::get_and_clear_pending_msg_events
- pub fn broadcast_node_announcement(&self, rgb: [u8; 3], alias: [u8; 32], mut addresses: Vec<NetAddress>) {
- let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
-
- if addresses.len() > 100 {
- panic!("More than half the message size was taken up by public addresses!");
- }
-
- // While all existing nodes handle unsorted addresses just fine, the spec requires that
- // addresses be sorted for future compatibility.
- addresses.sort_by_key(|addr| addr.get_id());
-
- let announcement = msgs::UnsignedNodeAnnouncement {
- features: NodeFeatures::known(),
- timestamp: self.last_node_announcement_serial.fetch_add(1, Ordering::AcqRel) as u32,
- node_id: self.get_our_node_id(),
- rgb, alias, addresses,
- excess_address_data: Vec::new(),
- excess_data: Vec::new(),
- };
- let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);
- let node_announce_sig = sign(&self.secp_ctx, &msghash, &self.our_network_key);
-
- let mut channel_state_lock = self.channel_state.lock().unwrap();
- let channel_state = &mut *channel_state_lock;
-
- let mut announced_chans = false;
- for (_, chan) in channel_state.by_id.iter() {
- if let Some(msg) = chan.get_signed_channel_announcement(self.get_our_node_id(), self.genesis_hash.clone(), self.best_block.read().unwrap().height()) {
- channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelAnnouncement {
- msg,
- update_msg: match self.get_channel_update_for_broadcast(chan) {
- Ok(msg) => msg,
- Err(_) => continue,
- },
- });
- announced_chans = true;
- } else {
- // If the channel is not public or has not yet reached channel_ready, check the
- // next channel. If we don't yet have any public channels, we'll skip the broadcast
- // below as peers may not accept it without channels on chain first.
- }
- }
-
- if announced_chans {
- channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastNodeAnnouncement {
- msg: msgs::NodeAnnouncement {
- signature: node_announce_sig,
- contents: announcement
- },
- });
- }
- }
-
/// Atomically updates the [`ChannelConfig`] for the given channels.
///
/// Once the updates are applied, each eligible channel (advertised with a known short channel
counterparty_node_id: &PublicKey
) {
for (htlc_src, payment_hash) in htlcs_to_fail.drain(..) {
- match htlc_src {
- HTLCSource::PreviousHopData(HTLCPreviousHopData { .. }) => {
- let (failure_code, onion_failure_data) =
- match self.channel_state.lock().unwrap().by_id.entry(channel_id) {
- hash_map::Entry::Occupied(chan_entry) => {
- self.get_htlc_inbound_temp_fail_err_and_data(0x1000|7, &chan_entry.get())
- },
- hash_map::Entry::Vacant(_) => (0x4000|10, Vec::new())
- };
- let channel_state = self.channel_state.lock().unwrap();
+ let mut channel_state = self.channel_state.lock().unwrap();
+ let (failure_code, onion_failure_data) =
+ match channel_state.by_id.entry(channel_id) {
+ hash_map::Entry::Occupied(chan_entry) => {
+ self.get_htlc_inbound_temp_fail_err_and_data(0x1000|7, &chan_entry.get())
+ },
+ hash_map::Entry::Vacant(_) => (0x4000|10, Vec::new())
+ };
- let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id.clone()), channel_id };
- self.fail_htlc_backwards_internal(channel_state, htlc_src, &payment_hash, HTLCFailReason::Reason { failure_code, data: onion_failure_data }, receiver)
- },
- HTLCSource::OutboundRoute { session_priv, payment_id, path, payment_params, .. } => {
- let mut session_priv_bytes = [0; 32];
- session_priv_bytes.copy_from_slice(&session_priv[..]);
- let mut outbounds = self.pending_outbound_payments.lock().unwrap();
- if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) {
- if payment.get_mut().remove(&session_priv_bytes, Some(&path)) && !payment.get().is_fulfilled() {
- let retry = if let Some(payment_params_data) = payment_params {
- let path_last_hop = path.last().expect("Outbound payments must have had a valid path");
- Some(RouteParameters {
- payment_params: payment_params_data,
- final_value_msat: path_last_hop.fee_msat,
- final_cltv_expiry_delta: path_last_hop.cltv_expiry_delta,
- })
- } else { None };
- let mut pending_events = self.pending_events.lock().unwrap();
- pending_events.push(events::Event::PaymentPathFailed {
- payment_id: Some(payment_id),
- payment_hash,
- rejected_by_dest: false,
- network_update: None,
- all_paths_failed: payment.get().remaining_parts() == 0,
- path: path.clone(),
- short_channel_id: None,
- retry,
- #[cfg(test)]
- error_code: None,
- #[cfg(test)]
- error_data: None,
- });
- if payment.get().abandoned() && payment.get().remaining_parts() == 0 {
- pending_events.push(events::Event::PaymentFailed {
- payment_id,
- payment_hash: payment.get().payment_hash().expect("PendingOutboundPayments::RetriesExceeded always has a payment hash set"),
- });
- payment.remove();
- }
- }
- } else {
- log_trace!(self.logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0));
- }
- },
- };
+ let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id.clone()), channel_id };
+ self.fail_htlc_backwards_internal(channel_state, htlc_src, &payment_hash, HTLCFailReason::Reason { failure_code, data: onion_failure_data }, receiver);
}
}
events::Event::PaymentPathFailed {
payment_id: Some(payment_id),
payment_hash: payment_hash.clone(),
- rejected_by_dest: !payment_retryable,
+ payment_failed_permanently: !payment_retryable,
network_update,
all_paths_failed,
path: path.clone(),
// channel here as we apparently can't relay through them anyway.
let scid = path.first().unwrap().short_channel_id;
retry.as_mut().map(|r| r.payment_params.previously_failed_channels.push(scid));
- events::Event::PaymentPathFailed {
- payment_id: Some(payment_id),
- payment_hash: payment_hash.clone(),
- rejected_by_dest: path.len() == 1,
- network_update: None,
- all_paths_failed,
- path: path.clone(),
- short_channel_id: Some(scid),
- retry,
+
+ if self.payment_is_probe(payment_hash, &payment_id) {
+ events::Event::ProbeFailed {
+ payment_id: payment_id,
+ payment_hash: payment_hash.clone(),
+ path: path.clone(),
+ short_channel_id: Some(scid),
+ }
+ } else {
+ events::Event::PaymentPathFailed {
+ payment_id: Some(payment_id),
+ payment_hash: payment_hash.clone(),
+ payment_failed_permanently: false,
+ network_update: None,
+ all_paths_failed,
+ path: path.clone(),
+ short_channel_id: Some(scid),
+ retry,
#[cfg(test)]
- error_code: Some(*failure_code),
+ error_code: Some(*failure_code),
#[cfg(test)]
- error_data: Some(data.clone()),
+ error_data: Some(data.clone()),
+ }
}
}
};
if were_node_one == msg_from_node_one {
return Ok(NotifyOption::SkipPersist);
} else {
+ log_debug!(self.logger, "Received channel_update for channel {}.", log_bytes!(chan_id));
try_chan_entry!(self, chan.get_mut().channel_update(&msg), channel_state, chan);
}
},
///
/// An [`EventHandler`] may safely call back to the provider in order to handle an event.
/// However, it must not call [`Writeable::write`] as doing so would result in a deadlock.
- ///
- /// Pending events are persisted as part of [`ChannelManager`]. While these events are cleared
- /// when processed, an [`EventHandler`] must be able to handle previously seen events when
- /// restarting from an old state.
fn process_pending_events<H: Deref>(&self, handler: H) where H::Target: EventHandler {
PersistenceNotifierGuard::optionally_notify(&self.total_consistency_lock, &self.persistence_notifier, || {
let mut result = NotifyOption::SkipPersist;
}
}
}
- max_time!(self.last_node_announcement_serial);
max_time!(self.highest_seen_timestamp);
let mut payment_secrets = self.pending_inbound_payments.lock().unwrap();
payment_secrets.retain(|_, inbound_payment| {
self.persistence_notifier.wait()
}
+ /// Gets a [`Future`] that completes when a persistable update is available. Note that
+ /// callbacks registered on the [`Future`] MUST NOT call back into this [`ChannelManager`] and
+ /// should instead register actions to be taken later.
+ pub fn get_persistable_update_future(&self) -> Future {
+ self.persistence_notifier.get_future()
+ }
+
#[cfg(any(test, feature = "_test_utils"))]
pub fn get_persistence_condvar_value(&self) -> bool {
- let mutcond = &self.persistence_notifier.persistence_lock;
- let &(ref mtx, _) = mutcond;
- let guard = mtx.lock().unwrap();
- *guard
+ self.persistence_notifier.notify_pending()
}
/// Gets the latest best block which was connected either via the [`chain::Listen`] or
&events::MessageSendEvent::SendClosingSigned { ref node_id, .. } => node_id != counterparty_node_id,
&events::MessageSendEvent::SendShutdown { ref node_id, .. } => node_id != counterparty_node_id,
&events::MessageSendEvent::SendChannelReestablish { ref node_id, .. } => node_id != counterparty_node_id,
+ &events::MessageSendEvent::SendChannelAnnouncement { ref node_id, .. } => node_id != counterparty_node_id,
&events::MessageSendEvent::BroadcastChannelAnnouncement { .. } => true,
- &events::MessageSendEvent::BroadcastNodeAnnouncement { .. } => true,
&events::MessageSendEvent::BroadcastChannelUpdate { .. } => true,
&events::MessageSendEvent::SendChannelUpdate { ref node_id, .. } => node_id != counterparty_node_id,
&events::MessageSendEvent::HandleError { ref node_id, .. } => node_id != counterparty_node_id,
}
}
- fn peer_connected(&self, counterparty_node_id: &PublicKey, init_msg: &msgs::Init) {
+ fn peer_connected(&self, counterparty_node_id: &PublicKey, init_msg: &msgs::Init) -> Result<(), ()> {
+ if !init_msg.features.supports_static_remote_key() {
+ log_debug!(self.logger, "Peer {} does not support static remote key, disconnecting with no_connection_possible", log_pubkey!(counterparty_node_id));
+ return Err(());
+ }
+
log_debug!(self.logger, "Generating channel_reestablish events for {}", log_pubkey!(counterparty_node_id));
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
let channel_state = &mut *channel_state_lock;
let pending_msg_events = &mut channel_state.pending_msg_events;
channel_state.by_id.retain(|_, chan| {
- if chan.get_counterparty_node_id() == *counterparty_node_id {
+ let retain = if chan.get_counterparty_node_id() == *counterparty_node_id {
if !chan.have_received_message() {
// If we created this (outbound) channel while we were disconnected from the
// peer we probably failed to send the open_channel message, which is now
});
true
}
- } else { true }
+ } else { true };
+ if retain && chan.get_counterparty_node_id() != *counterparty_node_id {
+ if let Some(msg) = chan.get_signed_channel_announcement(self.get_our_node_id(), self.genesis_hash.clone(), self.best_block.read().unwrap().height()) {
+ if let Ok(update_msg) = self.get_channel_update_for_broadcast(chan) {
+ pending_msg_events.push(events::MessageSendEvent::SendChannelAnnouncement {
+ node_id: *counterparty_node_id,
+ msg, update_msg,
+ });
+ }
+ }
+ }
+ retain
});
//TODO: Also re-broadcast announcement_signatures
+ Ok(())
}
fn handle_error(&self, counterparty_node_id: &PublicKey, msg: &msgs::ErrorMessage) {
let _ = self.force_close_channel_with_peer(&msg.channel_id, counterparty_node_id, Some(&msg.data), true);
}
}
-}
-/// Used to signal to the ChannelManager persister that the manager needs to be re-persisted to
-/// disk/backups, through `await_persistable_update_timeout` and `await_persistable_update`.
-struct PersistenceNotifier {
- /// Users won't access the persistence_lock directly, but rather wait on its bool using
- /// `wait_timeout` and `wait`.
- persistence_lock: (Mutex<bool>, Condvar),
-}
-
-impl PersistenceNotifier {
- fn new() -> Self {
- Self {
- persistence_lock: (Mutex::new(false), Condvar::new()),
- }
+ fn provided_node_features(&self) -> NodeFeatures {
+ provided_node_features()
}
- fn wait(&self) {
- loop {
- let &(ref mtx, ref cvar) = &self.persistence_lock;
- let mut guard = mtx.lock().unwrap();
- if *guard {
- *guard = false;
- return;
- }
- guard = cvar.wait(guard).unwrap();
- let result = *guard;
- if result {
- *guard = false;
- return
- }
- }
+ fn provided_init_features(&self, _their_init_features: &PublicKey) -> InitFeatures {
+ provided_init_features()
}
+}
- #[cfg(any(test, feature = "std"))]
- fn wait_timeout(&self, max_wait: Duration) -> bool {
- let current_time = Instant::now();
- loop {
- let &(ref mtx, ref cvar) = &self.persistence_lock;
- let mut guard = mtx.lock().unwrap();
- if *guard {
- *guard = false;
- return true;
- }
- guard = cvar.wait_timeout(guard, max_wait).unwrap().0;
- // Due to spurious wakeups that can happen on `wait_timeout`, here we need to check if the
- // desired wait time has actually passed, and if not then restart the loop with a reduced wait
- // time. Note that this logic can be highly simplified through the use of
- // `Condvar::wait_while` and `Condvar::wait_timeout_while`, if and when our MSRV is raised to
- // 1.42.0.
- let elapsed = current_time.elapsed();
- let result = *guard;
- if result || elapsed >= max_wait {
- *guard = false;
- return result;
- }
- match max_wait.checked_sub(elapsed) {
- None => return result,
- Some(_) => continue
- }
- }
- }
+/// Fetches the set of [`NodeFeatures`] flags which are provided by or required by
+/// [`ChannelManager`].
+pub fn provided_node_features() -> NodeFeatures {
+ provided_init_features().to_context()
+}
- // Signal to the ChannelManager persister that there are updates necessitating persisting to disk.
- fn notify(&self) {
- let &(ref persist_mtx, ref cnd) = &self.persistence_lock;
- let mut persistence_lock = persist_mtx.lock().unwrap();
- *persistence_lock = true;
- mem::drop(persistence_lock);
- cnd.notify_all();
- }
+/// Fetches the set of [`InvoiceFeatures`] flags which are provided by or required by
+/// [`ChannelManager`].
+///
+/// Note that the invoice feature flags can vary depending on if the invoice is a "phantom invoice"
+/// or not. Thus, this method is not public.
+#[cfg(any(feature = "_test_utils", test))]
+pub fn provided_invoice_features() -> InvoiceFeatures {
+ provided_init_features().to_context()
+}
+
+/// Fetches the set of [`ChannelFeatures`] flags which are provided by or required by
+/// [`ChannelManager`].
+pub fn provided_channel_features() -> ChannelFeatures {
+ provided_init_features().to_context()
+}
+
+/// Fetches the set of [`InitFeatures`] flags which are provided by or required by
+/// [`ChannelManager`].
+pub fn provided_init_features() -> InitFeatures {
+ // Note that if new features are added here which other peers may (eventually) require, we
+ // should also add the corresponding (optional) bit to the ChannelMessageHandler impl for
+ // ErroringMessageHandler.
+ let mut features = InitFeatures::empty();
+ features.set_data_loss_protect_optional();
+ features.set_upfront_shutdown_script_optional();
+ features.set_variable_length_onion_required();
+ features.set_static_remote_key_required();
+ features.set_payment_secret_required();
+ features.set_basic_mpp_optional();
+ features.set_wumbo_optional();
+ features.set_shutdown_any_segwit_optional();
+ features.set_channel_type_optional();
+ features.set_scid_privacy_optional();
+ features.set_zero_conf_optional();
+ features
}
const SERIALIZATION_VERSION: u8 = 1;
}
}
- (self.last_node_announcement_serial.load(Ordering::Acquire) as u32).write(writer)?;
+ // Prior to 0.0.111 we tracked node_announcement serials here, however that now happens in
+ // `PeerManager`, and thus we simply write the `highest_seen_timestamp` twice, which is
+ // likely to be identical.
+ (self.highest_seen_timestamp.load(Ordering::Acquire) as u32).write(writer)?;
(self.highest_seen_timestamp.load(Ordering::Acquire) as u32).write(writer)?;
(pending_inbound_payments.len() as u64).write(writer)?;
}
}
- let last_node_announcement_serial: u32 = Readable::read(reader)?;
+ let _last_node_announcement_serial: u32 = Readable::read(reader)?; // Only used < 0.0.111
let highest_seen_timestamp: u32 = Readable::read(reader)?;
let pending_inbound_payment_count: u64 = Readable::read(reader)?;
our_network_pubkey,
secp_ctx,
- last_node_announcement_serial: AtomicUsize::new(last_node_announcement_serial as usize),
highest_seen_timestamp: AtomicUsize::new(highest_seen_timestamp as usize),
per_peer_state: RwLock::new(per_peer_state),
pending_events: Mutex::new(pending_events_read),
pending_background_events: Mutex::new(pending_background_events_read),
total_consistency_lock: RwLock::new(()),
- persistence_notifier: PersistenceNotifier::new(),
+ persistence_notifier: Notifier::new(),
keys_manager: args.keys_manager,
logger: args.logger,
use core::time::Duration;
use core::sync::atomic::Ordering;
use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
- use ln::channelmanager::{PaymentId, PaymentSendFailure};
- use ln::channelmanager::inbound_payment;
- use ln::features::InitFeatures;
+ use ln::channelmanager::{self, inbound_payment, PaymentId, PaymentSendFailure};
use ln::functional_test_utils::*;
use ln::msgs;
use ln::msgs::ChannelMessageHandler;
use util::test_utils;
use chain::keysinterface::KeysInterface;
- #[cfg(feature = "std")]
- #[test]
- fn test_wait_timeout() {
- use ln::channelmanager::PersistenceNotifier;
- use sync::Arc;
- use core::sync::atomic::AtomicBool;
- use std::thread;
-
- let persistence_notifier = Arc::new(PersistenceNotifier::new());
- let thread_notifier = Arc::clone(&persistence_notifier);
-
- let exit_thread = Arc::new(AtomicBool::new(false));
- let exit_thread_clone = exit_thread.clone();
- thread::spawn(move || {
- loop {
- let &(ref persist_mtx, ref cnd) = &thread_notifier.persistence_lock;
- let mut persistence_lock = persist_mtx.lock().unwrap();
- *persistence_lock = true;
- cnd.notify_all();
-
- if exit_thread_clone.load(Ordering::SeqCst) {
- break
- }
- }
- });
-
- // Check that we can block indefinitely until updates are available.
- let _ = persistence_notifier.wait();
-
- // Check that the PersistenceNotifier will return after the given duration if updates are
- // available.
- loop {
- if persistence_notifier.wait_timeout(Duration::from_millis(100)) {
- break
- }
- }
-
- exit_thread.store(true, Ordering::SeqCst);
-
- // Check that the PersistenceNotifier will return after the given duration even if no updates
- // are available.
- loop {
- if !persistence_notifier.wait_timeout(Duration::from_millis(100)) {
- break
- }
- }
- }
-
#[test]
fn test_notify_limits() {
// Check that a few cases which don't require the persistence of a new ChannelManager,
assert!(nodes[1].node.await_persistable_update_timeout(Duration::from_millis(1)));
assert!(nodes[2].node.await_persistable_update_timeout(Duration::from_millis(1)));
- let mut chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let mut chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// We check that the channel info nodes have doesn't change too early, even though we try
// to connect messages with new values
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);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// First, send a partial MPP payment.
let (route, our_payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], 100_000);
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);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let scorer = test_utils::TestScorer::with_penalty(0);
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
let payer_pubkey = nodes[0].node.get_our_node_id();
let payee_pubkey = nodes[1].node.get_our_node_id();
- nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None });
- nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None });
+ nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
- let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known());
+ let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], channelmanager::provided_init_features(), channelmanager::provided_init_features());
let route_params = RouteParameters {
payment_params: PaymentParameters::for_keysend(payee_pubkey),
final_value_msat: 10000,
let payer_pubkey = nodes[0].node.get_our_node_id();
let payee_pubkey = nodes[1].node.get_our_node_id();
- nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None });
- nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None });
+ nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
- let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known());
+ let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], channelmanager::provided_init_features(), channelmanager::provided_init_features());
let route_params = RouteParameters {
payment_params: PaymentParameters::for_keysend(payee_pubkey),
final_value_msat: 10000,
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
- let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
- let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
- let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+ let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
+ let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
+ let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
+ let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
// Marshall an MPP route.
let (mut route, payment_hash, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[3], 100000);
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None).unwrap();
let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel);
let (temporary_channel_id, tx, _funding_output) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 1_000_000, 42);
let channel_id = &tx.txid().into_inner();
update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &nodes_0_update, &nodes_1_update);
nodes[0].node.close_channel(channel_id, &nodes[1].node.get_our_node_id()).unwrap();
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()));
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()));
let nodes_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &nodes_1_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &nodes_1_shutdown);
let closing_signed_node_0 = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id());
nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &closing_signed_node_0);
use chain::Listen;
use chain::chainmonitor::{ChainMonitor, Persist};
use chain::keysinterface::{KeysManager, KeysInterface, InMemorySigner};
- use ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage};
+ use ln::channelmanager::{self, BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage};
use ln::features::{InitFeatures, InvoiceFeatures};
use ln::functional_test_utils::*;
use ln::msgs::{ChannelMessageHandler, Init};
});
let node_b_holder = NodeHolder { node: &node_b };
- node_a.peer_connected(&node_b.get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
- node_b.peer_connected(&node_a.get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None });
+ node_a.peer_connected(&node_b.get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ node_b.peer_connected(&node_a.get_our_node_id(), &Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
node_a.create_channel(node_b.get_our_node_id(), 8_000_000, 100_000_000, 42, None).unwrap();
- node_b.handle_open_channel(&node_a.get_our_node_id(), InitFeatures::known(), &get_event_msg!(node_a_holder, MessageSendEvent::SendOpenChannel, node_b.get_our_node_id()));
- node_a.handle_accept_channel(&node_b.get_our_node_id(), InitFeatures::known(), &get_event_msg!(node_b_holder, MessageSendEvent::SendAcceptChannel, node_a.get_our_node_id()));
+ node_b.handle_open_channel(&node_a.get_our_node_id(), channelmanager::provided_init_features(), &get_event_msg!(node_a_holder, MessageSendEvent::SendOpenChannel, node_b.get_our_node_id()));
+ node_a.handle_accept_channel(&node_b.get_our_node_id(), channelmanager::provided_init_features(), &get_event_msg!(node_b_holder, MessageSendEvent::SendAcceptChannel, node_a.get_our_node_id()));
let tx;
if let Event::FundingGenerationReady { temporary_channel_id, output_script, .. } = get_event!(node_a_holder, Event::FundingGenerationReady) {
($node_a: expr, $node_b: expr) => {
let usable_channels = $node_a.list_usable_channels();
let payment_params = PaymentParameters::from_node_id($node_b.get_our_node_id())
- .with_features(InvoiceFeatures::known());
+ .with_features(channelmanager::provided_invoice_features());
let scorer = test_utils::TestScorer::with_penalty(0);
let seed = [3u8; 32];
let keys_manager = KeysManager::new(&seed, 42, 42);
//! (see [BOLT-4](https://github.com/lightning/bolts/blob/master/04-onion-routing.md) for more information).
//! - `BasicMPP` - requires/supports that a node can receive basic multi-part payments
//! (see [BOLT-4](https://github.com/lightning/bolts/blob/master/04-onion-routing.md#basic-multi-part-payments) for more information).
+//! - `Wumbo` - requires/supports that a node create large channels. Called `option_support_large_channel` in the spec.
+//! (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#the-open_channel-message) for more information).
//! - `ShutdownAnySegwit` - requires/supports that future segwit versions are allowed in `shutdown`
//! (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md) for more information).
+//! - `OnionMessages` - requires/supports forwarding onion messages
+//! (see [BOLT-7](https://github.com/lightning/bolts/pull/759/files) for more information).
+//! TODO: update link
//! - `ChannelType` - node supports the channel_type field in open/accept
//! (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md) for more information).
//! - `SCIDPrivacy` - supply channel aliases for routing
use prelude::*;
use ln::features::Features;
- /// The context in which [`Features`] are applicable. Defines which features are required and
- /// which are optional for the context.
+ /// The context in which [`Features`] are applicable. Defines which features are known to the
+ /// implementation, though specification of them as required or optional is up to the code
+ /// constructing a features object.
pub trait Context {
- /// Features that are known to the implementation, where a required feature is indicated by
- /// its even bit and an optional feature is indicated by its odd bit.
- const KNOWN_FEATURE_FLAGS: &'static [u8];
-
- /// Bitmask for selecting features that are known to the implementation, regardless of
- /// whether each feature is required or optional.
+ /// Bitmask for selecting features that are known to the implementation.
const KNOWN_FEATURE_MASK: &'static [u8];
}
/// are specified as a comma-separated list of bytes where each byte is a pipe-delimited list of
/// feature identifiers.
macro_rules! define_context {
- ($context: ident {
- required_features: [$( $( $required_feature: ident )|*, )*],
- optional_features: [$( $( $optional_feature: ident )|*, )*],
- }) => {
+ ($context: ident, [$( $( $known_feature: ident )|*, )*]) => {
#[derive(Eq, PartialEq)]
pub struct $context {}
impl Context for $context {
- const KNOWN_FEATURE_FLAGS: &'static [u8] = &[
- // For each byte, use bitwise-OR to compute the applicable flags for known
- // required features `r_i` and optional features `o_j` for all `i` and `j` such
- // that the following slice is formed:
- //
- // [
- // `r_0` | `r_1` | ... | `o_0` | `o_1` | ...,
- // ...,
- // ]
- $(
- 0b00_00_00_00 $(|
- <Self as $required_feature>::REQUIRED_MASK)*
- $(|
- <Self as $optional_feature>::OPTIONAL_MASK)*,
- )*
- ];
-
const KNOWN_FEATURE_MASK: &'static [u8] = &[
- // Similar as above, but set both flags for each feature regardless of whether
- // the feature is required or optional.
$(
0b00_00_00_00 $(|
- <Self as $required_feature>::REQUIRED_MASK |
- <Self as $required_feature>::OPTIONAL_MASK)*
- $(|
- <Self as $optional_feature>::REQUIRED_MASK |
- <Self as $optional_feature>::OPTIONAL_MASK)*,
+ <Self as $known_feature>::REQUIRED_MASK |
+ <Self as $known_feature>::OPTIONAL_MASK)*,
)*
];
}
fn fmt(&self, fmt: &mut alloc::fmt::Formatter) -> Result<(), alloc::fmt::Error> {
$(
$(
- fmt.write_fmt(format_args!("{}: {}, ", stringify!($required_feature),
- if <$context as $required_feature>::requires_feature(&self.flags) { "required" }
- else if <$context as $required_feature>::supports_feature(&self.flags) { "supported" }
- else { "not supported" }))?;
- )*
- $(
- fmt.write_fmt(format_args!("{}: {}, ", stringify!($optional_feature),
- if <$context as $optional_feature>::requires_feature(&self.flags) { "required" }
- else if <$context as $optional_feature>::supports_feature(&self.flags) { "supported" }
+ fmt.write_fmt(format_args!("{}: {}, ", stringify!($known_feature),
+ if <$context as $known_feature>::requires_feature(&self.flags) { "required" }
+ else if <$context as $known_feature>::supports_feature(&self.flags) { "supported" }
else { "not supported" }))?;
)*
+ {} // Rust gets mad if we only have a $()* block here, so add a dummy {}
)*
fmt.write_fmt(format_args!("unknown flags: {}",
if self.requires_unknown_bits() { "required" }
};
}
- define_context!(InitContext {
- required_features: [
- // Byte 0
- ,
- // Byte 1
- VariableLengthOnion | StaticRemoteKey | PaymentSecret,
- // Byte 2
- ,
- // Byte 3
- ,
- // Byte 4
- ,
- // Byte 5
- ,
- // Byte 6
- ,
- ],
- optional_features: [
- // Byte 0
- DataLossProtect | InitialRoutingSync | UpfrontShutdownScript | GossipQueries,
- // Byte 1
- ,
- // Byte 2
- BasicMPP | Wumbo,
- // Byte 3
- ShutdownAnySegwit,
- // Byte 4
- ,
- // Byte 5
- ChannelType | SCIDPrivacy,
- // Byte 6
- ZeroConf,
- ],
- });
- define_context!(NodeContext {
- required_features: [
- // Byte 0
- ,
- // Byte 1
- VariableLengthOnion | StaticRemoteKey | PaymentSecret,
- // Byte 2
- ,
- // Byte 3
- ,
- // Byte 4
- ,
- // Byte 5
- ,
- // Byte 6
- ,
- ],
- optional_features: [
- // Byte 0
- DataLossProtect | UpfrontShutdownScript | GossipQueries,
- // Byte 1
- ,
- // Byte 2
- BasicMPP | Wumbo,
- // Byte 3
- ShutdownAnySegwit,
- // Byte 4
- ,
- // Byte 5
- ChannelType | SCIDPrivacy,
- // Byte 6
- ZeroConf | Keysend,
- ],
- });
- define_context!(ChannelContext {
- required_features: [],
- optional_features: [],
- });
- define_context!(InvoiceContext {
- required_features: [
- // Byte 0
- ,
- // Byte 1
- VariableLengthOnion | PaymentSecret,
- // Byte 2
- ,
- ],
- optional_features: [
- // Byte 0
- ,
- // Byte 1
- ,
- // Byte 2
- BasicMPP,
- ],
- });
+ define_context!(InitContext, [
+ // Byte 0
+ DataLossProtect | InitialRoutingSync | UpfrontShutdownScript | GossipQueries,
+ // Byte 1
+ VariableLengthOnion | StaticRemoteKey | PaymentSecret,
+ // Byte 2
+ BasicMPP | Wumbo,
+ // Byte 3
+ ShutdownAnySegwit,
+ // Byte 4
+ OnionMessages,
+ // Byte 5
+ ChannelType | SCIDPrivacy,
+ // Byte 6
+ ZeroConf,
+ ]);
+ define_context!(NodeContext, [
+ // Byte 0
+ DataLossProtect | UpfrontShutdownScript | GossipQueries,
+ // Byte 1
+ VariableLengthOnion | StaticRemoteKey | PaymentSecret,
+ // Byte 2
+ BasicMPP | Wumbo,
+ // Byte 3
+ ShutdownAnySegwit,
+ // Byte 4
+ OnionMessages,
+ // Byte 5
+ ChannelType | SCIDPrivacy,
+ // Byte 6
+ ZeroConf | Keysend,
+ ]);
+ define_context!(ChannelContext, []);
+ define_context!(InvoiceContext, [
+ // Byte 0
+ ,
+ // Byte 1
+ VariableLengthOnion | PaymentSecret,
+ // Byte 2
+ BasicMPP,
+ ]);
// This isn't a "real" feature context, and is only used in the channel_type field in an
// `OpenChannel` message.
- define_context!(ChannelTypeContext {
- required_features: [
- // Byte 0
- ,
- // Byte 1
- StaticRemoteKey,
- // Byte 2
- ,
- // Byte 3
- ,
- // Byte 4
- ,
- // Byte 5
- SCIDPrivacy,
- // Byte 6
- ZeroConf,
- ],
- optional_features: [
- // Byte 0
- ,
- // Byte 1
- ,
- // Byte 2
- ,
- // Byte 3
- ,
- // Byte 4
- ,
- // Byte 5
- ,
- // Byte 6
- ,
- ],
- });
+ define_context!(ChannelTypeContext, [
+ // Byte 0
+ ,
+ // Byte 1
+ StaticRemoteKey,
+ // Byte 2
+ ,
+ // Byte 3
+ ,
+ // Byte 4
+ ,
+ // Byte 5
+ SCIDPrivacy,
+ // Byte 6
+ ZeroConf,
+ ]);
/// Defines a feature with the given bits for the specified [`Context`]s. The generated trait is
/// useful for manipulating feature flags.
/// [`ODD_BIT`]: #associatedconstant.ODD_BIT
const ASSERT_ODD_BIT_PARITY: usize;
+ /// Assertion that the bits are set in the context's [`KNOWN_FEATURE_MASK`].
+ ///
+ /// [`KNOWN_FEATURE_MASK`]: Context::KNOWN_FEATURE_MASK
+ #[cfg(not(test))] // We violate this constraint with `UnknownFeature`
+ const ASSERT_BITS_IN_MASK: u8;
+
/// The byte where the feature is set.
const BYTE_OFFSET: usize = Self::EVEN_BIT / 8;
// ODD_BIT % 2 == 1
const ASSERT_ODD_BIT_PARITY: usize = (<Self as $feature>::ODD_BIT % 2) - 1;
+
+ // (byte & (REQUIRED_MASK | OPTIONAL_MASK)) >> (EVEN_BIT % 8) == 3
+ #[cfg(not(test))] // We violate this constraint with `UnknownFeature`
+ const ASSERT_BITS_IN_MASK: u8 =
+ ((<$context>::KNOWN_FEATURE_MASK[<Self as $feature>::BYTE_OFFSET] & (<Self as $feature>::REQUIRED_MASK | <Self as $feature>::OPTIONAL_MASK))
+ >> (<Self as $feature>::EVEN_BIT % 8)) - 3;
}
)*
};
define_feature!(27, ShutdownAnySegwit, [InitContext, NodeContext],
"Feature flags for `opt_shutdown_anysegwit`.", set_shutdown_any_segwit_optional,
set_shutdown_any_segwit_required, supports_shutdown_anysegwit, requires_shutdown_anysegwit);
- // We do not yet advertise the onion messages feature bit, but we need to detect when peers
- // support it.
define_feature!(39, OnionMessages, [InitContext, NodeContext],
"Feature flags for `option_onion_messages`.", set_onion_messages_optional,
set_onion_messages_required, supports_onion_messages, requires_onion_messages);
mark: PhantomData<T>,
}
+impl <T: sealed::Context> Features<T> {
+ pub(crate) fn or(mut self, o: Self) -> Self {
+ let total_feature_len = cmp::max(self.flags.len(), o.flags.len());
+ self.flags.resize(total_feature_len, 0u8);
+ for (byte, o_byte) in self.flags.iter_mut().zip(o.flags.iter()) {
+ *byte |= *o_byte;
+ }
+ self
+ }
+}
+
impl<T: sealed::Context> Clone for Features<T> {
fn clone(&self) -> Self {
Self {
Ok(())
}
- /// or's another InitFeatures into this one.
- pub(crate) fn or(mut self, o: InitFeatures) -> InitFeatures {
- let total_feature_len = cmp::max(self.flags.len(), o.flags.len());
- self.flags.resize(total_feature_len, 0u8);
- for (byte, o_byte) in self.flags.iter_mut().zip(o.flags.iter()) {
- *byte |= *o_byte;
- }
- self
- }
-
/// Converts `InitFeatures` to `Features<C>`. Only known `InitFeatures` relevant to context `C`
/// are included in the result.
pub(crate) fn to_context<C: sealed::Context>(&self) -> Features<C> {
}
}
- /// Creates a Features with the bits set which are known by the implementation
- pub fn known() -> Self {
- Self {
- flags: T::KNOWN_FEATURE_FLAGS.to_vec(),
- mark: PhantomData,
- }
- }
-
/// Converts `Features<T>` to `Features<C>`. Only known `T` features relevant to context `C` are
/// included in the result.
fn to_context_internal<C: sealed::Context>(&self) -> Features<C> {
}
}
-
-impl<T: sealed::GossipQueries> Features<T> {
- #[cfg(test)]
- pub(crate) fn clear_gossip_queries(mut self) -> Self {
- <T as sealed::GossipQueries>::clear_bits(&mut self.flags);
- self
- }
-}
-
-impl<T: sealed::InitialRoutingSync> Features<T> {
- // We are no longer setting initial_routing_sync now that gossip_queries
- // is enabled. This feature is ignored by a peer when gossip_queries has
- // been negotiated.
- #[cfg(test)]
- pub(crate) fn clear_initial_routing_sync(&mut self) {
- <T as sealed::InitialRoutingSync>::clear_bits(&mut self.flags)
- }
-}
-
impl<T: sealed::ShutdownAnySegwit> Features<T> {
#[cfg(test)]
pub(crate) fn clear_shutdown_anysegwit(mut self) -> Self {
#[cfg(test)]
mod tests {
- use super::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
+ use super::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, InvoiceFeatures, NodeFeatures, sealed};
use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, u5};
- #[test]
- fn sanity_test_known_features() {
- assert!(!ChannelFeatures::known().requires_unknown_bits());
- assert!(!ChannelFeatures::known().supports_unknown_bits());
- assert!(!InitFeatures::known().requires_unknown_bits());
- assert!(!InitFeatures::known().supports_unknown_bits());
- assert!(!NodeFeatures::known().requires_unknown_bits());
- assert!(!NodeFeatures::known().supports_unknown_bits());
-
- assert!(InitFeatures::known().supports_upfront_shutdown_script());
- assert!(NodeFeatures::known().supports_upfront_shutdown_script());
- assert!(!InitFeatures::known().requires_upfront_shutdown_script());
- assert!(!NodeFeatures::known().requires_upfront_shutdown_script());
-
- assert!(InitFeatures::known().supports_gossip_queries());
- assert!(NodeFeatures::known().supports_gossip_queries());
- assert!(!InitFeatures::known().requires_gossip_queries());
- assert!(!NodeFeatures::known().requires_gossip_queries());
-
- assert!(InitFeatures::known().supports_data_loss_protect());
- assert!(NodeFeatures::known().supports_data_loss_protect());
- assert!(!InitFeatures::known().requires_data_loss_protect());
- assert!(!NodeFeatures::known().requires_data_loss_protect());
-
- assert!(InitFeatures::known().supports_variable_length_onion());
- assert!(NodeFeatures::known().supports_variable_length_onion());
- assert!(InvoiceFeatures::known().supports_variable_length_onion());
- assert!(InitFeatures::known().requires_variable_length_onion());
- assert!(NodeFeatures::known().requires_variable_length_onion());
- assert!(InvoiceFeatures::known().requires_variable_length_onion());
-
- assert!(InitFeatures::known().supports_static_remote_key());
- assert!(NodeFeatures::known().supports_static_remote_key());
- assert!(InitFeatures::known().requires_static_remote_key());
- assert!(NodeFeatures::known().requires_static_remote_key());
-
- assert!(InitFeatures::known().supports_payment_secret());
- assert!(NodeFeatures::known().supports_payment_secret());
- assert!(InvoiceFeatures::known().supports_payment_secret());
- assert!(InitFeatures::known().requires_payment_secret());
- assert!(NodeFeatures::known().requires_payment_secret());
- assert!(InvoiceFeatures::known().requires_payment_secret());
-
- assert!(InitFeatures::known().supports_basic_mpp());
- assert!(NodeFeatures::known().supports_basic_mpp());
- assert!(InvoiceFeatures::known().supports_basic_mpp());
- assert!(!InitFeatures::known().requires_basic_mpp());
- assert!(!NodeFeatures::known().requires_basic_mpp());
- assert!(!InvoiceFeatures::known().requires_basic_mpp());
-
- assert!(InitFeatures::known().supports_channel_type());
- assert!(NodeFeatures::known().supports_channel_type());
- assert!(!InitFeatures::known().requires_channel_type());
- assert!(!NodeFeatures::known().requires_channel_type());
-
- assert!(InitFeatures::known().supports_shutdown_anysegwit());
- assert!(NodeFeatures::known().supports_shutdown_anysegwit());
-
- assert!(InitFeatures::known().supports_scid_privacy());
- assert!(NodeFeatures::known().supports_scid_privacy());
- assert!(ChannelTypeFeatures::known().supports_scid_privacy());
- assert!(!InitFeatures::known().requires_scid_privacy());
- assert!(!NodeFeatures::known().requires_scid_privacy());
- assert!(ChannelTypeFeatures::known().requires_scid_privacy());
-
- assert!(InitFeatures::known().supports_wumbo());
- assert!(NodeFeatures::known().supports_wumbo());
- assert!(!InitFeatures::known().requires_wumbo());
- assert!(!NodeFeatures::known().requires_wumbo());
-
- assert!(InitFeatures::known().supports_zero_conf());
- assert!(!InitFeatures::known().requires_zero_conf());
- assert!(NodeFeatures::known().supports_zero_conf());
- assert!(!NodeFeatures::known().requires_zero_conf());
- assert!(ChannelTypeFeatures::known().supports_zero_conf());
- assert!(ChannelTypeFeatures::known().requires_zero_conf());
-
- let mut init_features = InitFeatures::known();
- assert!(init_features.initial_routing_sync());
- init_features.clear_initial_routing_sync();
- assert!(!init_features.initial_routing_sync());
- }
-
#[test]
fn sanity_test_unknown_bits() {
let features = ChannelFeatures::empty();
#[test]
fn convert_to_context_with_relevant_flags() {
- let init_features = InitFeatures::known().clear_upfront_shutdown_script().clear_gossip_queries();
+ let mut init_features = InitFeatures::empty();
+ // Set a bunch of features we use, plus initial_routing_sync_required (which shouldn't get
+ // converted as it's only relevant in an init context).
+ init_features.set_initial_routing_sync_required();
+ init_features.set_data_loss_protect_optional();
+ init_features.set_variable_length_onion_required();
+ init_features.set_static_remote_key_required();
+ init_features.set_payment_secret_required();
+ init_features.set_basic_mpp_optional();
+ init_features.set_wumbo_optional();
+ init_features.set_shutdown_any_segwit_optional();
+ init_features.set_onion_messages_optional();
+ init_features.set_channel_type_optional();
+ init_features.set_scid_privacy_optional();
+ init_features.set_zero_conf_optional();
+
assert!(init_features.initial_routing_sync());
assert!(!init_features.supports_upfront_shutdown_script());
assert!(!init_features.supports_gossip_queries());
// - var_onion_optin (req) | static_remote_key (req) | payment_secret(req)
// - basic_mpp | wumbo
// - opt_shutdown_anysegwit
- // -
+ // - onion_messages
// - option_channel_type | option_scid_alias
// - option_zeroconf
assert_eq!(node_features.flags.len(), 7);
assert_eq!(node_features.flags[1], 0b01010001);
assert_eq!(node_features.flags[2], 0b00001010);
assert_eq!(node_features.flags[3], 0b00001000);
- assert_eq!(node_features.flags[4], 0b00000000);
+ assert_eq!(node_features.flags[4], 0b10000000);
assert_eq!(node_features.flags[5], 0b10100000);
assert_eq!(node_features.flags[6], 0b00001000);
}
#[test]
fn convert_to_context_with_unknown_flags() {
// Ensure the `from` context has fewer known feature bytes than the `to` context.
- assert!(InvoiceFeatures::known().flags.len() < NodeFeatures::known().flags.len());
- let mut invoice_features = InvoiceFeatures::known();
+ assert!(<sealed::InvoiceContext as sealed::Context>::KNOWN_FEATURE_MASK.len() <
+ <sealed::NodeContext as sealed::Context>::KNOWN_FEATURE_MASK.len());
+ let mut invoice_features = InvoiceFeatures::empty();
invoice_features.set_unknown_feature_optional();
assert!(invoice_features.supports_unknown_bits());
let node_features: NodeFeatures = invoice_features.to_context();
use chain::channelmonitor::ChannelMonitor;
use chain::transaction::OutPoint;
use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
-use ln::channelmanager::{ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure, PaymentId, MIN_CLTV_EXPIRY_DELTA};
+use ln::channelmanager::{self, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure, PaymentId, MIN_CLTV_EXPIRY_DELTA};
use routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate};
use routing::router::{PaymentParameters, Route, get_route};
-use ln::features::{InitFeatures, InvoiceFeatures};
+use ln::features::InitFeatures;
use ln::msgs;
use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler};
use util::enforcing_trait_impls::EnforcingSigner;
fn drop(&mut self) {
if !panicking() {
// Check that we processed all pending events
- assert!(self.node.get_and_clear_pending_msg_events().is_empty());
- assert!(self.node.get_and_clear_pending_events().is_empty());
- assert!(self.chain_monitor.added_monitors.lock().unwrap().is_empty());
+ let msg_events = self.node.get_and_clear_pending_msg_events();
+ if !msg_events.is_empty() {
+ panic!("Had excess message events on node {}: {:?}", self.logger.id, msg_events);
+ }
+ let events = self.node.get_and_clear_pending_events();
+ if !events.is_empty() {
+ panic!("Had excess events on node {}: {:?}", self.logger.id, events);
+ }
+ let added_monitors = self.chain_monitor.added_monitors.lock().unwrap().split_off(0);
+ if !added_monitors.is_empty() {
+ panic!("Had {} excess added monitors on node {}", added_monitors.len(), self.logger.id);
+ }
// Check that if we serialize the Router, we can deserialize it again.
{
tx
}
+// Receiver must have been initialized with manually_accept_inbound_channels set to true.
+pub fn open_zero_conf_channel<'a, 'b, 'c, 'd>(initiator: &'a Node<'b, 'c, 'd>, receiver: &'a Node<'b, 'c, 'd>, initiator_config: Option<UserConfig>) -> (bitcoin::Transaction, [u8; 32]) {
+ let initiator_channels = initiator.node.list_usable_channels().len();
+ let receiver_channels = receiver.node.list_usable_channels().len();
+
+ initiator.node.create_channel(receiver.node.get_our_node_id(), 100_000, 10_001, 42, initiator_config).unwrap();
+ let open_channel = get_event_msg!(initiator, MessageSendEvent::SendOpenChannel, receiver.node.get_our_node_id());
+
+ receiver.node.handle_open_channel(&initiator.node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
+ let events = receiver.node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match events[0] {
+ Event::OpenChannelRequest { temporary_channel_id, .. } => {
+ receiver.node.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, &initiator.node.get_our_node_id(), 0).unwrap();
+ },
+ _ => panic!("Unexpected event"),
+ };
+
+ let accept_channel = get_event_msg!(receiver, MessageSendEvent::SendAcceptChannel, initiator.node.get_our_node_id());
+ assert_eq!(accept_channel.minimum_depth, 0);
+ initiator.node.handle_accept_channel(&receiver.node.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel);
+
+ let (temporary_channel_id, tx, _) = create_funding_transaction(&initiator, &receiver.node.get_our_node_id(), 100_000, 42);
+ initiator.node.funding_transaction_generated(&temporary_channel_id, &receiver.node.get_our_node_id(), tx.clone()).unwrap();
+ let funding_created = get_event_msg!(initiator, MessageSendEvent::SendFundingCreated, receiver.node.get_our_node_id());
+
+ receiver.node.handle_funding_created(&initiator.node.get_our_node_id(), &funding_created);
+ check_added_monitors!(receiver, 1);
+ let bs_signed_locked = receiver.node.get_and_clear_pending_msg_events();
+ assert_eq!(bs_signed_locked.len(), 2);
+ let as_channel_ready;
+ match &bs_signed_locked[0] {
+ MessageSendEvent::SendFundingSigned { node_id, msg } => {
+ assert_eq!(*node_id, initiator.node.get_our_node_id());
+ initiator.node.handle_funding_signed(&receiver.node.get_our_node_id(), &msg);
+ check_added_monitors!(initiator, 1);
+
+ assert_eq!(initiator.tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1);
+ assert_eq!(initiator.tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0)[0], tx);
+
+ as_channel_ready = get_event_msg!(initiator, MessageSendEvent::SendChannelReady, receiver.node.get_our_node_id());
+ }
+ _ => panic!("Unexpected event"),
+ }
+ match &bs_signed_locked[1] {
+ MessageSendEvent::SendChannelReady { node_id, msg } => {
+ assert_eq!(*node_id, initiator.node.get_our_node_id());
+ initiator.node.handle_channel_ready(&receiver.node.get_our_node_id(), &msg);
+ }
+ _ => panic!("Unexpected event"),
+ }
+
+ receiver.node.handle_channel_ready(&initiator.node.get_our_node_id(), &as_channel_ready);
+
+ let as_channel_update = get_event_msg!(initiator, MessageSendEvent::SendChannelUpdate, receiver.node.get_our_node_id());
+ let bs_channel_update = get_event_msg!(receiver, MessageSendEvent::SendChannelUpdate, initiator.node.get_our_node_id());
+
+ initiator.node.handle_channel_update(&receiver.node.get_our_node_id(), &bs_channel_update);
+ receiver.node.handle_channel_update(&initiator.node.get_our_node_id(), &as_channel_update);
+
+ assert_eq!(initiator.node.list_usable_channels().len(), initiator_channels + 1);
+ assert_eq!(receiver.node.list_usable_channels().len(), receiver_channels + 1);
+
+ (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, a_flags: InitFeatures, b_flags: InitFeatures) -> Transaction {
let create_chan_id = node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None).unwrap();
let open_channel_msg = get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b.node.get_our_node_id());
}
pub fn update_nodes_with_chan_announce<'a, 'b, 'c, 'd>(nodes: &'a Vec<Node<'b, 'c, 'd>>, a: usize, b: usize, ann: &msgs::ChannelAnnouncement, upd_1: &msgs::ChannelUpdate, upd_2: &msgs::ChannelUpdate) {
- nodes[a].node.broadcast_node_announcement([0, 0, 0], [0; 32], Vec::new());
- let a_events = nodes[a].node.get_and_clear_pending_msg_events();
- assert!(a_events.len() >= 2);
-
- // ann should be re-generated by broadcast_node_announcement - check that we have it.
- let mut found_ann_1 = false;
- for event in a_events.iter() {
- match event {
- MessageSendEvent::BroadcastChannelAnnouncement { ref msg, .. } => {
- if msg == ann { found_ann_1 = true; }
- },
- MessageSendEvent::BroadcastNodeAnnouncement { .. } => {},
- _ => panic!("Unexpected event {:?}", event),
- }
- }
- assert!(found_ann_1);
-
- let a_node_announcement = match a_events.last().unwrap() {
- MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
- (*msg).clone()
- },
- _ => panic!("Unexpected event"),
- };
-
- nodes[b].node.broadcast_node_announcement([1, 1, 1], [1; 32], Vec::new());
- let b_events = nodes[b].node.get_and_clear_pending_msg_events();
- assert!(b_events.len() >= 2);
-
- // ann should be re-generated by broadcast_node_announcement - check that we have it.
- let mut found_ann_2 = false;
- for event in b_events.iter() {
- match event {
- MessageSendEvent::BroadcastChannelAnnouncement { ref msg, .. } => {
- if msg == ann { found_ann_2 = true; }
- },
- MessageSendEvent::BroadcastNodeAnnouncement { .. } => {},
- _ => panic!("Unexpected event"),
- }
- }
- assert!(found_ann_2);
-
- let b_node_announcement = match b_events.last().unwrap() {
- MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
- (*msg).clone()
- },
- _ => panic!("Unexpected event"),
- };
-
for node in nodes {
assert!(node.gossip_sync.handle_channel_announcement(ann).unwrap());
node.gossip_sync.handle_channel_update(upd_1).unwrap();
node.gossip_sync.handle_channel_update(upd_2).unwrap();
- node.gossip_sync.handle_node_announcement(&a_node_announcement).unwrap();
- node.gossip_sync.handle_node_announcement(&b_node_announcement).unwrap();
// Note that channel_updates are also delivered to ChannelManagers to ensure we have
// forwarding info for local channels even if its not accepted in the network graph.
let (tx_a, tx_b);
node_a.close_channel(channel_id, &node_b.get_our_node_id()).unwrap();
- node_b.handle_shutdown(&node_a.get_our_node_id(), &InitFeatures::known(), &get_event_msg!(struct_a, MessageSendEvent::SendShutdown, node_b.get_our_node_id()));
+ node_b.handle_shutdown(&node_a.get_our_node_id(), &channelmanager::provided_init_features(), &get_event_msg!(struct_a, MessageSendEvent::SendShutdown, node_b.get_our_node_id()));
let events_1 = node_b.get_and_clear_pending_msg_events();
assert!(events_1.len() >= 1);
})
};
- node_a.handle_shutdown(&node_b.get_our_node_id(), &InitFeatures::known(), &shutdown_b);
+ node_a.handle_shutdown(&node_b.get_our_node_id(), &channelmanager::provided_init_features(), &shutdown_b);
let (as_update, bs_update) = if close_inbound_first {
assert!(node_a.get_and_clear_pending_msg_events().is_empty());
node_a.handle_closing_signed(&node_b.get_our_node_id(), &closing_signed_b.unwrap());
macro_rules! get_route_and_payment_hash {
($send_node: expr, $recv_node: expr, $recv_value: expr) => {{
let payment_params = $crate::routing::router::PaymentParameters::from_node_id($recv_node.node.get_our_node_id())
- .with_features($crate::ln::features::InvoiceFeatures::known());
+ .with_features($crate::ln::channelmanager::provided_invoice_features());
$crate::get_route_and_payment_hash!($send_node, $recv_node, payment_params, $recv_value, TEST_FINAL_CLTV)
}};
($send_node: expr, $recv_node: expr, $payment_params: expr, $recv_value: expr, $cltv: expr) => {{
#[cfg(test)]
macro_rules! expect_payment_failed_with_update {
- ($node: expr, $expected_payment_hash: expr, $rejected_by_dest: expr, $scid: expr, $chan_closed: expr) => {
+ ($node: expr, $expected_payment_hash: expr, $payment_failed_permanently: expr, $scid: expr, $chan_closed: expr) => {
$crate::ln::functional_test_utils::expect_payment_failed_conditions(
- &$node, $expected_payment_hash, $rejected_by_dest,
+ &$node, $expected_payment_hash, $payment_failed_permanently,
$crate::ln::functional_test_utils::PaymentFailedConditions::new()
.blamed_scid($scid).blamed_chan_closed($chan_closed));
}
#[cfg(test)]
macro_rules! expect_payment_failed {
- ($node: expr, $expected_payment_hash: expr, $rejected_by_dest: expr $(, $expected_error_code: expr, $expected_error_data: expr)*) => {
+ ($node: expr, $expected_payment_hash: expr, $payment_failed_permanently: expr $(, $expected_error_code: expr, $expected_error_data: expr)*) => {
#[allow(unused_mut)]
let mut conditions = $crate::ln::functional_test_utils::PaymentFailedConditions::new();
$(
conditions = conditions.expected_htlc_error_data($expected_error_code, &$expected_error_data);
)*
- $crate::ln::functional_test_utils::expect_payment_failed_conditions(&$node, $expected_payment_hash, $rejected_by_dest, conditions);
+ $crate::ln::functional_test_utils::expect_payment_failed_conditions(&$node, $expected_payment_hash, $payment_failed_permanently, conditions);
};
}
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>
+ expected_payment_failed_permanently: bool, conditions: PaymentFailedConditions<'e>
) {
let expected_payment_id = match payment_failed_event {
- Event::PaymentPathFailed { payment_hash, rejected_by_dest, path, retry, payment_id, network_update, short_channel_id,
+ Event::PaymentPathFailed { payment_hash, payment_failed_permanently, path, retry, payment_id, network_update, short_channel_id,
#[cfg(test)]
error_code,
#[cfg(test)]
error_data, .. } => {
assert_eq!(payment_hash, expected_payment_hash, "unexpected payment_hash");
- assert_eq!(rejected_by_dest, expected_rejected_by_dest, "unexpected rejected_by_dest value");
+ assert_eq!(payment_failed_permanently, expected_payment_failed_permanently, "unexpected payment_failed_permanently value");
assert!(retry.is_some(), "expected retry.is_some()");
assert_eq!(retry.as_ref().unwrap().final_value_msat, path.last().unwrap().fee_msat, "Retry amount should match last hop in path");
assert_eq!(retry.as_ref().unwrap().payment_params.payee_pubkey, path.last().unwrap().pubkey, "Retry payee node_id should match last hop in path");
}
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,
+ node: &'a Node<'b, 'c, 'd>, expected_payment_hash: PaymentHash, expected_payment_failed_permanently: 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);
+ expect_payment_failed_conditions_event(node, events.pop().unwrap(), expected_payment_hash, expected_payment_failed_permanently, 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 {
pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash, PaymentSecret) {
let payment_params = PaymentParameters::from_node_id(expected_route.last().unwrap().node.get_our_node_id())
- .with_features(InvoiceFeatures::known());
+ .with_features(channelmanager::provided_invoice_features());
let route = get_route!(origin_node, payment_params, recv_value, TEST_FINAL_CLTV).unwrap();
assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].len(), expected_route.len());
pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) {
let payment_params = PaymentParameters::from_node_id(expected_route.last().unwrap().node.get_our_node_id())
- .with_features(InvoiceFeatures::known());
+ .with_features(channelmanager::provided_invoice_features());
let network_graph = origin_node.network_graph.read_only();
let scorer = test_utils::TestScorer::with_penalty(0);
let seed = [0u8; 32];
let events = origin_node.node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
let expected_payment_id = match events[0] {
- Event::PaymentPathFailed { payment_hash, rejected_by_dest, all_paths_failed, ref path, ref payment_id, .. } => {
+ Event::PaymentPathFailed { payment_hash, payment_failed_permanently, all_paths_failed, ref path, ref payment_id, .. } => {
assert_eq!(payment_hash, our_payment_hash);
- assert!(rejected_by_dest);
+ assert!(payment_failed_permanently);
assert_eq!(all_paths_failed, i == expected_paths.len() - 1);
for (idx, hop) in expected_route.iter().enumerate() {
assert_eq!(hop.node.get_our_node_id(), path[idx].pubkey);
chain_monitor,
keys_manager: &chanmon_cfgs[i].keys_manager,
node_seed: seed,
- features: InitFeatures::known(),
+ features: channelmanager::provided_init_features(),
network_graph: NetworkGraph::new(chanmon_cfgs[i].chain_source.genesis_hash, &chanmon_cfgs[i].logger),
});
}
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: cfgs[j].features.clone(), remote_network_address: None });
- nodes[j].node.peer_connected(&nodes[i].node.get_our_node_id(), &msgs::Init { features: cfgs[i].features.clone(), remote_network_address: None });
+ nodes[i].node.peer_connected(&nodes[j].node.get_our_node_id(), &msgs::Init { features: cfgs[j].features.clone(), remote_network_address: None }).unwrap();
+ nodes[j].node.peer_connected(&nodes[i].node.get_our_node_id(), &msgs::Init { features: cfgs[i].features.clone(), remote_network_address: None }).unwrap();
}
}
// Note that the following only works for CLTV values up to 128
pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 137; //Here we have a diff due to HTLC CLTV expiry being < 2^15 in test
-pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
#[derive(PartialEq)]
pub enum HTLCType { NONE, TIMEOUT, SUCCESS }
macro_rules! get_chan_reestablish_msgs {
($src_node: expr, $dst_node: expr) => {
{
+ let mut announcements = $crate::prelude::HashSet::new();
let mut res = Vec::with_capacity(1);
for msg in $src_node.node.get_and_clear_pending_msg_events() {
if let MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } = msg {
assert_eq!(*node_id, $dst_node.node.get_our_node_id());
res.push(msg.clone());
+ } else if let MessageSendEvent::SendChannelAnnouncement { ref node_id, ref msg, .. } = msg {
+ assert_eq!(*node_id, $dst_node.node.get_our_node_id());
+ announcements.insert(msg.contents.short_channel_id);
} else {
panic!("Unexpected event")
}
}
+ for chan in $src_node.node.list_channels() {
+ if chan.is_public && chan.counterparty.node_id != $dst_node.node.get_our_node_id() {
+ if let Some(scid) = chan.short_channel_id {
+ assert!(announcements.remove(&scid));
+ }
+ }
+ }
+ assert!(announcements.is_empty());
res
}
}
/// pending_htlc_adds includes both the holding cell and in-flight update_add_htlcs, whereas
/// for claims/fails they are separated out.
pub fn reconnect_nodes<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, send_channel_ready: (bool, bool), pending_htlc_adds: (i64, i64), pending_htlc_claims: (usize, usize), pending_htlc_fails: (usize, usize), pending_cell_htlc_claims: (usize, usize), pending_cell_htlc_fails: (usize, usize), pending_raa: (bool, bool)) {
- node_a.node.peer_connected(&node_b.node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ node_a.node.peer_connected(&node_b.node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_1 = get_chan_reestablish_msgs!(node_a, node_b);
- node_b.node.peer_connected(&node_a.node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ node_b.node.peer_connected(&node_a.node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_2 = get_chan_reestablish_msgs!(node_b, node_a);
if send_channel_ready.0 {
use chain::keysinterface::{BaseSign, KeysInterface};
use ln::{PaymentPreimage, PaymentSecret, PaymentHash};
use ln::channel::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC, CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT};
-use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, PaymentId, RAACommitmentOrder, PaymentSendFailure, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, PAYMENT_EXPIRY_BLOCKS };
+use ln::channelmanager::{self, ChannelManager, ChannelManagerReadArgs, PaymentId, RAACommitmentOrder, PaymentSendFailure, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, PAYMENT_EXPIRY_BLOCKS};
use ln::channel::{Channel, ChannelError};
use ln::{chan_utils, onion_utils};
-use ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight, HTLCOutputInCommitment};
-use routing::gossip::NetworkGraph;
+use ln::chan_utils::{OFFERED_HTLC_SCRIPT_WEIGHT, htlc_success_tx_weight, htlc_timeout_tx_weight, HTLCOutputInCommitment};
+use routing::gossip::{NetworkGraph, NetworkUpdate};
use routing::router::{PaymentParameters, Route, RouteHop, RouteParameters, find_route, get_route};
-use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
+use ln::features::{ChannelFeatures, NodeFeatures};
use ln::msgs;
use ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, ErrorAction};
use util::enforcing_trait_impls::EnforcingSigner;
// Test helper that asserts we get the correct error string given a mutator
// that supposedly makes the channel open message insane
let insane_open_helper = |expected_error_str: &str, message_mutator: fn(msgs::OpenChannel) -> msgs::OpenChannel| {
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &message_mutator(open_channel_message.clone()));
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &message_mutator(open_channel_message.clone()));
let msg_events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(msg_events.len(), 1);
let expected_regex = regex::Regex::new(expected_error_str).unwrap();
use ln::channel::MAX_FUNDING_SATOSHIS_NO_WUMBO;
let chanmon_cfgs = create_chanmon_cfgs(2);
let mut node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
- node_cfgs[1].features = InitFeatures::known().clear_wumbo();
+ node_cfgs[1].features = channelmanager::provided_init_features().clear_wumbo();
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
open_channel_message.channel_reserve_satoshis = 0;
open_channel_message.max_htlc_value_in_flight_msat = 100_000_000;
}
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel_message);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel_message);
// Extract the channel accept message from node1 to node0
let mut accept_channel_message = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
accept_channel_message.channel_reserve_satoshis = 0;
accept_channel_message.max_htlc_value_in_flight_msat = 100_000_000;
}
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel_message);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel_message);
{
let mut lock;
let mut chan = get_channel_ref!(if send_from_initiator { &nodes[1] } else { &nodes[0] }, lock, temp_channel_id);
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());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// balancing
send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
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());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// balancing
send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
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);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// A B
// update_fee/commitment_signed ->
let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
if steps & 0x0f == 1 { return; }
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
if steps & 0x0f == 2 { return; }
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel);
let (temporary_channel_id, tx, funding_output) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
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);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
{
let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let channel_value = 5000;
let push_sats = 700;
- let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value, push_sats * 1000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value, push_sats * 1000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let channel_id = chan.2;
let secp_ctx = Secp256k1::new();
let default_config = UserConfig::default();
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 chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// balancing
send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
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 chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let channel_id = chan.2;
// A B
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
- let chan_3 = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_3 = create_announced_chan_between_nodes(&nodes, 2, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Rebalance the network a bit by relaying one payment through all the channels...
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000);
fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], payment_hash_1);
// Add a new channel that skips 3
- let chan_4 = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::known(), InitFeatures::known());
+ let chan_4 = create_announced_chan_between_nodes(&nodes, 1, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], 1000000);
send_payment(&nodes[2], &vec!(&nodes[3])[..], 1000000);
});
hops.push(RouteHop {
pubkey: nodes[1].node.get_our_node_id(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: chan_4.0.contents.short_channel_id,
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: 1000000,
cltv_expiry_delta: TEST_FINAL_CLTV,
});
});
hops.push(RouteHop {
pubkey: nodes[1].node.get_our_node_id(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: chan_2.0.contents.short_channel_id,
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: 1000000,
cltv_expiry_delta: TEST_FINAL_CLTV,
});
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let mut payments = Vec::new();
for _ in 0..::ln::channel::OUR_MAX_HTLCS {
let mut nodes = create_network(6, &node_cfgs, &node_chanmgrs);
// Create some initial channels to route via 3 to 4/5 from 0/1/2
- create_announced_chan_between_nodes(&nodes, 0, 3, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 3, 4, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 3, 5, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 1, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 2, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 3, 4, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 3, 5, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &vec!(&nodes[3], &nodes[4])[..], 1000000);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// balancing
send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
connect_blocks(&nodes[0], TEST_FINAL_CLTV - 1); // Confirm blocks until the HTLC expires
let claim_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
- assert_eq!(claim_txn.len(), 8);
+ assert_eq!(claim_txn.len(), 5);
check_spends!(claim_txn[0], remote_txn[0]); // Immediate HTLC claim with preimage
-
check_spends!(claim_txn[1], chan_1.3); // Alternative commitment tx
check_spends!(claim_txn[2], claim_txn[1]); // HTLC spend in alternative commitment tx
- let bump_tx = if claim_txn[1] == claim_txn[4] {
- assert_eq!(claim_txn[1], claim_txn[4]);
- assert_eq!(claim_txn[2], claim_txn[5]);
-
- check_spends!(claim_txn[7], claim_txn[1]); // HTLC timeout on alternative commitment tx
-
- check_spends!(claim_txn[3], remote_txn[0]); // HTLC timeout on broadcasted commitment tx
- &claim_txn[3]
+ check_spends!(claim_txn[3], remote_txn[0]);
+ check_spends!(claim_txn[4], remote_txn[0]);
+ let preimage_tx = &claim_txn[0];
+ let (preimage_bump_tx, timeout_tx) = if claim_txn[3].input[0].previous_output == preimage_tx.input[0].previous_output {
+ (&claim_txn[3], &claim_txn[4])
} else {
- assert_eq!(claim_txn[1], claim_txn[3]);
- assert_eq!(claim_txn[2], claim_txn[4]);
-
- check_spends!(claim_txn[5], claim_txn[1]); // HTLC timeout on alternative commitment tx
-
- check_spends!(claim_txn[7], remote_txn[0]); // HTLC timeout on broadcasted commitment tx
-
- &claim_txn[7]
+ (&claim_txn[4], &claim_txn[3])
};
- assert_eq!(claim_txn[0].input.len(), 1);
- assert_eq!(bump_tx.input.len(), 1);
- assert_eq!(claim_txn[0].input[0].previous_output, bump_tx.input[0].previous_output);
+ assert_eq!(preimage_tx.input.len(), 1);
+ assert_eq!(preimage_bump_tx.input.len(), 1);
- assert_eq!(claim_txn[0].input.len(), 1);
- assert_eq!(claim_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); // HTLC 1 <--> 0, preimage tx
- assert_eq!(remote_txn[0].output[claim_txn[0].input[0].previous_output.vout as usize].value, 800);
+ assert_eq!(preimage_tx.input.len(), 1);
+ assert_eq!(preimage_tx.input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); // HTLC 1 <--> 0, preimage tx
+ assert_eq!(remote_txn[0].output[preimage_tx.input[0].previous_output.vout as usize].value, 800);
- assert_eq!(claim_txn[6].input.len(), 1);
- assert_eq!(claim_txn[6].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); // HTLC 0 <--> 1, timeout tx
- check_spends!(claim_txn[6], remote_txn[0]);
- assert_eq!(remote_txn[0].output[claim_txn[6].input[0].previous_output.vout as usize].value, 900);
+ assert_eq!(timeout_tx.input.len(), 1);
+ assert_eq!(timeout_tx.input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); // HTLC 0 <--> 1, timeout tx
+ check_spends!(timeout_tx, remote_txn[0]);
+ assert_eq!(remote_txn[0].output[timeout_tx.input[0].previous_output.vout as usize].value, 900);
let events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 3);
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_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let chan_stat = get_channel_value_stat!(nodes[0], chan.2);
let channel_reserve = chan_stat.channel_reserve_msat;
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_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 3460001);
// Need to manually create the update_add_htlc message to go around the channel reserve check in send_htlc()
push_amt -= Channel::<EnforcingSigner>::get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000;
- let _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, push_amt, InitFeatures::known(), InitFeatures::known());
+ let _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, push_amt, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Sending exactly enough to hit the reserve amount should be accepted
for _ in 0..MIN_AFFORDABLE_HTLC_COUNT {
let mut push_amt = 100_000_000;
push_amt -= commit_tx_fee_msat(feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT as u64, opt_anchors);
push_amt -= Channel::<EnforcingSigner>::get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000;
- let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, push_amt, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, push_amt, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Send four HTLCs to cover the initial push_msat buffer we're required to include
for _ in 0..MIN_AFFORDABLE_HTLC_COUNT {
let mut push_amt = 100_000_000;
push_amt -= commit_tx_fee_msat(feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT as u64, opt_anchors);
push_amt -= Channel::<EnforcingSigner>::get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000;
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, push_amt, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, push_amt, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let dust_amt = crate::ln::channel::MIN_CHAN_DUST_LIMIT_SATOSHIS * 1000
+ feerate_per_kw as u64 * htlc_success_tx_weight(opt_anchors) / 1000 * 1000 - 1;
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, push_amt, 42, None).unwrap();
let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
open_channel_msg.push_msat += 1;
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel_msg);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel_msg);
let msg_events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(msg_events.len(), 1);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 98000000, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 98000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_amt = 46000; // Dust amount
// In the previous code, these first four payments would succeed.
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
- let _ = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let _ = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let feemsat = 239;
let total_routing_fee_msat = (nodes.len() - 2) as u64 * feemsat;
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 _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let channels0 = node_chanmgrs[0].list_channels();
let channels1 = node_chanmgrs[1].list_channels();
let default_config = UserConfig::default();
config.channel_config.forwarding_fee_base_msat = 239;
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config.clone()), Some(config.clone()), Some(config.clone())]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 190000, 1001, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 190000, 1001, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 190000, 1001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 190000, 1001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let mut stat01 = get_channel_value_stat!(nodes[0], chan_1.2);
let mut stat11 = get_channel_value_stat!(nodes[1], chan_1.2);
// attempt to send amt_msat > their_max_htlc_value_in_flight_msat
{
let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
- .with_features(InvoiceFeatures::known()).with_max_channel_saturation_power_of_half(0);
+ .with_features(channelmanager::provided_invoice_features()).with_max_channel_saturation_power_of_half(0);
let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, recv_value_0, TEST_FINAL_CLTV);
route.paths[0].last_mut().unwrap().fee_msat += 1;
assert!(route.paths[0].iter().rev().skip(1).all(|h| h.fee_msat == feemsat));
}
let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
- .with_features(InvoiceFeatures::known()).with_max_channel_saturation_power_of_half(0);
+ .with_features(channelmanager::provided_invoice_features()).with_max_channel_saturation_power_of_half(0);
let route = get_route!(nodes[0], payment_params, recv_value_0, TEST_FINAL_CLTV).unwrap();
let (payment_preimage, ..) = send_along_route(&nodes[0], route, &[&nodes[1], &nodes[2]], recv_value_0);
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
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_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let b_chan_values = get_channel_value_stat!(nodes[1], chan_1.2);
// Route the first two HTLCs.
let nodes = create_network(5, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
- let chan_3 = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
- let chan_4 = create_announced_chan_between_nodes(&nodes, 3, 4, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_3 = create_announced_chan_between_nodes(&nodes, 2, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_4 = create_announced_chan_between_nodes(&nodes, 3, 4, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Make sure all nodes are at the same starting height
connect_blocks(&nodes[0], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
*nodes[0].connect_style.borrow_mut() = ConnectStyle::FullBlockViaListen;
// Create some new channels:
- let chan_5 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_5 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// A pending HTLC which will be revoked:
let payment_preimage_3 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
// We test justice_tx build by A on B's revoked HTLC-Success tx
// Create some new channels:
- let chan_6 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_6 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
{
let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
node_txn.clear();
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_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// node[0] is gonna to revoke an old state thus node[1] should be able to claim the revoked output
let revoked_local_txn = get_local_commitment_txn!(nodes[0], chan_1.2);
assert_eq!(revoked_local_txn.len(), 1);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some new channel:
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Rebalance the network to generate htlc in the two directions
send_payment(&nodes[0], &[&nodes[1]], 8_000_000);
// ANTI_REORG_DELAY confirmations.
mine_transaction(&nodes[1], &node_txn[0]);
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
- expect_payment_failed!(nodes[1], payment_hash_2, true);
+ expect_payment_failed!(nodes[1], payment_hash_2, false);
}
get_announce_close_broadcast_events(&nodes, 0, 1);
assert_eq!(nodes[0].node.list_channels().len(), 0);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Rebalance the network to generate htlc in the two directions
send_payment(&nodes[0], &[&nodes[1]], 8_000_000);
mine_transaction(&nodes[1], &node_txn[3]);
mine_transaction(&nodes[1], &node_txn[4]);
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
- expect_payment_failed!(nodes[1], payment_hash_2, true);
+ expect_payment_failed!(nodes[1], payment_hash_2, false);
}
get_announce_close_broadcast_events(&nodes, 0, 1);
assert_eq!(nodes[0].node.list_channels().len(), 0);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Ensure all nodes are at the same height
let node_max_height = nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32;
*nodes[2].connect_style.borrow_mut() = connect_style;
// Create some intial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Rebalance the network a bit by relaying one payment thorugh all the channels...
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage, _payment_hash, _payment_secret) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3000000);
// Get the will-be-revoked local txn from nodes[2]
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage, _payment_hash, _payment_secret) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], if no_to_remote { 10_000 } else { 3_000_000 });
// Get the will-be-revoked local txn from nodes[2]
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 3);
match events[0] {
- Event::PaymentPathFailed { ref payment_hash, rejected_by_dest: _, ref network_update, .. } => {
+ Event::PaymentPathFailed { ref payment_hash, ref network_update, .. } => {
assert!(failed_htlcs.insert(payment_hash.0));
// If we delivered B's RAA we got an unknown preimage error, not something
// that we should update our routing table for.
_ => panic!("Unexpected event"),
}
match events[1] {
- Event::PaymentPathFailed { ref payment_hash, rejected_by_dest: _, ref network_update, .. } => {
+ Event::PaymentPathFailed { ref payment_hash, ref network_update, .. } => {
assert!(failed_htlcs.insert(payment_hash.0));
assert!(network_update.is_some());
},
_ => panic!("Unexpected event"),
}
match events[2] {
- Event::PaymentPathFailed { ref payment_hash, rejected_by_dest: _, ref network_update, .. } => {
+ Event::PaymentPathFailed { ref payment_hash, ref network_update, .. } => {
assert!(failed_htlcs.insert(payment_hash.0));
assert!(network_update.is_some());
},
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_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Alice -> Bob: Route a payment but without Bob sending revoke_and_ack.
{
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);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
route_payment(&nodes[0], &[&nodes[1]], 10000000);
nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap();
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 1000000);
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);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
// broadcasted, even though it's created by `nodes[0]`.
let expected_temporary_channel_id = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None).unwrap();
let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel);
let (temporary_channel_id, tx, _funding_output) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 1_000_000, 42);
assert_eq!(temporary_channel_id, expected_temporary_channel_id);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
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);
_ => panic!("Unexpected event"),
}
match events[1] {
- Event::PaymentPathFailed { payment_hash, rejected_by_dest, .. } => {
+ Event::PaymentPathFailed { payment_hash, payment_failed_permanently, .. } => {
assert_eq!(payment_hash, payment_hash_5);
- assert!(rejected_by_dest);
+ assert!(payment_failed_permanently);
},
_ => panic!("Unexpected event"),
}
let mut as_channel_ready = None;
if messages_delivered == 0 {
- let (channel_ready, _, _) = create_chan_between_nodes_with_value_a(&nodes[0], &nodes[1], 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let (channel_ready, _, _) = create_chan_between_nodes_with_value_a(&nodes[0], &nodes[1], 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
as_channel_ready = Some(channel_ready);
// nodes[1] doesn't receive the channel_ready message (it'll be re-sent on reconnect)
// Note that we store it so that if we're running with `simulate_broken_lnd` we can deliver
// it before the channel_reestablish message.
} else {
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
}
let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], 1_000_000);
let new_chain_monitor: test_utils::TestChainMonitor;
let nodes_0_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
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);
let events_2 = nodes[1].node.get_and_clear_pending_msg_events();
assert!(events_2.is_empty());
- nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
- let as_reestablish = 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::empty(), remote_network_address: None });
- let bs_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let as_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
// nodes[0] hasn't yet received a channel_ready, so it only sends that on reconnect.
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
check_added_monitors!(nodes[0], 1);
reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
-
- // The channel announcement should be re-generated exactly by broadcast_node_announcement.
- nodes[0].node.broadcast_node_announcement([0, 0, 0], [0; 32], Vec::new());
- let msgs = nodes[0].node.get_and_clear_pending_msg_events();
- let mut found_announcement = false;
- for event in msgs.iter() {
- match event {
- MessageSendEvent::BroadcastChannelAnnouncement { ref msg, .. } => {
- if *msg == chan_announcement { found_announcement = true; }
- },
- MessageSendEvent::BroadcastNodeAnnouncement { .. } => {},
- _ => panic!("Unexpected event"),
- }
- }
- assert!(found_announcement);
}
#[test]
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
*nodes[0].connect_style.borrow_mut() = ConnectStyle::BestBlockFirstSkippingBlocks;
- let funding_tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
+ let funding_tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let conf_height = nodes[0].best_block_info().1 + 1;
connect_blocks(&nodes[0], CHAN_CONFIRM_DEPTH);
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());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage_1, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
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::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
assert_eq!(reestablish_1.len(), 1);
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
assert_eq!(reestablish_2.len(), 1);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let our_payment_hash = if send_partial_mpp {
let (route, our_payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], 100000);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Make sure all nodes are at the same starting height
connect_blocks(&nodes[0], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1);
let nodes_0_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
assert_eq!(nodes[0].node.list_channels().len(), 1);
check_added_monitors!(nodes[0], 1);
- nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[0]);
// Start creating a channel, but stop right before broadcasting the funding transaction
let channel_value = 100000;
let push_msat = 10001;
- let a_flags = InitFeatures::known();
- let b_flags = InitFeatures::known();
+ let a_flags = channelmanager::provided_init_features();
+ let b_flags = channelmanager::provided_init_features();
let node_a = nodes.remove(0);
let node_b = nodes.remove(0);
node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None).unwrap();
assert_eq!(nodes[0].node.list_channels().len(), 1);
check_added_monitors!(nodes[0], 1);
- nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[0]);
let new_chain_monitor: test_utils::TestChainMonitor;
let nodes_0_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
let (our_payment_preimage, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
let (_, our_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
let new_chain_monitor: test_utils::TestChainMonitor;
let nodes_0_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- let chan_id_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
- let chan_id_2 = create_announced_chan_between_nodes(&nodes, 2, 0, InitFeatures::known(), InitFeatures::known()).2;
- let (_, _, channel_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 3, InitFeatures::known(), InitFeatures::known());
+ let chan_id_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
+ let chan_id_2 = create_announced_chan_between_nodes(&nodes, 2, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
+ let (_, _, channel_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let mut node_0_stale_monitors_serialized = Vec::new();
for chan_id_iter in &[chan_id_1, chan_id_2, channel_id] {
//... and we can even still claim the payment!
claim_payment(&nodes[2], &[&nodes[0], &nodes[1]], our_payment_preimage);
- nodes[3].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
- let reestablish = get_event_msg!(nodes[3], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
- nodes[0].node.peer_connected(&nodes[3].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[3].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let reestablish = get_chan_reestablish_msgs!(nodes[3], nodes[0]).pop().unwrap();
+ nodes[0].node.peer_connected(&nodes[3].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
nodes[0].node.handle_channel_reestablish(&nodes[3].node.get_our_node_id(), &reestablish);
- let msg_events = nodes[0].node.get_and_clear_pending_msg_events();
- assert_eq!(msg_events.len(), 1);
- if let MessageSendEvent::HandleError { ref action, .. } = msg_events[0] {
- match action {
- &ErrorAction::SendErrorMessage { ref msg } => {
- assert_eq!(msg.channel_id, channel_id);
- },
- _ => panic!("Unexpected event!"),
+ let mut found_err = false;
+ for msg_event in nodes[0].node.get_and_clear_pending_msg_events() {
+ if let MessageSendEvent::HandleError { ref action, .. } = msg_event {
+ match action {
+ &ErrorAction::SendErrorMessage { ref msg } => {
+ assert_eq!(msg.channel_id, channel_id);
+ assert!(!found_err);
+ found_err = true;
+ },
+ _ => panic!("Unexpected event!"),
+ }
}
}
+ assert!(found_err);
}
macro_rules! check_spendable_outputs {
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_with_value(&nodes, 0, 1, 100_000, 98_000_000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 98_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()).unwrap();
check_closed_broadcast!(nodes[1], true);
check_added_monitors!(nodes[1], 1);
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_with_value(&nodes, 0, 1, 100_000, 98_000_000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 98_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[0].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[1].node.get_our_node_id()).unwrap();
check_closed_broadcast!(nodes[0], true);
check_added_monitors!(nodes[0], 1);
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_with_value(&nodes, 0, 1, 100000, 59000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 59000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
let revoked_local_txn = get_local_commitment_txn!(nodes[0], chan.2);
assert_eq!(revoked_local_txn[0].input.len(), 1);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 3_000_000);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Rebalance the network a bit by relaying one payment through all the channels ...
send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
mine_transaction(&nodes[1], &node_txn[1]);
check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed);
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
- expect_payment_failed!(nodes[1], our_payment_hash, true);
+ expect_payment_failed!(nodes[1], our_payment_hash, false);
let spend_txn = check_spendable_outputs!(nodes[1], node_cfgs[1].keys_manager);
assert_eq!(spend_txn.len(), 3); // SpendableOutput: remote_commitment_tx.to_remote, timeout_tx.output
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
let revoked_local_txn = get_local_commitment_txn!(nodes[0], chan_1.2);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
let revoked_local_txn = get_local_commitment_txn!(nodes[0], chan_1.2);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
let revoked_local_txn = get_local_commitment_txn!(nodes[1], chan_1.2);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Ensure all nodes are at the same height
let node_max_height = nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32;
&[Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone())]);
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 2, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let node_max_height = nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32;
connect_blocks(&nodes[0], node_max_height - nodes[0].best_block_info().1);
// script push size limit so that the below script length checks match
// ACCEPTED_HTLC_SCRIPT_WEIGHT.
let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id())
- .with_features(InvoiceFeatures::known());
+ .with_features(channelmanager::provided_invoice_features());
let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[3], payment_params, 900000, TEST_FINAL_CLTV - 40);
send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[2], &nodes[3]]], 900000, duplicate_payment_hash, payment_secret);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 9_000_000);
let local_txn = get_local_commitment_txn!(nodes[1], chan_1.2);
&[Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone())]);
let nodes = create_network(6, &node_cfgs, &node_chanmgrs);
- let _chan_0_2 = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::known(), InitFeatures::known());
- let _chan_1_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
- let chan_2_3 = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
- let chan_3_4 = create_announced_chan_between_nodes(&nodes, 3, 4, InitFeatures::known(), InitFeatures::known());
- let chan_3_5 = create_announced_chan_between_nodes(&nodes, 3, 5, InitFeatures::known(), InitFeatures::known());
+ let _chan_0_2 = create_announced_chan_between_nodes(&nodes, 0, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let _chan_1_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2_3 = create_announced_chan_between_nodes(&nodes, 2, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_3_4 = create_announced_chan_between_nodes(&nodes, 3, 4, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_3_5 = create_announced_chan_between_nodes(&nodes, 3, 5, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Rebalance and check output sanity...
send_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 500000);
let mut as_failds = HashSet::new();
let mut as_updates = 0;
for event in as_events.iter() {
- if let &Event::PaymentPathFailed { ref payment_hash, ref rejected_by_dest, ref network_update, .. } = event {
+ if let &Event::PaymentPathFailed { ref payment_hash, ref payment_failed_permanently, ref network_update, .. } = event {
assert!(as_failds.insert(*payment_hash));
if *payment_hash != payment_hash_2 {
- assert_eq!(*rejected_by_dest, deliver_last_raa);
+ assert_eq!(*payment_failed_permanently, deliver_last_raa);
} else {
- assert!(!rejected_by_dest);
+ assert!(!payment_failed_permanently);
}
if network_update.is_some() {
as_updates += 1;
let mut bs_failds = HashSet::new();
let mut bs_updates = 0;
for event in bs_events.iter() {
- if let &Event::PaymentPathFailed { ref payment_hash, ref rejected_by_dest, ref network_update, .. } = event {
+ if let &Event::PaymentPathFailed { ref payment_hash, ref payment_failed_permanently, ref network_update, .. } = event {
assert!(bs_failds.insert(*payment_hash));
if *payment_hash != payment_hash_1 && *payment_hash != payment_hash_5 {
- assert_eq!(*rejected_by_dest, deliver_last_raa);
+ assert_eq!(*payment_failed_permanently, deliver_last_raa);
} else {
- assert!(!rejected_by_dest);
+ assert!(!payment_failed_permanently);
}
if network_update.is_some() {
bs_updates += 1;
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (_, our_payment_hash, _) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000);
let local_txn = get_local_commitment_txn!(nodes[0], chan_1.2);
mine_transaction(&nodes[0], &htlc_timeout);
connect_blocks(&nodes[0], BREAKDOWN_TIMEOUT as u32 - 1);
- expect_payment_failed!(nodes[0], our_payment_hash, true);
+ expect_payment_failed!(nodes[0], our_payment_hash, false);
// Verify that A is able to spend its own HTLC-Timeout tx thanks to spendable output event given back by its ChannelMonitor
let spend_txn = check_spendable_outputs!(nodes[0], node_cfgs[0].keys_manager);
let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
let chain_monitor = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[0].chain_source), &chanmon_cfgs[0].tx_broadcaster, &chanmon_cfgs[0].logger, &chanmon_cfgs[0].fee_estimator, &chanmon_cfgs[0].persister, &keys_manager);
let network_graph = NetworkGraph::new(chanmon_cfgs[0].chain_source.genesis_hash, &chanmon_cfgs[0].logger);
- let node = NodeCfg { chain_source: &chanmon_cfgs[0].chain_source, logger: &chanmon_cfgs[0].logger, tx_broadcaster: &chanmon_cfgs[0].tx_broadcaster, fee_estimator: &chanmon_cfgs[0].fee_estimator, chain_monitor, keys_manager: &keys_manager, network_graph, node_seed: seed, features: InitFeatures::known() };
+ let node = NodeCfg { chain_source: &chanmon_cfgs[0].chain_source, logger: &chanmon_cfgs[0].logger, tx_broadcaster: &chanmon_cfgs[0].tx_broadcaster, fee_estimator: &chanmon_cfgs[0].fee_estimator, chain_monitor, keys_manager: &keys_manager, network_graph, node_seed: seed, features: channelmanager::provided_init_features() };
let mut node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
node_cfgs.remove(0);
node_cfgs.insert(0, node);
// Create some initial channels
// Create a dummy channel to advance index by one and thus test re-derivation correctness
// for node 0
- let chan_0 = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::known(), InitFeatures::known());
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_0 = create_announced_chan_between_nodes(&nodes, 0, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
assert_ne!(chan_0.3.output[0].script_pubkey, chan_1.3.output[0].script_pubkey);
// Ensure all nodes are at the same height
mine_transaction(&nodes[0], &htlc_timeout);
connect_blocks(&nodes[0], BREAKDOWN_TIMEOUT as u32 - 1);
- expect_payment_failed!(nodes[0], our_payment_hash, true);
+ expect_payment_failed!(nodes[0], our_payment_hash, false);
// Verify that A is able to spend its own HTLC-Timeout tx thanks to spendable output event given back by its ChannelMonitor
let new_keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
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 chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
let closing_tx = close_channel(&nodes[0], &nodes[1], &chan.2, chan.3, true).2;
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 chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], if use_dust { 50000 } else { 3_000_000 });
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 chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], if use_dust { 50000 } else { 3000000 });
nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Fail the payment, but don't deliver A's final RAA, resulting in the HTLC only being present
// in B's previous (unrevoked) commitment transaction, but none of A's commitment transactions.
let push_msat=10001;
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None).unwrap();
let node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &node0_to_1_send_open_channel);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &node0_to_1_send_open_channel);
get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
// Create a second channel with the same random values. This used to panic due to a colliding
node0_to_1_send_open_channel.dust_limit_satoshis = 547;
node0_to_1_send_open_channel.channel_reserve_satoshis = 100001;
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &node0_to_1_send_open_channel);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &node0_to_1_send_open_channel);
let events = nodes[1].node.get_and_clear_pending_msg_events();
let err_msg = match events[0] {
MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id: _ } => {
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_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// First nodes[0] generates an update_fee, setting the channel's
// pending_update_fee.
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match &events[0] {
- &Event::PaymentPathFailed { ref payment_id, ref payment_hash, ref rejected_by_dest, ref network_update, ref all_paths_failed, ref short_channel_id, ref error_code, ref error_data, .. } => {
+ &Event::PaymentPathFailed { ref payment_id, ref payment_hash, ref payment_failed_permanently, ref network_update, ref all_paths_failed, ref short_channel_id, .. } => {
assert_eq!(our_payment_id, *payment_id.as_ref().unwrap());
assert_eq!(our_payment_hash.clone(), *payment_hash);
- assert_eq!(*rejected_by_dest, false);
+ assert_eq!(*payment_failed_permanently, false);
assert_eq!(*all_paths_failed, true);
assert_eq!(*network_update, None);
- assert_eq!(*short_channel_id, None);
- assert_eq!(*error_code, None);
- assert_eq!(*error_data, None);
+ assert_eq!(*short_channel_id, Some(route.paths[0][0].short_channel_id));
},
_ => panic!("Unexpected event"),
}
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_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// First nodes[0] generates an update_fee, setting the channel's
// pending_update_fee.
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match &events[0] {
- &Event::PaymentPathFailed { ref payment_id, ref payment_hash, ref rejected_by_dest, ref network_update, ref all_paths_failed, ref short_channel_id, ref error_code, ref error_data, .. } => {
+ &Event::PaymentPathFailed { ref payment_id, ref payment_hash, ref payment_failed_permanently, ref network_update, ref all_paths_failed, ref short_channel_id, .. } => {
assert_eq!(payment_id_2, *payment_id.as_ref().unwrap());
assert_eq!(payment_hash_2.clone(), *payment_hash);
- assert_eq!(*rejected_by_dest, false);
+ assert_eq!(*payment_failed_permanently, false);
assert_eq!(*all_paths_failed, true);
assert_eq!(*network_update, None);
- assert_eq!(*short_channel_id, None);
- assert_eq!(*error_code, None);
- assert_eq!(*error_data, None);
+ assert_eq!(*short_channel_id, Some(route_2.paths[0][0].short_channel_id));
},
_ => panic!("Unexpected event"),
}
config.channel_config.forwarding_fee_base_msat = 196;
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config.clone()), Some(config.clone()), Some(config.clone())]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_0_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
- let chan_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let chan_0_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// First nodes[1] generates an update_fee, setting the channel's
// pending_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_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
route.paths[0][0].fee_msat = 100;
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_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
route.paths[0][0].fee_msat = 0;
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_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
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_with_value(&nodes, 0, 1, 1000000, 0, InitFeatures::known(), InitFeatures::known());
+ let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
- .with_features(InvoiceFeatures::known());
+ .with_features(channelmanager::provided_invoice_features());
let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, 100000000, 0);
route.paths[0].last_mut().unwrap().cltv_expiry_delta = 500000001;
unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)), true, APIError::RouteError { ref err },
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_with_value(&nodes, 0, 1, 1000000, 0, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let max_accepted_htlcs = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().counterparty_max_accepted_htlcs as u64;
for i in 0..max_accepted_htlcs {
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let channel_value = 100000;
- let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value, 0, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let max_in_flight = get_channel_value_stat!(nodes[0], chan.2).counterparty_max_htlc_value_in_flight_msat;
send_payment(&nodes[0], &vec!(&nodes[1])[..], max_in_flight);
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_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let htlc_minimum_msat: u64;
{
let chan_lock = nodes[0].node.channel_state.lock().unwrap();
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_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let chan_stat = get_channel_value_stat!(nodes[0], chan.2);
let channel_reserve = chan_stat.channel_reserve_msat;
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_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 3999999);
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
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_with_value(&nodes, 0, 1, 1000000, 1000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
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_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
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());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
//Disconnect and 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::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
assert_eq!(reestablish_1.len(), 1);
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
assert_eq!(reestablish_2.len(), 1);
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &reestablish_2[0]);
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 chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
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 chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
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 chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
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);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (our_payment_preimage, our_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 100_000);
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);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (our_payment_preimage, our_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 100_000);
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_with_value(&nodes, 0, 1, 1000000, 1000000, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1000000, 1000000, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1000000, 1000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 100000);
check_added_monitors!(nodes[1], 1);
}
+#[test]
+fn test_channel_failed_after_message_with_badonion_node_perm_bits_set() {
+ let chanmon_cfgs = create_chanmon_cfgs(3);
+ let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
+ let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+
+ let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 100_000);
+
+ // First hop
+ let mut payment_event = {
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
+ check_added_monitors!(nodes[0], 1);
+ SendEvent::from_node(&nodes[0])
+ };
+
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
+ commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
+ expect_pending_htlcs_forwardable!(nodes[1]);
+ check_added_monitors!(nodes[1], 1);
+ payment_event = SendEvent::from_node(&nodes[1]);
+ assert_eq!(payment_event.msgs.len(), 1);
+
+ // Second Hop
+ payment_event.msgs[0].onion_routing_packet.version = 1; // Trigger an invalid_onion_version error
+ nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &payment_event.msgs[0]);
+ check_added_monitors!(nodes[2], 0);
+ commitment_signed_dance!(nodes[2], nodes[1], payment_event.commitment_msg, false, true);
+
+ let events_3 = nodes[2].node.get_and_clear_pending_msg_events();
+ assert_eq!(events_3.len(), 1);
+ match events_3[0] {
+ MessageSendEvent::UpdateHTLCs { ref updates, .. } => {
+ let mut update_msg = updates.update_fail_malformed_htlcs[0].clone();
+ // Set the NODE bit (BADONION and PERM already set in invalid_onion_version error)
+ update_msg.failure_code |= 0x2000;
+
+ nodes[1].node.handle_update_fail_malformed_htlc(&nodes[2].node.get_our_node_id(), &update_msg);
+ commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false, true);
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1],
+ vec![HTLCDestination::NextHopChannel {
+ node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]);
+ let events_4 = nodes[1].node.get_and_clear_pending_msg_events();
+ assert_eq!(events_4.len(), 1);
+ check_added_monitors!(nodes[1], 1);
+
+ match events_4[0] {
+ MessageSendEvent::UpdateHTLCs { ref updates, .. } => {
+ nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
+ commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false, true);
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ let events_5 = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events_5.len(), 1);
+
+ // Expect a PaymentPathFailed event with a ChannelFailure network update for the channel between
+ // the node originating the error to its next hop.
+ match events_5[0] {
+ Event::PaymentPathFailed { network_update:
+ Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent }), error_code, ..
+ } => {
+ assert_eq!(short_channel_id, chan_2.0.contents.short_channel_id);
+ assert!(is_permanent);
+ assert_eq!(error_code, Some(0x8000|0x4000|0x2000|4));
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ // TODO: Test actual removal of channel from NetworkGraph when it's implemented.
+}
+
fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) {
// Dust-HTLC failure updates must be delayed until failure-trigger tx (in this case local commitment) reach ANTI_REORG_DELAY
// We can have at most two valid local commitment tx, so both cases must be covered, and both txs must be checked to get them all as
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 chan =create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let bs_dust_limit = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().holder_dust_limit_satoshis;
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let bs_dust_limit = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().holder_dust_limit_satoshis;
mine_transaction(&nodes[0], &as_commitment_tx[0]);
check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed);
connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1);
- expect_payment_failed!(nodes[0], dust_hash, true);
+ expect_payment_failed!(nodes[0], dust_hash, false);
connect_blocks(&nodes[0], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS - ANTI_REORG_DELAY);
check_closed_broadcast!(nodes[0], true);
assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
mine_transaction(&nodes[0], &timeout_tx[0]);
connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1);
- expect_payment_failed!(nodes[0], non_dust_hash, true);
+ expect_payment_failed!(nodes[0], non_dust_hash, false);
} else {
// We fail dust-HTLC 1 by broadcast of remote commitment tx. If revoked, fail also non-dust HTLC
mine_transaction(&nodes[0], &bs_commitment_tx[0]);
check_spends!(timeout_tx[0], bs_commitment_tx[0]);
// For both a revoked or non-revoked commitment transaction, after ANTI_REORG_DELAY the
// dust HTLC should have been failed.
- expect_payment_failed!(nodes[0], dust_hash, true);
+ expect_payment_failed!(nodes[0], dust_hash, false);
if !revoked {
assert_eq!(timeout_tx[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
mine_transaction(&nodes[0], &timeout_tx[0]);
assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1);
- expect_payment_failed!(nodes[0], non_dust_hash, true);
+ expect_payment_failed!(nodes[0], non_dust_hash, false);
}
}
// We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in Channel::new_outbound()
if let Err(error) = Channel::new_outbound(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
- &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &InitFeatures::known(), 1000000, 1000000, 0,
+ &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), 1000000, 1000000, 0,
&low_our_to_self_config, 0, 42)
{
match error {
let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
open_channel.to_self_delay = 200;
if let Err(error) = Channel::new_from_req(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
- &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &InitFeatures::known(), &open_channel, 0,
+ &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &open_channel, 0,
&low_our_to_self_config, 0, &nodes[0].logger, 42)
{
match error {
// We test msg.to_self_delay <= config.their_to_self_delay is enforced in Chanel::accept_channel()
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 1000000, 1000000, 42, None).unwrap();
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()));
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()));
let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
accept_channel.to_self_delay = 200;
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel);
let reason_msg;
if let MessageSendEvent::HandleError { ref action, .. } = nodes[0].node.get_and_clear_pending_msg_events()[0] {
match action {
let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
open_channel.to_self_delay = 200;
if let Err(error) = Channel::new_from_req(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
- &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &InitFeatures::known(), &open_channel, 0,
+ &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &open_channel, 0,
&high_their_to_self_config, 0, &nodes[0].logger, 42)
{
match error {
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_with_value(&nodes, 0, 1, 1000000, 1000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Cache node A state before any channel update
let previous_node_state = nodes[0].node.encode();
check_added_monitors!(nodes[0], 1);
if reconnect_panicing {
- nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
// after the warning message sent by B, we should not able to
// use the channel, or reconnect with success to the channel.
assert!(nodes[0].node.list_usable_channels().is_empty());
- nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let retry_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &retry_reestablish[0]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let scorer = test_utils::TestScorer::with_penalty(0);
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
- let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id()).with_features(InvoiceFeatures::known());
+ let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id()).with_features(channelmanager::provided_invoice_features());
let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), None, 10_000, TEST_FINAL_CLTV, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
let (_, our_payment_hash, _) = get_payment_preimage_hash!(nodes[0]);
let our_payment_secret = nodes[1].node.create_inbound_payment_for_hash(our_payment_hash, Some(100_000), 7200).unwrap();
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 1, 0, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 1, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Disconnect peers
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
}
}
// Reconnect peers
- nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
assert_eq!(reestablish_1.len(), 3);
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
assert_eq!(reestablish_2.len(), 3);
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_with_value(&nodes, 0, 1, 1000000, 59000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id())
- .with_features(InvoiceFeatures::known());
+ .with_features(channelmanager::provided_invoice_features());
let (route,_, _, _) = get_route_and_payment_hash!(nodes[1], nodes[0], payment_params, 3000000, 30);
send_along_route(&nodes[1], route, &vec!(&nodes[0])[..], 3000000);
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_with_value(&nodes, 0, 1, 1000000, 59000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Lock HTLC in both directions (using a slightly lower CLTV delay to provide timely RBF bumps)
- let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id()).with_features(InvoiceFeatures::known());
+ let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id()).with_features(channelmanager::provided_invoice_features());
let scorer = test_utils::TestScorer::with_penalty(0);
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), None,
3_000_000, 50, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
let payment_preimage = send_along_route(&nodes[0], route, &[&nodes[1]], 3_000_000).0;
- let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id()).with_features(InvoiceFeatures::known());
+ let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id()).with_features(channelmanager::provided_invoice_features());
let route = get_route(&nodes[1].node.get_our_node_id(), &payment_params, &nodes[1].network_graph.read_only(), None,
3_000_000, 50, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
send_along_route(&nodes[1], route, &[&nodes[0]], 3_000_000);
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_with_value(&nodes, 0, 1, 1000000, 59000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 3_000_000);
route_payment(&nodes[1], &vec!(&nodes[0])[..], 3000000).0;
let feerate_preimage;
{
let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
- // 9 transactions including:
- // 1*2 ChannelManager local broadcasts of commitment + HTLC-Success
- // 1*3 ChannelManager local broadcasts of commitment + HTLC-Success + HTLC-Timeout
- // 2 * HTLC-Success (one RBF bump we'll check later)
- // 1 * HTLC-Timeout
- assert_eq!(node_txn.len(), 8);
+ // 5 transactions including:
+ // local commitment + HTLC-Success
+ // preimage and timeout sweeps from remote commitment + preimage sweep bump
+ assert_eq!(node_txn.len(), 5);
assert_eq!(node_txn[0].input.len(), 1);
- assert_eq!(node_txn[6].input.len(), 1);
+ assert_eq!(node_txn[3].input.len(), 1);
+ assert_eq!(node_txn[4].input.len(), 1);
check_spends!(node_txn[0], remote_txn[0]);
- check_spends!(node_txn[6], remote_txn[0]);
-
- check_spends!(node_txn[1], chan.3);
- check_spends!(node_txn[2], node_txn[1]);
+ check_spends!(node_txn[3], remote_txn[0]);
+ check_spends!(node_txn[4], remote_txn[0]);
- if node_txn[0].input[0].previous_output == node_txn[3].input[0].previous_output {
- preimage_bump = node_txn[3].clone();
- check_spends!(node_txn[3], remote_txn[0]);
-
- assert_eq!(node_txn[1], node_txn[4]);
- assert_eq!(node_txn[2], node_txn[5]);
- } else {
- preimage_bump = node_txn[7].clone();
- check_spends!(node_txn[7], remote_txn[0]);
- assert_eq!(node_txn[0].input[0].previous_output, node_txn[7].input[0].previous_output);
-
- assert_eq!(node_txn[1], node_txn[3]);
- assert_eq!(node_txn[2], node_txn[4]);
- }
-
- timeout = node_txn[6].txid();
- let index = node_txn[6].input[0].previous_output.vout;
- let fee = remote_txn[0].output[index as usize].value - node_txn[6].output[0].value;
- feerate_timeout = fee * 1000 / node_txn[6].weight() as u64;
+ check_spends!(node_txn[1], chan.3); // local commitment
+ check_spends!(node_txn[2], node_txn[1]); // local HTLC-Success
preimage = node_txn[0].txid();
let index = node_txn[0].input[0].previous_output.vout;
let fee = remote_txn[0].output[index as usize].value - node_txn[0].output[0].value;
feerate_preimage = fee * 1000 / node_txn[0].weight() as u64;
+ let (preimage_bump_tx, timeout_tx) = if node_txn[3].input[0].previous_output == node_txn[0].input[0].previous_output {
+ (node_txn[3].clone(), node_txn[4].clone())
+ } else {
+ (node_txn[4].clone(), node_txn[3].clone())
+ };
+
+ preimage_bump = preimage_bump_tx;
+ check_spends!(preimage_bump, remote_txn[0]);
+ assert_eq!(node_txn[0].input[0].previous_output, preimage_bump.input[0].previous_output);
+
+ timeout = timeout_tx.txid();
+ let index = timeout_tx.input[0].previous_output.vout;
+ let fee = remote_txn[0].output[index as usize].value - timeout_tx.output[0].value;
+ feerate_timeout = fee * 1000 / timeout_tx.weight() as u64;
+
node_txn.clear();
};
assert_ne!(feerate_timeout, 0);
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 channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
let per_commitment_secret;
let next_per_commitment_point;
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_with_value(&nodes, 0, 1, 1000000, 59000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Lock HTLC in both directions
let (payment_preimage_1, _, _) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000);
let (_, payment_hash_2, _) = route_payment(&nodes[1], &vec!(&nodes[0])[..], 9_000_000);
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);
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 1_010_000);
nodes[1].node.claim_funds(payment_preimage);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let _funding_tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 1_000_000, 100_000, InitFeatures::known(), InitFeatures::known());
+ let _funding_tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 1_000_000, 100_000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// The outbound node should wait forever for confirmation:
// This matches `channel::FUNDING_CONF_DEADLINE_BLOCKS` and BOLT 2's suggested timeout, thus is
let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
assert_eq!(res.htlc_minimum_msat, 1);
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &res);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &res);
let res = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
assert_eq!(res.htlc_minimum_msat, 1);
}
let channel_value_50_percent_msat = (channel_value_msat as f64 * 0.5) as u64;
let channel_value_90_percent_msat = (channel_value_msat as f64 * 0.9) as u64;
- let (node_0_chan_update, node_1_chan_update, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value_satoshis, 10001, InitFeatures::known(), InitFeatures::known());
- let (node_2_chan_update, node_3_chan_update, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, channel_value_satoshis, 10001, InitFeatures::known(), InitFeatures::known());
+ let (node_0_chan_update, node_1_chan_update, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value_satoshis, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let (node_2_chan_update, node_3_chan_update, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, channel_value_satoshis, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Assert that `node[0]`'s `ChannelUpdate` is capped at 50 percent of the `channel_value`, as
// that's the value of `node[1]`'s `holder_max_htlc_value_in_flight_msat`.
let temp_channel_id = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, Some(manually_accept_conf)).unwrap();
let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &res);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &res);
// Assert that `nodes[1]` has no `MessageSendEvent::SendAcceptChannel` in `msg_events` before
// accepting the inbound channel request.
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, Some(manually_accept_conf)).unwrap();
let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &res);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &res);
// Assert that `nodes[1]` has no `MessageSendEvent::SendAcceptChannel` in `msg_events` before
// rejecting the inbound channel request.
let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
let temp_channel_id = res.temporary_channel_id;
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &res);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &res);
// Assert that `nodes[1]` has no `MessageSendEvent::SendAcceptChannel` in the `msg_events`.
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
let channel = get_channel_ref!(&nodes[1], lock, temp_channel_id);
channel.get_accept_channel_message()
};
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_chan_msg);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_chan_msg);
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, Some(manually_accept_conf)).unwrap();
let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &res);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &res);
// Assert that `nodes[1]` has no `MessageSendEvent::SendAcceptChannel` in `msg_events` before
// accepting the inbound channel request.
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
- let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
- let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
- let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+ let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
+ let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
+ let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
+ let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[3], 100000);
let path = route.paths[0].clone();
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
{
let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(100_000), 7200).unwrap();
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
let (payment_hash, payment_secret_1) = nodes[1].node.create_inbound_payment_legacy(Some(100_000), 2).unwrap();
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
let random_payment_hash = PaymentHash([42; 32]);
let random_payment_secret = PaymentSecret([43; 32]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some initial channel
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let outpoint = OutPoint { txid: chan_1.3.txid(), index: 0 };
// Rebalance the network to generate htlc in the two directions
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some initial channel
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let outpoint = OutPoint { txid: chan_1.3.txid(), index: 0 };
// Rebalance the network to generate htlc in the two directions
watchtower_alice.chain_monitor.block_connected(&Block { header, txdata: vec![bob_state_y.clone()] }, CHAN_CONFIRM_DEPTH + 2 + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS);
{
let htlc_txn = chanmon_cfgs[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
- // We broadcast twice the transaction, once due to the HTLC-timeout, once due
- // the onchain detection of the HTLC output
- assert_eq!(htlc_txn.len(), 2);
+ assert_eq!(htlc_txn.len(), 1);
check_spends!(htlc_txn[0], bob_state_y);
- check_spends!(htlc_txn[1], bob_state_y);
}
}
// Create an initial channel
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_msg);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_chan_msg);
let accept_chan_msg = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_chan_msg);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_chan_msg);
// Move the first channel through the funding flow...
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
send_payment(&nodes[0], &vec!(&nodes[1])[..], 1_000_000);
let (_, our_payment_hash, _) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 2_000_000);
let header_201 = BlockHeader { version: 0x20000000, prev_blockhash: nodes[0].best_block_hash(), merkle_root: TxMerkleNode::all_zeros(), time: 42, bits: 42, nonce: 42 };
connect_block(&nodes[0], &Block { header: header_201, txdata: vec![htlc_timeout.clone()] });
connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1);
- expect_payment_failed!(nodes[0], our_payment_hash, true);
+ expect_payment_failed!(nodes[0], our_payment_hash, false);
}
fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain_before_fulfill: bool) {
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_ab = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_ab = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Steps (1) and (2):
// Send an HTLC Alice --> Bob --> Carol, but Carol doesn't settle the HTLC back.
// Create an initial channel
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_msg);
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_chan_msg);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
// Try to create a second channel with the same temporary_channel_id as the first and check
// that it is rejected.
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_msg);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_chan_msg);
{
let events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
// Technically this is allowed by the spec, but we don't support it and there's little reason
// to. Still, it shouldn't cause any other issues.
open_chan_msg.temporary_channel_id = channel_id;
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_msg);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_chan_msg);
{
let events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
// Now try to create a second channel which has a duplicate funding output.
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
let open_chan_2_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_2_msg);
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_chan_2_msg);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); // Get and check the FundingGenerationReady event
let funding_created = {
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
// Create some initial channels
- let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
- let chan_3 = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_3 = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
assert_eq!(nodes[0].node.list_usable_channels().len(), 3);
assert_eq!(nodes[1].node.list_usable_channels().len(), 2);
assert!(nodes[0].node.list_usable_channels()[0].channel_id == chan_3.2 || nodes[0].node.list_usable_channels()[1].channel_id == chan_3.2);
// A null channel ID should close all channels
- let _chan_4 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let _chan_4 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[0].node.handle_error(&nodes[1].node.get_our_node_id(), &msgs::ErrorMessage { channel_id: [0; 32], data: "ERR".to_owned() });
check_added_monitors!(nodes[0], 2);
check_closed_event!(nodes[0], 2, ClosureReason::CounterpartyForceClosed { peer_msg: "ERR".to_string() });
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 10_000, 42, None).unwrap();
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()));
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()));
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
let (temporary_channel_id, mut tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100_000, 42);
// a panic as we'd try to extract a 32 byte preimage from a witness element without checking
// its length.
let mut wit_program: Vec<u8> = channelmonitor::deliberately_bogus_accepted_htlc_witness_program();
- assert!(chan_utils::HTLCType::scriptlen_to_htlctype(wit_program.len()).unwrap() ==
- chan_utils::HTLCType::AcceptedHTLC);
-
- let wit_program_script: Script = wit_program.clone().into();
+ let wit_program_script: Script = wit_program.into();
for output in tx.output.iter_mut() {
// Make the confirmed funding transaction have a bogus script_pubkey
output.script_pubkey = Script::new_v0_p2wsh(&wit_program_script.wscript_hash());
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
*nodes[0].connect_style.borrow_mut() = ConnectStyle::BestBlockFirstSkippingBlocks;
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let (chan_announce, _, channel_id, _) = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let (chan_announce, _, channel_id, _) = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (_, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000);
nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id(), false);
nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
let new_chain_monitor: test_utils::TestChainMonitor;
let nodes_1_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_id_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
- let chan_id_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known()).2;
+ let chan_id_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
+ let chan_id_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
// First send a payment to nodes[1]
let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000);
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_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
- .with_features(InvoiceFeatures::known());
+ .with_features(channelmanager::provided_invoice_features());
let route = get_route!(nodes[0], payment_params, 10_000, TEST_FINAL_CLTV).unwrap();
let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(&nodes[1]);
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100_000, 0, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0, InitFeatures::known(), InitFeatures::known());
- let chan_2_3 =create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2_3 =create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id())
- .with_features(InvoiceFeatures::known());
+ .with_features(channelmanager::provided_invoice_features());
let mut route = get_route!(nodes[0], payment_params, 15_000_000, TEST_FINAL_CLTV).unwrap();
assert_eq!(route.paths.len(), 2);
route.paths.sort_by(|path_a, _| {
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_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let network_graph = nodes[0].network_graph;
let payer_pubkey = nodes[0].node.get_our_node_id();
let payee_pubkey = nodes[1].node.get_our_node_id();
let payer_pubkey = nodes[0].node.get_our_node_id();
let payee_pubkey = nodes[1].node.get_our_node_id();
- nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None });
- nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None });
+ nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
- let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known());
+ let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], channelmanager::provided_init_features(), channelmanager::provided_init_features());
let route_params = RouteParameters {
payment_params: PaymentParameters::for_keysend(payee_pubkey),
final_value_msat: 10000,
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100_000, 0, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[3], 15_000_000);
assert_eq!(route.paths.len(), 2);
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100_000, 0, InitFeatures::known(), InitFeatures::known());
- let chan_id_persisted = create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0, InitFeatures::known(), InitFeatures::known()).2;
- let chan_id_not_persisted = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0, InitFeatures::known(), InitFeatures::known()).2;
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_id_persisted = create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
+ let chan_id_not_persisted = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
// Create an MPP route for 15k sats, more than the default htlc-max of 10%
let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[3], 15_000_000);
if !persist_both_monitors {
// If one of the two channels is still live, reveal the payment preimage over it.
- nodes[3].node.peer_connected(&nodes[2].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[3].node.peer_connected(&nodes[2].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_1 = get_chan_reestablish_msgs!(nodes[3], nodes[2]);
- nodes[2].node.peer_connected(&nodes[3].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[2].node.peer_connected(&nodes[3].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
let reestablish_2 = get_chan_reestablish_msgs!(nodes[2], nodes[3]);
nodes[2].node.handle_channel_reestablish(&nodes[3].node.get_our_node_id(), &reestablish_1[0]);
if on_holder_tx {
open_channel.dust_limit_satoshis = 546;
}
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel);
let opt_anchors = false;
let temp_channel_id = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None).unwrap();
let open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel_message);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel_message);
let accept_channel_message = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel_message);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel_message);
let best_height = nodes[0].node.best_block.read().unwrap().height();
use chain::transaction::OutPoint;
use chain::chaininterface::LowerBoundedFeeEstimator;
use ln::channel;
-use ln::channelmanager::BREAKDOWN_TIMEOUT;
-use ln::features::InitFeatures;
+use ln::channelmanager::{self, BREAKDOWN_TIMEOUT};
use ln::msgs::ChannelMessageHandler;
use util::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination};
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let (update_a, _, chan_id_2, _) = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let (update_a, _, chan_id_2, _) = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 1_000_000);
nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
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_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_hash_1 = route_payment(&nodes[1], &[&nodes[0]], 1_000_000).1;
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
- expect_payment_failed!(nodes[1], payment_hash_1, true);
+ expect_payment_failed!(nodes[1], payment_hash_1, false);
}
#[test]
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let (_, _, chan_id, funding_tx) =
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 1_000_000, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 1_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 };
assert_eq!(funding_outpoint.to_channel_id(), chan_id);
nodes[0].node.close_channel(&chan_id, &nodes[1].node.get_our_node_id()).unwrap();
let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_1_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_1_shutdown);
let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id());
nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_closing_signed);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let (_, _, chan_id, funding_tx) =
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 1_000_000, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 1_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 };
assert_eq!(funding_outpoint.to_channel_id(), chan_id);
sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()));
connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1);
- expect_payment_failed!(nodes[0], dust_payment_hash, true);
+ expect_payment_failed!(nodes[0], dust_payment_hash, false);
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
// After ANTI_REORG_DELAY, A will consider its balance fully spendable and generate a
connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1);
assert_eq!(Vec::<Balance>::new(),
nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances());
- expect_payment_failed!(nodes[0], timeout_payment_hash, true);
+ expect_payment_failed!(nodes[0], timeout_payment_hash, false);
test_spendable_output(&nodes[0], &a_broadcast_txn[2]);
// Create a single channel with two pending HTLCs from nodes[0] to nodes[1], one which nodes[1]
// knows the preimage for, one which it does not.
- let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
+ let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 };
let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 10_000_000);
// panicked as described in the test introduction. This will remove the "maybe claimable"
// spendable output as nodes[1] has fully claimed the second HTLC.
connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1);
- expect_payment_failed!(nodes[0], payment_hash, true);
+ expect_payment_failed!(nodes[0], payment_hash, false);
assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations {
claimable_amount_satoshis: 1_000_000 - 10_000 - 20_000 - chan_feerate *
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known());
+ let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 };
// Send two HTLCs, one from A to B, and one from B to A.
// Once as_htlc_timeout_claim[0] reaches ANTI_REORG_DELAY confirmations, we should get a
// payment failure event.
connect_blocks(&nodes[0], ANTI_REORG_DELAY - 2);
- expect_payment_failed!(nodes[0], to_b_failed_payment_hash, true);
+ expect_payment_failed!(nodes[0], to_b_failed_payment_hash, false);
connect_blocks(&nodes[0], 1);
assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations {
sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()));
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 2);
- expect_payment_failed!(nodes[1], to_a_failed_payment_hash, true);
+ expect_payment_failed!(nodes[1], to_a_failed_payment_hash, false);
assert_eq!(vec![Balance::MaybePreimageClaimableHTLC {
claimable_amount_satoshis: 10_000,
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let (_, _, chan_id, funding_tx) =
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 100_000_000, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 100_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 };
assert_eq!(funding_outpoint.to_channel_id(), chan_id);
let mut payment_failed_events = nodes[1].node.get_and_clear_pending_events();
expect_payment_failed_conditions_event(&nodes[1], payment_failed_events.pop().unwrap(),
- dust_payment_hash, true, PaymentFailedConditions::new());
+ dust_payment_hash, false, PaymentFailedConditions::new());
expect_payment_failed_conditions_event(&nodes[1], payment_failed_events.pop().unwrap(),
- missing_htlc_payment_hash, true, PaymentFailedConditions::new());
+ missing_htlc_payment_hash, false, PaymentFailedConditions::new());
assert!(payment_failed_events.is_empty());
connect_blocks(&nodes[1], 1);
test_spendable_output(&nodes[1], &claim_txn[if confirm_htlc_spend_first { 2 } else { 3 }]);
connect_blocks(&nodes[1], 1);
test_spendable_output(&nodes[1], &claim_txn[if confirm_htlc_spend_first { 3 } else { 2 }]);
- expect_payment_failed!(nodes[1], live_payment_hash, true);
+ expect_payment_failed!(nodes[1], live_payment_hash, false);
connect_blocks(&nodes[1], 1);
test_spendable_output(&nodes[1], &claim_txn[0]);
connect_blocks(&nodes[1], 1);
test_spendable_output(&nodes[1], &claim_txn[1]);
- expect_payment_failed!(nodes[1], timeout_payment_hash, true);
+ expect_payment_failed!(nodes[1], timeout_payment_hash, false);
assert_eq!(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances(), Vec::new());
}
// Create some initial channels
let (_, _, chan_id, funding_tx) =
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 11_000_000, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 11_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 };
assert_eq!(funding_outpoint.to_channel_id(), chan_id);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let (_, _, chan_id, funding_tx) =
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 100_000_000, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 100_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 };
assert_eq!(funding_outpoint.to_channel_id(), chan_id);
assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); // We shouldn't fail the payment until we spend the output
connect_blocks(&nodes[1], 5);
- expect_payment_failed!(nodes[1], revoked_payment_hash, true);
+ expect_payment_failed!(nodes[1], revoked_payment_hash, false);
test_spendable_output(&nodes[1], &claim_txn_2[0]);
assert!(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances().is_empty());
}
/// is believed to be possible in the future (eg they're sending us messages we don't
/// understand or indicate they require unknown feature bits), no_connection_possible is set
/// and any outstanding channels should be failed.
+ ///
+ /// Note that in some rare cases this may be called without a corresponding
+ /// [`Self::peer_connected`].
fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool);
/// Handle a peer reconnecting, possibly generating channel_reestablish message(s).
- fn peer_connected(&self, their_node_id: &PublicKey, msg: &Init);
+ ///
+ /// May return an `Err(())` if the features the peer supports are not sufficient to communicate
+ /// with us. Implementors should be somewhat conservative about doing so, however, as other
+ /// message handlers may still wish to communicate with this peer.
+ fn peer_connected(&self, their_node_id: &PublicKey, msg: &Init) -> Result<(), ()>;
/// Handle an incoming channel_reestablish message from the given peer.
fn handle_channel_reestablish(&self, their_node_id: &PublicKey, msg: &ChannelReestablish);
// Error:
/// Handle an incoming error message from the given peer.
fn handle_error(&self, their_node_id: &PublicKey, msg: &ErrorMessage);
+
+ // Handler information:
+ /// Gets the node feature flags which this handler itself supports. All available handlers are
+ /// queried similarly and their feature flags are OR'd together to form the [`NodeFeatures`]
+ /// which are broadcasted in our [`NodeAnnouncement`] message.
+ fn provided_node_features(&self) -> NodeFeatures;
+
+ /// Gets the init feature flags which should be sent to the given peer. All available handlers
+ /// are queried similarly and their feature flags are OR'd together to form the [`InitFeatures`]
+ /// which are sent in our [`Init`] message.
+ ///
+ /// Note that this method is called before [`Self::peer_connected`].
+ fn provided_init_features(&self, their_node_id: &PublicKey) -> InitFeatures;
}
/// A trait to describe an object which can receive routing messages.
/// Called when a connection is established with a peer. This can be used to
/// perform routing table synchronization using a strategy defined by the
/// implementor.
- fn peer_connected(&self, their_node_id: &PublicKey, init: &Init);
+ ///
+ /// May return an `Err(())` if the features the peer supports are not sufficient to communicate
+ /// with us. Implementors should be somewhat conservative about doing so, however, as other
+ /// message handlers may still wish to communicate with this peer.
+ fn peer_connected(&self, their_node_id: &PublicKey, init: &Init) -> Result<(), ()>;
/// Handles the reply of a query we initiated to learn about channels
/// for a given range of blocks. We can expect to receive one or more
/// replies to a single query.
/// Handles when a peer asks us to send routing gossip messages for a
/// list of short_channel_ids.
fn handle_query_short_channel_ids(&self, their_node_id: &PublicKey, msg: QueryShortChannelIds) -> Result<(), LightningError>;
+
+ // Handler information:
+ /// Gets the node feature flags which this handler itself supports. All available handlers are
+ /// queried similarly and their feature flags are OR'd together to form the [`NodeFeatures`]
+ /// which are broadcasted in our [`NodeAnnouncement`] message.
+ fn provided_node_features(&self) -> NodeFeatures;
+ /// Gets the init feature flags which should be sent to the given peer. All available handlers
+ /// are queried similarly and their feature flags are OR'd together to form the [`InitFeatures`]
+ /// which are sent in our [`Init`] message.
+ ///
+ /// Note that this method is called before [`Self::peer_connected`].
+ fn provided_init_features(&self, their_node_id: &PublicKey) -> InitFeatures;
}
/// A trait to describe an object that can receive onion messages.
fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage);
/// Called when a connection is established with a peer. Can be used to track which peers
/// advertise onion message support and are online.
- fn peer_connected(&self, their_node_id: &PublicKey, init: &Init);
+ ///
+ /// May return an `Err(())` if the features the peer supports are not sufficient to communicate
+ /// with us. Implementors should be somewhat conservative about doing so, however, as other
+ /// message handlers may still wish to communicate with this peer.
+ fn peer_connected(&self, their_node_id: &PublicKey, init: &Init) -> Result<(), ()>;
/// Indicates a connection to the peer failed/an existing connection was lost. Allows handlers to
/// drop and refuse to forward onion messages to this peer.
+ ///
+ /// Note that in some rare cases this may be called without a corresponding
+ /// [`Self::peer_connected`].
fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool);
+
+ // Handler information:
+ /// Gets the node feature flags which this handler itself supports. All available handlers are
+ /// queried similarly and their feature flags are OR'd together to form the [`NodeFeatures`]
+ /// which are broadcasted in our [`NodeAnnouncement`] message.
+ fn provided_node_features(&self) -> NodeFeatures;
+
+ /// Gets the init feature flags which should be sent to the given peer. All available handlers
+ /// are queried similarly and their feature flags are OR'd together to form the [`InitFeatures`]
+ /// which are sent in our [`Init`] message.
+ ///
+ /// Note that this method is called before [`Self::peer_connected`].
+ fn provided_init_features(&self, their_node_id: &PublicKey) -> InitFeatures;
}
mod fuzzy_internal_msgs {
let sig_2 = get_sig_on!(privkey_2, secp_ctx, String::from("01010101010101010101010101010101"));
let sig_3 = get_sig_on!(privkey_3, secp_ctx, String::from("01010101010101010101010101010101"));
let sig_4 = get_sig_on!(privkey_4, secp_ctx, String::from("01010101010101010101010101010101"));
- let mut features = ChannelFeatures::known();
+ let mut features = ChannelFeatures::empty();
if unknown_features_bits {
features = ChannelFeatures::from_le_bytes(vec![0xFF, 0xFF]);
}
use chain::keysinterface::{KeysInterface, Recipient};
use ln::{PaymentHash, PaymentSecret};
use ln::channel::EXPIRE_PREV_CONFIG_TICKS;
-use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, HTLCForwardInfo, CLTV_FAR_FAR_AWAY, MIN_CLTV_EXPIRY_DELTA, PendingHTLCInfo, PendingHTLCRouting};
+use ln::channelmanager::{self, ChannelManager, ChannelManagerReadArgs, HTLCForwardInfo, CLTV_FAR_FAR_AWAY, MIN_CLTV_EXPIRY_DELTA, PendingHTLCInfo, PendingHTLCRouting};
use ln::onion_utils;
use routing::gossip::{NetworkUpdate, RoutingFees, NodeId};
use routing::router::{get_route, PaymentParameters, Route, RouteHint, RouteHintHop};
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
- if let &Event::PaymentPathFailed { ref rejected_by_dest, ref network_update, ref all_paths_failed, ref short_channel_id, ref error_code, .. } = &events[0] {
- assert_eq!(*rejected_by_dest, !expected_retryable);
+ if let &Event::PaymentPathFailed { ref payment_failed_permanently, ref network_update, ref all_paths_failed, ref short_channel_id, ref error_code, .. } = &events[0] {
+ assert_eq!(*payment_failed_permanently, !expected_retryable);
assert_eq!(*all_paths_failed, true);
assert_eq!(*error_code, expected_error_code);
if expected_channel_update.is_some() {
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config), Some(config), Some(config)]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let channels = [create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()), create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known())];
+ let channels = [create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()), create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features())];
// positive case
let (route, payment_hash_success, payment_preimage_success, payment_secret_success) = get_route_and_payment_hash!(nodes[0], nodes[2], 40_000);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config), Some(config), Some(node_2_cfg)]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let channels = [create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()), create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known())];
+ let channels = [create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()), create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features())];
for node in nodes.iter() {
*node.keys_manager.override_random_bytes.lock().unwrap() = Some([3; 32]);
}
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
let other_channel = create_chan_between_nodes(
- &nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known(),
+ &nodes[0], &nodes[1], channelmanager::provided_init_features(), channelmanager::provided_init_features(),
);
let channel_to_update = if announced_channel {
let channel = create_announced_chan_between_nodes(
- &nodes, 1, 2, InitFeatures::known(), InitFeatures::known(),
+ &nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features(),
);
(channel.2, channel.0.contents.short_channel_id)
} else {
let channel = create_unannounced_chan_between_nodes_with_value(
- &nodes, 1, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known(),
+ &nodes, 1, 2, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features(),
);
(channel.0.channel_id, channel.0.short_channel_id_alias.unwrap())
};
htlc_minimum_msat: None,
}])];
let payment_params = PaymentParameters::from_node_id(*channel_to_update_counterparty)
- .with_features(InvoiceFeatures::known())
+ .with_features(channelmanager::provided_invoice_features())
.with_route_hints(hop_hints);
get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, PAYMENT_AMT, TEST_FINAL_CLTV)
};
let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &[None, None, None, None, Some(priv_channels_conf)]);
let mut nodes = create_network(5, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
- create_unannounced_chan_between_nodes_with_value(&nodes, 3, 4, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 2, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_unannounced_chan_between_nodes_with_value(&nodes, 3, 4, 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id());
let origin_node = &nodes[0];
// supports variable length onions, as the `InitFeatures` exchanged in the init message
// between the nodes will be used when creating the route. We therefore do not default to
// supporting variable length onions for that hop, as the `InitFeatures` in this case are
- // `InitFeatures::known()`.
+ // `channelmanager::provided_init_features()`.
let unannounced_chan = &nodes[4].node.list_usable_channels()[0];
let chanmon_cfgs = create_chanmon_cfgs(4);
let mut node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
- // Set `node[1]` config to `InitFeatures::empty()` which return `false` for
- // `supports_variable_length_onion()`
+ // Set `node[1]` config to `InitFeatures::empty()` + `static_remote_key` which implies
+ // `!supports_variable_length_onion()` but still supports the required static-remote-key
+ // feature.
let mut node_1_cfg = &mut node_cfgs[1];
node_1_cfg.features = InitFeatures::empty();
+ node_1_cfg.features.set_static_remote_key_required();
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 2, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id())
.with_features(InvoiceFeatures::empty());
let phantom_pubkey = PublicKey::from_secret_key(&secp_ctx, &phantom_secret);
let phantom_route_hint = $nodes[1].node.get_phantom_route_hints();
let payment_params = PaymentParameters::from_node_id(phantom_pubkey)
- .with_features(InvoiceFeatures::known())
+ .with_features(channelmanager::provided_invoice_features())
.with_route_hints(vec![RouteHint(vec![
RouteHintHop {
src_node_id: $nodes[0].node.get_our_node_id(),
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let channel = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let channel = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Get the route.
let recv_value_msat = 10_000;
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let channel = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let channel = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Get the route.
let recv_value_msat = 10_000;
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let channel = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let channel = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Get the route.
let recv_value_msat = 10_000;
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let channel = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let channel = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Get the route.
let recv_value_msat = 10_000;
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let channel = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let channel = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Get the route with a too-low amount.
let recv_amt_msat = 10_000;
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(receiver_config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let channel = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let channel = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Get the route with an amount exceeding the dust exposure threshold of nodes[1].
let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1], Some(max_dust_exposure + 1));
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let channel = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let channel = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Get the route with a too-low amount.
let recv_amt_msat = 10_000;
if fixed_time_eq(&Hmac::from_engine(hmac).into_inner(), &err_packet.hmac) {
if let Some(error_code_slice) = err_packet.failuremsg.get(0..2) {
+ const BADONION: u16 = 0x8000;
const PERM: u16 = 0x4000;
const NODE: u16 = 0x2000;
const UPDATE: u16 = 0x1000;
let mut network_update = None;
let mut short_channel_id = None;
- if error_code & NODE == NODE {
+ if error_code & BADONION == BADONION {
+ // If the error code has the BADONION bit set, always blame the channel
+ // from the node "originating" the error to its next hop. The
+ // "originator" is ultimately actually claiming that its counterparty
+ // is the one who is failing the HTLC.
+ // If the "originator" here isn't lying we should really mark the
+ // next-hop node as failed entirely, but we can't be confident in that,
+ // as it would allow any node to get us to completely ban one of its
+ // counterparties. Instead, we simply remove the channel in question.
+ network_update = Some(NetworkUpdate::ChannelFailure {
+ short_channel_id: failing_route_hop.short_channel_id,
+ is_permanent: true,
+ });
+ } else if error_code & NODE == NODE {
let is_permanent = error_code & PERM == PERM;
network_update = Some(NetworkUpdate::NodeFailure { node_id: route_hop.pubkey, is_permanent });
short_channel_id = Some(route_hop.short_channel_id);
- }
- else if error_code & PERM == PERM {
+ } else if error_code & PERM == PERM {
if !payment_failed {
network_update = Some(NetworkUpdate::ChannelFailure {
short_channel_id: failing_route_hop.short_channel_id,
});
short_channel_id = Some(failing_route_hop.short_channel_id);
}
- }
- else if error_code & UPDATE == UPDATE {
+ } else if error_code & UPDATE == UPDATE {
if let Some(update_len_slice) = err_packet.failuremsg.get(debug_field_size+2..debug_field_size+4) {
let update_len = u16::from_be_bytes(update_len_slice.try_into().expect("len is 2")) as usize;
if let Some(mut update_slice) = err_packet.failuremsg.get(debug_field_size + 4..debug_field_size + 4 + update_len) {
short_channel_id = Some(route_hop.short_channel_id);
}
- // TODO: Here (and a few other places) we assume that BADONION errors
- // are always "sourced" from the node previous to the one which failed
- // to decode the onion.
res = Some((network_update, short_channel_id, !(error_code & PERM == PERM && is_from_final_node)));
let (description, title) = errors::get_onion_error_description(error_code);
use chain::transaction::OutPoint;
use chain::keysinterface::KeysInterface;
use ln::channel::EXPIRE_PREV_CONFIG_TICKS;
-use ln::channelmanager::{BREAKDOWN_TIMEOUT, ChannelManager, ChannelManagerReadArgs, MPP_TIMEOUT_TICKS, PaymentId, PaymentSendFailure};
-use ln::features::{InitFeatures, InvoiceFeatures};
+use ln::channelmanager::{self, BREAKDOWN_TIMEOUT, ChannelManager, ChannelManagerReadArgs, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, PaymentSendFailure};
use ln::msgs;
use ln::msgs::ChannelMessageHandler;
use routing::router::{PaymentParameters, get_route};
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let _chan_0 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_1 = create_announced_chan_between_nodes(&nodes, 2, 1, InitFeatures::known(), InitFeatures::known());
+ let _chan_0 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 2, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Rebalance to find a route
send_payment(&nodes[2], &vec!(&nodes[1])[..], 3_000_000);
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
- let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
- let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
- let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+ let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
+ let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
+ let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
+ let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
let (mut route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[3], 100000);
let path = route.paths[0].clone();
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- let (chan_1_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let (chan_2_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::known(), InitFeatures::known());
- let (chan_3_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::known(), InitFeatures::known());
- let (chan_4_update, _, chan_4_id, _) = create_announced_chan_between_nodes(&nodes, 3, 2, InitFeatures::known(), InitFeatures::known());
+ let (chan_1_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let (chan_2_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 0, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let (chan_3_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 1, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let (chan_4_update, _, chan_4_id, _) = create_announced_chan_between_nodes(&nodes, 3, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Rebalance
send_payment(&nodes[3], &vec!(&nodes[2])[..], 1_500_000);
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
- let (chan_1_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let (chan_2_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::known(), InitFeatures::known());
- let (chan_3_update, _, chan_3_id, _) = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::known(), InitFeatures::known());
- let (chan_4_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
+ let (chan_1_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let (chan_2_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 0, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let (chan_3_update, _, chan_3_id, _) = create_announced_chan_between_nodes(&nodes, 1, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let (chan_4_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 2, 3, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[3], 100_000);
let path = route.paths[0].clone();
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let _chan_0 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_1 = create_announced_chan_between_nodes(&nodes, 2, 1, InitFeatures::known(), InitFeatures::known());
+ let _chan_0 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 2, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Rebalance to find a route
send_payment(&nodes[2], &vec!(&nodes[1])[..], 3_000_000);
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());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000);
let nodes_0_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
- let (_, _, chan_id_2, _) = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
+ let (_, _, chan_id_2, _) = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Serialize the ChannelManager prior to sending payments
let nodes_0_serialized = nodes[0].node.encode();
assert_eq!(as_broadcasted_txn[0], as_commitment_tx);
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(), remote_network_address: None });
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
// Now nodes[1] should send a channel reestablish, which nodes[0] will respond to with an
// error, as the channel has hit the chain.
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known(), remote_network_address: None });
- let bs_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
let as_err = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(as_err.len(), 1);
// Create a new channel on which to retry the payment before we fail the payment via the
// HTLC-Timeout transaction. This avoids ChannelManager timing out the payment due to us
// connecting several blocks while creating the channel (implying time has passed).
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
mine_transaction(&nodes[1], &as_commitment_tx);
expect_payment_sent!(nodes[0], payment_preimage_1);
connect_blocks(&nodes[0], TEST_FINAL_CLTV*4 + 20);
let as_htlc_timeout_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
- assert_eq!(as_htlc_timeout_txn.len(), 3);
- let (first_htlc_timeout_tx, second_htlc_timeout_tx) = if as_htlc_timeout_txn[0] == as_commitment_tx {
- (&as_htlc_timeout_txn[1], &as_htlc_timeout_txn[2])
- } else {
- assert_eq!(as_htlc_timeout_txn[2], as_commitment_tx);
- (&as_htlc_timeout_txn[0], &as_htlc_timeout_txn[1])
- };
+ assert_eq!(as_htlc_timeout_txn.len(), 2);
+ let (first_htlc_timeout_tx, second_htlc_timeout_tx) = (&as_htlc_timeout_txn[0], &as_htlc_timeout_txn[1]);
check_spends!(first_htlc_timeout_tx, as_commitment_tx);
check_spends!(second_htlc_timeout_tx, as_commitment_tx);
if first_htlc_timeout_tx.input[0].previous_output == bs_htlc_claim_txn[0].input[0].previous_output {
do_retry_with_no_persist(false);
}
+fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) {
+ // Test that an off-chain completed payment is not retryable on restart. This was previously
+ // broken for dust payments, but we test for both dust and non-dust payments.
+ //
+ // `use_dust` switches to using a dust HTLC, which results in the HTLC not having an on-chain
+ // output at all.
+ let chanmon_cfgs = create_chanmon_cfgs(3);
+ let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+
+ let mut manually_accept_config = test_default_channel_config();
+ manually_accept_config.manually_accept_inbound_channels = true;
+
+ let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(manually_accept_config), None]);
+
+ let first_persister: test_utils::TestPersister;
+ let first_new_chain_monitor: test_utils::TestChainMonitor;
+ let first_nodes_0_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
+ let second_persister: test_utils::TestPersister;
+ let second_new_chain_monitor: test_utils::TestChainMonitor;
+ let second_nodes_0_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
+ let third_persister: test_utils::TestPersister;
+ let third_new_chain_monitor: test_utils::TestChainMonitor;
+ let third_nodes_0_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
+
+ let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+
+ // Because we set nodes[1] to manually accept channels, just open a 0-conf channel.
+ let (funding_tx, chan_id) = open_zero_conf_channel(&nodes[0], &nodes[1], None);
+ confirm_transaction(&nodes[0], &funding_tx);
+ confirm_transaction(&nodes[1], &funding_tx);
+ // Ignore the announcement_signatures messages
+ nodes[0].node.get_and_clear_pending_msg_events();
+ nodes[1].node.get_and_clear_pending_msg_events();
+ let chan_id_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
+
+ // Serialize the ChannelManager prior to sending payments
+ let mut nodes_0_serialized = nodes[0].node.encode();
+
+ let route = get_route_and_payment_hash!(nodes[0], nodes[2], if use_dust { 1_000 } else { 1_000_000 }).0;
+ let (payment_preimage, payment_hash, payment_secret, payment_id) = send_along_route(&nodes[0], route, &[&nodes[1], &nodes[2]], if use_dust { 1_000 } else { 1_000_000 });
+
+ // The ChannelMonitor should always be the latest version, as we're required to persist it
+ // during the `commitment_signed_dance!()`.
+ let mut chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new());
+ get_monitor!(nodes[0], chan_id).write(&mut chan_0_monitor_serialized).unwrap();
+
+ let mut chan_1_monitor_serialized = test_utils::TestVecWriter(Vec::new());
+
+ macro_rules! reload_node {
+ ($chain_monitor: ident, $chan_manager: ident, $persister: ident) => { {
+ $persister = test_utils::TestPersister::new();
+ let keys_manager = &chanmon_cfgs[0].keys_manager;
+ $chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), nodes[0].logger, node_cfgs[0].fee_estimator, &$persister, keys_manager);
+ nodes[0].chain_monitor = &$chain_monitor;
+ let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..];
+ let (_, mut chan_0_monitor) = <(BlockHash, ChannelMonitor<EnforcingSigner>)>::read(
+ &mut chan_0_monitor_read, keys_manager).unwrap();
+ assert!(chan_0_monitor_read.is_empty());
+
+ let mut chan_1_monitor = None;
+ let mut channel_monitors = HashMap::new();
+ channel_monitors.insert(chan_0_monitor.get_funding_txo().0, &mut chan_0_monitor);
+
+ if !chan_1_monitor_serialized.0.is_empty() {
+ let mut chan_1_monitor_read = &chan_1_monitor_serialized.0[..];
+ chan_1_monitor = Some(<(BlockHash, ChannelMonitor<EnforcingSigner>)>::read(
+ &mut chan_1_monitor_read, keys_manager).unwrap().1);
+ assert!(chan_1_monitor_read.is_empty());
+ channel_monitors.insert(chan_1_monitor.as_ref().unwrap().get_funding_txo().0, chan_1_monitor.as_mut().unwrap());
+ }
+
+ let mut nodes_0_read = &nodes_0_serialized[..];
+ let (_, nodes_0_deserialized_tmp) = {
+ <(BlockHash, ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
+ default_config: test_default_channel_config(),
+ keys_manager,
+ fee_estimator: node_cfgs[0].fee_estimator,
+ chain_monitor: nodes[0].chain_monitor,
+ tx_broadcaster: nodes[0].tx_broadcaster.clone(),
+ logger: nodes[0].logger,
+ channel_monitors,
+ }).unwrap()
+ };
+ $chan_manager = nodes_0_deserialized_tmp;
+ assert!(nodes_0_read.is_empty());
+
+ assert!(nodes[0].chain_monitor.watch_channel(chan_0_monitor.get_funding_txo().0, chan_0_monitor).is_ok());
+ if !chan_1_monitor_serialized.0.is_empty() {
+ let funding_txo = chan_1_monitor.as_ref().unwrap().get_funding_txo().0;
+ assert!(nodes[0].chain_monitor.watch_channel(funding_txo, chan_1_monitor.unwrap()).is_ok());
+ }
+ nodes[0].node = &$chan_manager;
+ check_added_monitors!(nodes[0], if !chan_1_monitor_serialized.0.is_empty() { 2 } else { 1 });
+
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ } }
+ }
+
+ reload_node!(first_new_chain_monitor, first_nodes_0_deserialized, first_persister);
+
+ // On reload, the ChannelManager should realize it is stale compared to the ChannelMonitor and
+ // force-close the channel.
+ check_closed_event!(nodes[0], 1, ClosureReason::OutdatedChannelManager);
+ assert!(nodes[0].node.list_channels().is_empty());
+ assert!(nodes[0].node.has_pending_payments());
+ assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0).len(), 1);
+
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+
+ // Now nodes[1] should send a channel reestablish, which nodes[0] will respond to with an
+ // error, as the channel has hit the chain.
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
+ nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
+ let as_err = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(as_err.len(), 1);
+ let bs_commitment_tx;
+ match as_err[0] {
+ MessageSendEvent::HandleError { node_id, action: msgs::ErrorAction::SendErrorMessage { ref msg } } => {
+ assert_eq!(node_id, nodes[1].node.get_our_node_id());
+ nodes[1].node.handle_error(&nodes[0].node.get_our_node_id(), msg);
+ check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyForceClosed { peer_msg: "Failed to find corresponding channel".to_string() });
+ check_added_monitors!(nodes[1], 1);
+ bs_commitment_tx = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
+ },
+ _ => panic!("Unexpected event"),
+ }
+ check_closed_broadcast!(nodes[1], false);
+
+ // Now fail back the payment from nodes[2] to nodes[1]. This doesn't really matter as the
+ // previous hop channel is already on-chain, but it makes nodes[2] willing to see additional
+ // incoming HTLCs with the same payment hash later.
+ nodes[2].node.fail_htlc_backwards(&payment_hash);
+ expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], [HTLCDestination::FailedPayment { payment_hash }]);
+ check_added_monitors!(nodes[2], 1);
+
+ let htlc_fulfill_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
+ nodes[1].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &htlc_fulfill_updates.update_fail_htlcs[0]);
+ commitment_signed_dance!(nodes[1], nodes[2], htlc_fulfill_updates.commitment_signed, false);
+ expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1],
+ [HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_id_2 }]);
+
+ // Connect the HTLC-Timeout transaction, timing out the HTLC on both nodes (but not confirming
+ // the HTLC-Timeout transaction beyond 1 conf). For dust HTLCs, the HTLC is considered resolved
+ // after the commitment transaction, so always connect the commitment transaction.
+ mine_transaction(&nodes[0], &bs_commitment_tx[0]);
+ mine_transaction(&nodes[1], &bs_commitment_tx[0]);
+ if !use_dust {
+ connect_blocks(&nodes[0], TEST_FINAL_CLTV - 1 + (MIN_CLTV_EXPIRY_DELTA as u32));
+ connect_blocks(&nodes[1], TEST_FINAL_CLTV - 1 + (MIN_CLTV_EXPIRY_DELTA as u32));
+ let as_htlc_timeout = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
+ check_spends!(as_htlc_timeout[0], bs_commitment_tx[0]);
+ assert_eq!(as_htlc_timeout.len(), 1);
+
+ mine_transaction(&nodes[0], &as_htlc_timeout[0]);
+ // nodes[0] may rebroadcast (or RBF-bump) its HTLC-Timeout, so wipe the announced set.
+ nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clear();
+ mine_transaction(&nodes[1], &as_htlc_timeout[0]);
+ }
+
+ // Create a new channel on which to retry the payment before we fail the payment via the
+ // HTLC-Timeout transaction. This avoids ChannelManager timing out the payment due to us
+ // connecting several blocks while creating the channel (implying time has passed).
+ // We do this with a zero-conf channel to avoid connecting blocks as a side-effect.
+ let (_, chan_id_3) = open_zero_conf_channel(&nodes[0], &nodes[1], None);
+ assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
+
+ // If we attempt to retry prior to the HTLC-Timeout (or commitment transaction, for dust HTLCs)
+ // confirming, we will fail as it's considered still-pending...
+ let (new_route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[2], if use_dust { 1_000 } else { 1_000_000 });
+ assert!(nodes[0].node.retry_payment(&new_route, payment_id).is_err());
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+
+ // After ANTI_REORG_DELAY confirmations, the HTLC should be failed and we can try the payment
+ // again. We serialize the node first as we'll then test retrying the HTLC after a restart
+ // (which should also still work).
+ connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1);
+ connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
+ // We set mpp_parts_remain to avoid having abandon_payment called
+ expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain());
+
+ chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new());
+ get_monitor!(nodes[0], chan_id).write(&mut chan_0_monitor_serialized).unwrap();
+ chan_1_monitor_serialized = test_utils::TestVecWriter(Vec::new());
+ get_monitor!(nodes[0], chan_id_3).write(&mut chan_1_monitor_serialized).unwrap();
+ nodes_0_serialized = nodes[0].node.encode();
+
+ assert!(nodes[0].node.retry_payment(&new_route, payment_id).is_ok());
+ assert!(!nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+
+ reload_node!(second_new_chain_monitor, second_nodes_0_deserialized, second_persister);
+ reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+
+ // Now resend the payment, delivering the HTLC and actually claiming it this time. This ensures
+ // the payment is not (spuriously) listed as still pending.
+ assert!(nodes[0].node.retry_payment(&new_route, payment_id).is_ok());
+ check_added_monitors!(nodes[0], 1);
+ pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], if use_dust { 1_000 } else { 1_000_000 }, payment_hash, payment_secret);
+ claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
+
+ assert!(nodes[0].node.retry_payment(&new_route, payment_id).is_err());
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+
+ chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new());
+ get_monitor!(nodes[0], chan_id).write(&mut chan_0_monitor_serialized).unwrap();
+ chan_1_monitor_serialized = test_utils::TestVecWriter(Vec::new());
+ get_monitor!(nodes[0], chan_id_3).write(&mut chan_1_monitor_serialized).unwrap();
+ nodes_0_serialized = nodes[0].node.encode();
+
+ // Ensure that after reload we cannot retry the payment.
+ reload_node!(third_new_chain_monitor, third_nodes_0_deserialized, third_persister);
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+
+ assert!(nodes[0].node.retry_payment(&new_route, payment_id).is_err());
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+}
+
+#[test]
+fn test_completed_payment_not_retryable_on_reload() {
+ do_test_completed_payment_not_retryable_on_reload(true);
+ do_test_completed_payment_not_retryable_on_reload(false);
+}
+
+
fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, confirm_commitment_tx: bool, payment_timeout: bool) {
// When a Channel is closed, any outbound HTLCs which were relayed through it are simply
// dropped when the Channel is. From there, the ChannelManager relies on the ChannelMonitor
let nodes_0_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Route a payment, but force-close the channel before the HTLC fulfill message arrives at
// nodes[0].
nodes[0].chain_monitor.chain_monitor.channel_monitor_updated(funding_txo, update).unwrap();
}
if payment_timeout {
- expect_payment_failed!(nodes[0], payment_hash, true);
+ expect_payment_failed!(nodes[0], payment_hash, false);
} else {
expect_payment_sent!(nodes[0], payment_preimage);
}
if persist_manager_post_event {
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
} else if payment_timeout {
- expect_payment_failed!(nodes[0], payment_hash, true);
+ expect_payment_failed!(nodes[0], payment_hash, false);
} else {
expect_payment_sent!(nodes[0], payment_preimage);
}
let nodes_1_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 100_000);
// The simplest way to get a failure after a fulfill is to reload nodes[1] from a state
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());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let amt_msat = 60_000;
let expiry_secs = 60 * 60;
let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(amt_msat), expiry_secs).unwrap();
let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
- .with_features(InvoiceFeatures::known());
+ .with_features(channelmanager::provided_invoice_features());
let scorer = test_utils::TestScorer::with_penalty(0);
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// First check we refuse to build a single-hop probe
let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[1], 100_000);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], 100_000);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 90000000, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 90000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id());
_ => panic!(),
};
}
+
+#[test]
+fn onchain_failed_probe_yields_event() {
+ // Tests that an attempt to probe over a channel that is eventaully closed results in a failure
+ // event.
+ let chanmon_cfgs = create_chanmon_cfgs(3);
+ let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
+ let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+
+ let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
+ create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+
+ let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id());
+
+ // Send a dust HTLC, which will be treated as if it timed out once the channel hits the chain.
+ let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], &payment_params, 1_000, 42);
+ let (payment_hash, payment_id) = nodes[0].node.send_probe(route.paths[0].clone()).unwrap();
+
+ // node[0] -- update_add_htlcs -> node[1]
+ check_added_monitors!(nodes[0], 1);
+ let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+ let probe_event = SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), updates);
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &probe_event.msgs[0]);
+ check_added_monitors!(nodes[1], 0);
+ commitment_signed_dance!(nodes[1], nodes[0], probe_event.commitment_msg, false);
+ expect_pending_htlcs_forwardable!(nodes[1]);
+
+ check_added_monitors!(nodes[1], 1);
+ let _ = get_htlc_update_msgs!(nodes[1], nodes[2].node.get_our_node_id());
+
+ // Don't bother forwarding the HTLC onwards and just confirm the force-close transaction on
+ // Node A, which after 6 confirmations should result in a probe failure event.
+ let bs_txn = get_local_commitment_txn!(nodes[1], chan_id);
+ confirm_transaction(&nodes[0], &bs_txn[0]);
+ check_closed_broadcast!(&nodes[0], true);
+ check_added_monitors!(nodes[0], 1);
+
+ let mut events = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 2);
+ let mut found_probe_failed = false;
+ for event in events.drain(..) {
+ match event {
+ Event::ProbeFailed { payment_id: ev_pid, payment_hash: ev_ph, .. } => {
+ assert_eq!(payment_id, ev_pid);
+ assert_eq!(payment_hash, ev_ph);
+ found_probe_failed = true;
+ },
+ Event::ChannelClosed { .. } => {},
+ _ => panic!(),
+ }
+ }
+ assert!(found_probe_failed);
+}
use ln::msgs::LightningError;
use ln::msgs;
+use ln::wire;
use bitcoin::hashes::{Hash, HashEngine};
use bitcoin::hashes::sha256::Hash as Sha256;
use util::chacha20poly1305rfc::ChaCha20Poly1305RFC;
use util::crypto::hkdf_extract_expand_twice;
+use util::ser::VecWriter;
use bitcoin::hashes::hex::ToHex;
/// Maximum Lightning message data length according to
res[plaintext.len()..].copy_from_slice(&tag);
}
+ #[inline]
+ /// Encrypts the message in res[offset..] in-place and pushes a 16-byte tag onto the end of
+ /// res.
+ fn encrypt_in_place_with_ad(res: &mut Vec<u8>, offset: usize, n: u64, key: &[u8; 32], h: &[u8]) {
+ let mut nonce = [0; 12];
+ nonce[4..].copy_from_slice(&n.to_le_bytes()[..]);
+
+ let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h);
+ let mut tag = [0; 16];
+ chacha.encrypt_full_message_in_place(&mut res[offset..], &mut tag);
+ res.extend_from_slice(&tag);
+ }
+
#[inline]
fn decrypt_with_ad(res: &mut[u8], n: u64, key: &[u8; 32], h: &[u8], cyphertext: &[u8]) -> Result<(), LightningError> {
let mut nonce = [0; 12];
Ok(self.their_node_id.unwrap().clone())
}
- /// Encrypts the given message, returning the encrypted version
+ /// Encrypts the given pre-serialized message, returning the encrypted version.
/// panics if msg.len() > 65535 or Noise handshake has not finished.
- pub fn encrypt_message(&mut self, msg: &[u8]) -> Vec<u8> {
+ pub fn encrypt_buffer(&mut self, msg: &[u8]) -> Vec<u8> {
if msg.len() > LN_MAX_MSG_LEN {
panic!("Attempted to encrypt message longer than 65535 bytes!");
}
res
}
+ /// Encrypts the given message, returning the encrypted version.
+ /// panics if the length of `message`, once encoded, is greater than 65535 or if the Noise
+ /// handshake has not finished.
+ pub fn encrypt_message<M: wire::Type>(&mut self, message: &M) -> Vec<u8> {
+ // Allocate a buffer with 2KB, fitting most common messages. Reserve the first 16+2 bytes
+ // for the 2-byte message type prefix and its MAC.
+ let mut res = VecWriter(Vec::with_capacity(2048));
+ res.0.resize(16 + 2, 0);
+ wire::write(message, &mut res).expect("In-memory messages must never fail to serialize");
+
+ let msg_len = res.0.len() - 16 - 2;
+ if msg_len > LN_MAX_MSG_LEN {
+ panic!("Attempted to encrypt message longer than 65535 bytes!");
+ }
+
+ match self.noise_state {
+ NoiseState::Finished { ref mut sk, ref mut sn, ref mut sck, rk: _, rn: _, rck: _ } => {
+ if *sn >= 1000 {
+ let (new_sck, new_sk) = hkdf_extract_expand_twice(sck, sk);
+ *sck = new_sck;
+ *sk = new_sk;
+ *sn = 0;
+ }
+
+ Self::encrypt_with_ad(&mut res.0[0..16+2], *sn, sk, &[0; 0], &(msg_len as u16).to_be_bytes());
+ *sn += 1;
+
+ Self::encrypt_in_place_with_ad(&mut res.0, 16+2, *sn, sk, &[0; 0]);
+ *sn += 1;
+ },
+ _ => panic!("Tried to encrypt a message prior to noise handshake completion"),
+ }
+
+ res.0
+ }
+
/// Decrypts a message length header from the remote peer.
/// panics if noise handshake has not yet finished or msg.len() != 18
pub fn decrypt_length_header(&mut self, msg: &[u8]) -> Result<u16, LightningError> {
for i in 0..1005 {
let msg = [0x68, 0x65, 0x6c, 0x6c, 0x6f];
- let res = outbound_peer.encrypt_message(&msg);
+ let res = outbound_peer.encrypt_buffer(&msg);
assert_eq!(res.len(), 5 + 2*16 + 2);
let len_header = res[0..2+16].to_vec();
fn max_message_len_encryption() {
let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors();
let msg = [4u8; LN_MAX_MSG_LEN + 1];
- outbound_peer.encrypt_message(&msg);
+ outbound_peer.encrypt_buffer(&msg);
}
#[test]
use bitcoin::secp256k1::{self, Secp256k1, SecretKey, PublicKey};
-use ln::features::InitFeatures;
+use ln::features::{InitFeatures, NodeFeatures};
use ln::msgs;
use ln::msgs::{ChannelMessageHandler, LightningError, NetAddress, OnionMessageHandler, RoutingMessageHandler};
use ln::channelmanager::{SimpleArcChannelManager, SimpleRefChannelManager};
use ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep};
use ln::wire;
use ln::wire::Encode;
+use onion_message::{SimpleArcOnionMessenger, SimpleRefOnionMessenger};
use routing::gossip::{NetworkGraph, P2PGossipSync};
use util::atomic_counter::AtomicCounter;
+use util::crypto::sign;
use util::events::{MessageSendEvent, MessageSendEventsProvider, OnionMessageProvider};
use util::logger::Logger;
use io;
use alloc::collections::LinkedList;
use sync::{Arc, Mutex, MutexGuard, FairRwLock};
-use core::sync::atomic::{AtomicBool, Ordering};
+use core::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use core::{cmp, hash, fmt, mem};
use core::ops::Deref;
use core::convert::Infallible;
#[cfg(feature = "std")] use std::error;
use bitcoin::hashes::sha256::Hash as Sha256;
+use bitcoin::hashes::sha256d::Hash as Sha256dHash;
use bitcoin::hashes::sha256::HashEngine as Sha256Engine;
use bitcoin::hashes::{HashEngine, Hash};
fn get_next_channel_announcement(&self, _starting_point: u64) ->
Option<(msgs::ChannelAnnouncement, Option<msgs::ChannelUpdate>, Option<msgs::ChannelUpdate>)> { None }
fn get_next_node_announcement(&self, _starting_point: Option<&PublicKey>) -> Option<msgs::NodeAnnouncement> { None }
- fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init) {}
+ fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init) -> Result<(), ()> { Ok(()) }
fn handle_reply_channel_range(&self, _their_node_id: &PublicKey, _msg: msgs::ReplyChannelRange) -> Result<(), LightningError> { Ok(()) }
fn handle_reply_short_channel_ids_end(&self, _their_node_id: &PublicKey, _msg: msgs::ReplyShortChannelIdsEnd) -> Result<(), LightningError> { Ok(()) }
fn handle_query_channel_range(&self, _their_node_id: &PublicKey, _msg: msgs::QueryChannelRange) -> Result<(), LightningError> { Ok(()) }
fn handle_query_short_channel_ids(&self, _their_node_id: &PublicKey, _msg: msgs::QueryShortChannelIds) -> Result<(), LightningError> { Ok(()) }
+ fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() }
+ fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures {
+ InitFeatures::empty()
+ }
}
impl OnionMessageProvider for IgnoringMessageHandler {
fn next_onion_message_for_peer(&self, _peer_node_id: PublicKey) -> Option<msgs::OnionMessage> { None }
}
impl OnionMessageHandler for IgnoringMessageHandler {
fn handle_onion_message(&self, _their_node_id: &PublicKey, _msg: &msgs::OnionMessage) {}
- fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init) {}
+ fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init) -> Result<(), ()> { Ok(()) }
fn peer_disconnected(&self, _their_node_id: &PublicKey, _no_connection_possible: bool) {}
+ fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() }
+ fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures {
+ InitFeatures::empty()
+ }
}
impl Deref for IgnoringMessageHandler {
type Target = IgnoringMessageHandler;
// msgs::ChannelUpdate does not contain the channel_id field, so we just drop them.
fn handle_channel_update(&self, _their_node_id: &PublicKey, _msg: &msgs::ChannelUpdate) {}
fn peer_disconnected(&self, _their_node_id: &PublicKey, _no_connection_possible: bool) {}
- fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &msgs::Init) {}
+ fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init) -> Result<(), ()> { Ok(()) }
fn handle_error(&self, _their_node_id: &PublicKey, _msg: &msgs::ErrorMessage) {}
+ fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() }
+ fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures {
+ // Set a number of features which various nodes may require to talk to us. It's totally
+ // reasonable to indicate we "support" all kinds of channel features...we just reject all
+ // channels.
+ let mut features = InitFeatures::empty();
+ features.set_data_loss_protect_optional();
+ features.set_upfront_shutdown_script_optional();
+ features.set_variable_length_onion_optional();
+ features.set_static_remote_key_optional();
+ features.set_payment_secret_optional();
+ features.set_basic_mpp_optional();
+ features.set_wumbo_optional();
+ features.set_shutdown_any_segwit_optional();
+ features.set_channel_type_optional();
+ features.set_scid_privacy_optional();
+ features.set_zero_conf_optional();
+ features
+ }
}
impl Deref for ErroringMessageHandler {
type Target = ErroringMessageHandler;
pending_outbound_buffer: LinkedList<Vec<u8>>,
pending_outbound_buffer_first_msg_offset: usize,
- // Queue gossip broadcasts separately from `pending_outbound_buffer` so we can easily prioritize
- // channel messages over them.
+ /// Queue gossip broadcasts separately from `pending_outbound_buffer` so we can easily
+ /// prioritize channel messages over them.
+ ///
+ /// Note that these messages are *not* encrypted/MAC'd, and are only serialized.
gossip_broadcast_buffer: LinkedList<Vec<u8>>,
awaiting_write_event: bool,
/// SimpleRefPeerManager is the more appropriate type. Defining these type aliases prevents
/// issues such as overly long function definitions.
///
-/// (C-not exported) as Arcs don't make sense in bindings
-pub type SimpleArcPeerManager<SD, M, T, F, C, L> = PeerManager<SD, Arc<SimpleArcChannelManager<M, T, F, L>>, Arc<P2PGossipSync<Arc<NetworkGraph<Arc<L>>>, Arc<C>, Arc<L>>>, IgnoringMessageHandler, Arc<L>, Arc<IgnoringMessageHandler>>;
+/// (C-not exported) as `Arc`s don't make sense in bindings.
+pub type SimpleArcPeerManager<SD, M, T, F, C, L> = PeerManager<SD, Arc<SimpleArcChannelManager<M, T, F, L>>, Arc<P2PGossipSync<Arc<NetworkGraph<Arc<L>>>, Arc<C>, Arc<L>>>, Arc<SimpleArcOnionMessenger<L>>, Arc<L>, IgnoringMessageHandler>;
/// SimpleRefPeerManager is a type alias for a PeerManager reference, and is the reference
/// counterpart to the SimpleArcPeerManager type alias. Use this type by default when you don't
/// But if this is not necessary, using a reference is more efficient. Defining these type aliases
/// helps with issues such as long function definitions.
///
-/// (C-not exported) as Arcs don't make sense in bindings
-pub type SimpleRefPeerManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, SD, M, T, F, C, L> = PeerManager<SD, SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, M, T, F, L>, &'e P2PGossipSync<&'g NetworkGraph<&'f L>, &'h C, &'f L>, IgnoringMessageHandler, &'f L, IgnoringMessageHandler>;
+/// (C-not exported) as general type aliases don't make sense in bindings.
+pub type SimpleRefPeerManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, SD, M, T, F, C, L> = PeerManager<SD, SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, M, T, F, L>, &'e P2PGossipSync<&'g NetworkGraph<&'f L>, &'h C, &'f L>, &'i SimpleRefOnionMessenger<'j, 'k, L>, &'f L, IgnoringMessageHandler>;
/// A PeerManager manages a set of peers, described by their [`SocketDescriptor`] and marshalls
/// socket events into messages which it passes on to its [`MessageHandler`].
/// Instead, we limit the total blocked event processors to always exactly one by setting this
/// when an event process call is waiting.
blocked_event_processors: AtomicBool,
+
+ /// Used to track the last value sent in a node_announcement "timestamp" field. We ensure this
+ /// value increases strictly since we don't assume access to a time source.
+ last_node_announcement_serial: AtomicU64,
+
our_node_secret: SecretKey,
ephemeral_key_midstate: Sha256Engine,
custom_message_handler: CMH,
/// ephemeral_random_data is used to derive per-connection ephemeral keys and must be
/// cryptographically secure random bytes.
///
+ /// `current_time` is used as an always-increasing counter that survives across restarts and is
+ /// incremented irregularly internally. In general it is best to simply use the current UNIX
+ /// timestamp, however if it is not available a persistent counter that increases once per
+ /// minute should suffice.
+ ///
/// (C-not exported) as we can't export a PeerManager with a dummy route handler
- pub fn new_channel_only(channel_message_handler: CM, onion_message_handler: OM, our_node_secret: SecretKey, ephemeral_random_data: &[u8; 32], logger: L) -> Self {
+ pub fn new_channel_only(channel_message_handler: CM, onion_message_handler: OM, our_node_secret: SecretKey, current_time: u64, ephemeral_random_data: &[u8; 32], logger: L) -> Self {
Self::new(MessageHandler {
chan_handler: channel_message_handler,
route_handler: IgnoringMessageHandler{},
onion_message_handler,
- }, our_node_secret, ephemeral_random_data, logger, IgnoringMessageHandler{})
+ }, our_node_secret, current_time, ephemeral_random_data, logger, IgnoringMessageHandler{})
}
}
/// generate error messages). Note that some other lightning implementations time-out connections
/// after some time if no channel is built with the peer.
///
+ /// `current_time` is used as an always-increasing counter that survives across restarts and is
+ /// incremented irregularly internally. In general it is best to simply use the current UNIX
+ /// timestamp, however if it is not available a persistent counter that increases once per
+ /// minute should suffice.
+ ///
/// ephemeral_random_data is used to derive per-connection ephemeral keys and must be
/// cryptographically secure random bytes.
///
/// (C-not exported) as we can't export a PeerManager with a dummy channel handler
- pub fn new_routing_only(routing_message_handler: RM, our_node_secret: SecretKey, ephemeral_random_data: &[u8; 32], logger: L) -> Self {
+ pub fn new_routing_only(routing_message_handler: RM, our_node_secret: SecretKey, current_time: u64, ephemeral_random_data: &[u8; 32], logger: L) -> Self {
Self::new(MessageHandler {
chan_handler: ErroringMessageHandler::new(),
route_handler: routing_message_handler,
onion_message_handler: IgnoringMessageHandler{},
- }, our_node_secret, ephemeral_random_data, logger, IgnoringMessageHandler{})
+ }, our_node_secret, current_time, ephemeral_random_data, logger, IgnoringMessageHandler{})
}
}
/// Constructs a new PeerManager with the given message handlers and node_id secret key
/// ephemeral_random_data is used to derive per-connection ephemeral keys and must be
/// cryptographically secure random bytes.
- pub fn new(message_handler: MessageHandler<CM, RM, OM>, our_node_secret: SecretKey, ephemeral_random_data: &[u8; 32], logger: L, custom_message_handler: CMH) -> Self {
+ ///
+ /// `current_time` is used as an always-increasing counter that survives across restarts and is
+ /// incremented irregularly internally. In general it is best to simply use the current UNIX
+ /// timestamp, however if it is not available a persistent counter that increases once per
+ /// minute should suffice.
+ pub fn new(message_handler: MessageHandler<CM, RM, OM>, our_node_secret: SecretKey, current_time: u64, ephemeral_random_data: &[u8; 32], logger: L, custom_message_handler: CMH) -> Self {
let mut ephemeral_key_midstate = Sha256::engine();
ephemeral_key_midstate.input(ephemeral_random_data);
our_node_secret,
ephemeral_key_midstate,
peer_counter: AtomicCounter::new(),
+ last_node_announcement_serial: AtomicU64::new(current_time),
logger,
custom_message_handler,
secp_ctx,
}
if peer.should_buffer_gossip_broadcast() {
if let Some(msg) = peer.gossip_broadcast_buffer.pop_front() {
- peer.pending_outbound_buffer.push_back(msg);
+ peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_buffer(&msg[..]));
}
}
if peer.should_buffer_gossip_backfill() {
/// Append a message to a peer's pending outbound/write buffer
fn enqueue_message<M: wire::Type>(&self, peer: &mut Peer, message: &M) {
- let mut buffer = VecWriter(Vec::with_capacity(2048));
- wire::write(message, &mut buffer).unwrap(); // crash if the write failed
-
if is_gossip_msg(message.type_id()) {
log_gossip!(self.logger, "Enqueueing message {:?} to {}", message, log_pubkey!(peer.their_node_id.unwrap()));
} else {
log_trace!(self.logger, "Enqueueing message {:?} to {}", message, log_pubkey!(peer.their_node_id.unwrap()))
}
peer.msgs_sent_since_pong += 1;
- peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&buffer.0[..]));
+ peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(message));
}
/// Append a message to a peer's pending outbound/write gossip broadcast buffer
- fn enqueue_encoded_gossip_broadcast(&self, peer: &mut Peer, encoded_message: &Vec<u8>) {
+ fn enqueue_encoded_gossip_broadcast(&self, peer: &mut Peer, encoded_message: Vec<u8>) {
peer.msgs_sent_since_pong += 1;
- peer.gossip_broadcast_buffer.push_back(peer.channel_encryptor.encrypt_message(&encoded_message[..]));
+ peer.gossip_broadcast_buffer.push_back(encoded_message);
}
fn do_read_event(&self, peer_descriptor: &mut Descriptor, data: &[u8]) -> Result<bool, PeerHandleError> {
peer.their_node_id = Some(their_node_id);
insert_node_id!();
- let features = InitFeatures::known();
+ let features = self.message_handler.chan_handler.provided_init_features(&their_node_id)
+ .or(self.message_handler.route_handler.provided_init_features(&their_node_id))
+ .or(self.message_handler.onion_message_handler.provided_init_features(&their_node_id));
let resp = msgs::Init { features, remote_network_address: filter_addresses(peer.their_net_address.clone()) };
self.enqueue_message(peer, &resp);
peer.awaiting_pong_timer_tick_intervals = 0;
peer.pending_read_is_header = true;
peer.their_node_id = Some(their_node_id);
insert_node_id!();
- let features = InitFeatures::known();
+ let features = self.message_handler.chan_handler.provided_init_features(&their_node_id)
+ .or(self.message_handler.route_handler.provided_init_features(&their_node_id))
+ .or(self.message_handler.onion_message_handler.provided_init_features(&their_node_id));
let resp = msgs::Init { features, remote_network_address: filter_addresses(peer.their_net_address.clone()) };
self.enqueue_message(peer, &resp);
peer.awaiting_pong_timer_tick_intervals = 0;
}
(_, Some(ty)) if is_gossip_msg(ty) => {
log_gossip!(self.logger, "Got an invalid value while deserializing a gossip message");
- self.enqueue_message(peer, &msgs::WarningMessage { channel_id: [0; 32], data: "Unreadable/bogus gossip message".to_owned() });
+ self.enqueue_message(peer, &msgs::WarningMessage {
+ channel_id: [0; 32],
+ data: format!("Unreadable/bogus gossip message of type {}", ty),
+ });
continue;
}
(msgs::DecodeError::UnknownRequiredFeature, ty) => {
peer_lock.sync_status = InitSyncTracker::ChannelsSyncing(0);
}
- if !msg.features.supports_static_remote_key() {
- log_debug!(self.logger, "Peer {} does not support static remote key, disconnecting with no_connection_possible", log_pubkey!(their_node_id));
+ if let Err(()) = self.message_handler.route_handler.peer_connected(&their_node_id, &msg) {
+ log_debug!(self.logger, "Route Handler decided we couldn't communicate with peer {}", log_pubkey!(their_node_id));
+ return Err(PeerHandleError{ no_connection_possible: true }.into());
+ }
+ if let Err(()) = self.message_handler.chan_handler.peer_connected(&their_node_id, &msg) {
+ log_debug!(self.logger, "Channel Handler decided we couldn't communicate with peer {}", log_pubkey!(their_node_id));
+ return Err(PeerHandleError{ no_connection_possible: true }.into());
+ }
+ if let Err(()) = self.message_handler.onion_message_handler.peer_connected(&their_node_id, &msg) {
+ log_debug!(self.logger, "Onion Message Handler decided we couldn't communicate with peer {}", log_pubkey!(their_node_id));
return Err(PeerHandleError{ no_connection_possible: true }.into());
}
-
- self.message_handler.route_handler.peer_connected(&their_node_id, &msg);
- self.message_handler.chan_handler.peer_connected(&their_node_id, &msg);
- self.message_handler.onion_message_handler.peer_connected(&their_node_id, &msg);
peer_lock.their_features = Some(msg.features);
return Ok(None);
if except_node.is_some() && peer.their_node_id.as_ref() == except_node {
continue;
}
- self.enqueue_encoded_gossip_broadcast(&mut *peer, &encoded_msg);
+ self.enqueue_encoded_gossip_broadcast(&mut *peer, encoded_msg.clone());
}
},
wire::Message::NodeAnnouncement(ref msg) => {
if except_node.is_some() && peer.their_node_id.as_ref() == except_node {
continue;
}
- self.enqueue_encoded_gossip_broadcast(&mut *peer, &encoded_msg);
+ self.enqueue_encoded_gossip_broadcast(&mut *peer, encoded_msg.clone());
}
},
wire::Message::ChannelUpdate(ref msg) => {
if except_node.is_some() && peer.their_node_id.as_ref() == except_node {
continue;
}
- self.enqueue_encoded_gossip_broadcast(&mut *peer, &encoded_msg);
+ self.enqueue_encoded_gossip_broadcast(&mut *peer, encoded_msg.clone());
}
},
_ => debug_assert!(false, "We shouldn't attempt to forward anything but gossip messages"),
log_bytes!(msg.channel_id));
self.enqueue_message(&mut *get_peer_for_forwarding!(node_id), msg);
},
+ MessageSendEvent::SendChannelAnnouncement { ref node_id, ref msg, ref update_msg } => {
+ log_debug!(self.logger, "Handling SendChannelAnnouncement event in peer_handler for node {} for short channel id {}",
+ log_pubkey!(node_id),
+ msg.contents.short_channel_id);
+ self.enqueue_message(&mut *get_peer_for_forwarding!(node_id), msg);
+ self.enqueue_message(&mut *get_peer_for_forwarding!(node_id), update_msg);
+ },
MessageSendEvent::BroadcastChannelAnnouncement { msg, update_msg } => {
log_debug!(self.logger, "Handling BroadcastChannelAnnouncement event in peer_handler for short channel id {}", msg.contents.short_channel_id);
match self.message_handler.route_handler.handle_channel_announcement(&msg) {
_ => {},
}
},
- MessageSendEvent::BroadcastNodeAnnouncement { msg } => {
- log_debug!(self.logger, "Handling BroadcastNodeAnnouncement event in peer_handler");
- match self.message_handler.route_handler.handle_node_announcement(&msg) {
- Ok(_) | Err(LightningError { action: msgs::ErrorAction::IgnoreDuplicateGossip, .. }) =>
- self.forward_broadcast_msg(peers, &wire::Message::NodeAnnouncement(msg), None),
- _ => {},
- }
- },
MessageSendEvent::BroadcastChannelUpdate { msg } => {
log_debug!(self.logger, "Handling BroadcastChannelUpdate event in peer_handler for short channel id {}", msg.contents.short_channel_id);
match self.message_handler.route_handler.handle_channel_update(&msg) {
}
}
}
+
+ #[allow(dead_code)]
+ // Messages of up to 64KB should never end up more than half full with addresses, as that would
+ // be absurd. We ensure this by checking that at least 100 (our stated public contract on when
+ // broadcast_node_announcement panics) of the maximum-length addresses would fit in a 64KB
+ // message...
+ const HALF_MESSAGE_IS_ADDRS: u32 = ::core::u16::MAX as u32 / (NetAddress::MAX_LEN as u32 + 1) / 2;
+ #[deny(const_err)]
+ #[allow(dead_code)]
+ // ...by failing to compile if the number of addresses that would be half of a message is
+ // smaller than 100:
+ const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 100;
+
+ /// Generates a signed node_announcement from the given arguments, sending it to all connected
+ /// peers. Note that peers will likely ignore this message unless we have at least one public
+ /// channel which has at least six confirmations on-chain.
+ ///
+ /// `rgb` is a node "color" and `alias` is a printable human-readable string to describe this
+ /// node to humans. They carry no in-protocol meaning.
+ ///
+ /// `addresses` represent the set (possibly empty) of socket addresses on which this node
+ /// accepts incoming connections. These will be included in the node_announcement, publicly
+ /// tying these addresses together and to this node. If you wish to preserve user privacy,
+ /// addresses should likely contain only Tor Onion addresses.
+ ///
+ /// Panics if `addresses` is absurdly large (more than 100).
+ ///
+ /// [`get_and_clear_pending_msg_events`]: MessageSendEventsProvider::get_and_clear_pending_msg_events
+ pub fn broadcast_node_announcement(&self, rgb: [u8; 3], alias: [u8; 32], mut addresses: Vec<NetAddress>) {
+ if addresses.len() > 100 {
+ panic!("More than half the message size was taken up by public addresses!");
+ }
+
+ // While all existing nodes handle unsorted addresses just fine, the spec requires that
+ // addresses be sorted for future compatibility.
+ addresses.sort_by_key(|addr| addr.get_id());
+
+ let features = self.message_handler.chan_handler.provided_node_features()
+ .or(self.message_handler.route_handler.provided_node_features())
+ .or(self.message_handler.onion_message_handler.provided_node_features());
+ let announcement = msgs::UnsignedNodeAnnouncement {
+ features,
+ timestamp: self.last_node_announcement_serial.fetch_add(1, Ordering::AcqRel) as u32,
+ node_id: PublicKey::from_secret_key(&self.secp_ctx, &self.our_node_secret),
+ rgb, alias, addresses,
+ excess_address_data: Vec::new(),
+ excess_data: Vec::new(),
+ };
+ let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);
+ let node_announce_sig = sign(&self.secp_ctx, &msghash, &self.our_node_secret);
+
+ let msg = msgs::NodeAnnouncement {
+ signature: node_announce_sig,
+ contents: announcement
+ };
+
+ log_debug!(self.logger, "Broadcasting NodeAnnouncement after passing it to our own RoutingMessageHandler.");
+ let _ = self.message_handler.route_handler.handle_node_announcement(&msg);
+ self.forward_broadcast_msg(&*self.peers.read().unwrap(), &wire::Message::NodeAnnouncement(msg), None);
+ }
}
fn is_gossip_msg(type_id: u16) -> bool {
let node_secret = SecretKey::from_slice(&[42 + i as u8; 32]).unwrap();
let ephemeral_bytes = [i as u8; 32];
let msg_handler = MessageHandler { chan_handler: &cfgs[i].chan_handler, route_handler: &cfgs[i].routing_handler, onion_message_handler: IgnoringMessageHandler {} };
- let peer = PeerManager::new(msg_handler, node_secret, &ephemeral_bytes, &cfgs[i].logger, IgnoringMessageHandler {});
+ let peer = PeerManager::new(msg_handler, node_secret, 0, &ephemeral_bytes, &cfgs[i].logger, IgnoringMessageHandler {});
peers.push(peer);
}
use chain::{ChannelMonitorUpdateErr, Watch};
use chain::channelmonitor::ChannelMonitor;
use chain::keysinterface::{Recipient, KeysInterface};
-use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, MIN_CLTV_EXPIRY_DELTA};
+use ln::channelmanager::{self, ChannelManager, ChannelManagerReadArgs, MIN_CLTV_EXPIRY_DELTA};
use routing::gossip::RoutingFees;
use routing::router::{PaymentParameters, RouteHint, RouteHintHop};
-use ln::features::{InitFeatures, InvoiceFeatures, ChannelTypeFeatures};
+use ln::features::ChannelTypeFeatures;
use ln::msgs;
use ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, ChannelUpdate, ErrorAction};
use ln::wire::Encode;
let nodes_1_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_id_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known()).2;
- let chan_id_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known()).0.channel_id;
+ let chan_id_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
+ let chan_id_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 500_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.channel_id;
// We should always be able to forward through nodes[1] as long as its out through a public
// channel:
}]);
let last_hops = vec![route_hint];
let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
- .with_features(InvoiceFeatures::known())
+ .with_features(channelmanager::provided_invoice_features())
.with_route_hints(last_hops);
let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 10_000, TEST_FINAL_CLTV);
check_added_monitors!(nodes[1], 2);
nodes[1].node = &nodes_1_deserialized;
- nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known(), remote_network_address: None });
- nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
- let as_reestablish = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
- let bs_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let as_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
+ let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &as_reestablish);
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id());
- nodes[1].node.peer_connected(&nodes[2].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known(), remote_network_address: None });
- nodes[2].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
- let bs_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[2].node.get_our_node_id());
- let cs_reestablish = get_event_msg!(nodes[2], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
+ nodes[1].node.peer_connected(&nodes[2].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ nodes[2].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[2]).pop().unwrap();
+ let cs_reestablish = get_chan_reestablish_msgs!(nodes[2], nodes[1]).pop().unwrap();
nodes[2].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
nodes[1].node.handle_channel_reestablish(&nodes[2].node.get_our_node_id(), &cs_reestablish);
get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[2].node.get_our_node_id());
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
*nodes[0].connect_style.borrow_mut() = connect_style;
- let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
mine_transaction(&nodes[1], &tx);
nodes[0].node.handle_channel_ready(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, nodes[0].node.get_our_node_id()));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(no_announce_cfg), None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known()).2;
- let mut as_channel_ready = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known()).0;
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
+ let mut as_channel_ready = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 500_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0;
let last_hop = nodes[2].node.list_usable_channels();
let hop_hints = vec![RouteHint(vec![RouteHintHop {
htlc_minimum_msat: None,
}])];
let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
- .with_features(InvoiceFeatures::known())
+ .with_features(channelmanager::provided_invoice_features())
.with_route_hints(hop_hints);
let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 100_000, 42);
assert_eq!(route.paths[0][1].short_channel_id, last_hop[0].inbound_scid_alias.unwrap());
open_channel.channel_type.as_mut().unwrap().set_scid_privacy_required();
assert_eq!(open_channel.channel_flags & 1, 1); // The `announce_channel` bit is set.
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
let err = get_err_msg!(nodes[1], nodes[0].node.get_our_node_id());
assert_eq!(err.data, "SCID Alias/Privacy Channel Type cannot be set on a public channel");
}
let second_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
assert!(!second_open_channel.channel_type.as_ref().unwrap().supports_scid_privacy());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &second_open_channel);
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &second_open_channel);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(accept_forward_cfg), None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let mut no_announce_cfg = test_default_channel_config();
no_announce_cfg.channel_handshake_config.announced_channel = false;
assert!(open_channel.channel_type.as_ref().unwrap().requires_scid_privacy());
- nodes[2].node.handle_open_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &open_channel);
+ nodes[2].node.handle_open_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
let accept_channel = get_event_msg!(nodes[2], MessageSendEvent::SendAcceptChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_accept_channel(&nodes[2].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
+ nodes[1].node.handle_accept_channel(&nodes[2].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel);
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[1], &nodes[2].node.get_our_node_id(), 100_000, 42);
nodes[1].node.funding_transaction_generated(&temporary_channel_id, &nodes[2].node.get_our_node_id(), tx.clone()).unwrap();
htlc_minimum_msat: None,
}])];
let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
- .with_features(InvoiceFeatures::known())
+ .with_features(channelmanager::provided_invoice_features())
.with_route_hints(hop_hints.clone());
let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 100_000, 42);
assert_eq!(route.paths[0][1].short_channel_id, last_hop[0].inbound_scid_alias.unwrap());
hop_hints[0].0[0].short_channel_id = last_hop[0].short_channel_id.unwrap();
let payment_params_2 = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
- .with_features(InvoiceFeatures::known())
+ .with_features(channelmanager::provided_invoice_features())
.with_route_hints(hop_hints);
let (route_2, payment_hash_2, _, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params_2, 100_000, 42);
assert_eq!(route_2.paths[0][1].short_channel_id, last_hop[0].short_channel_id.unwrap());
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(accept_forward_cfg), None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0, InitFeatures::known(), InitFeatures::known());
- let chan = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 10_000, 0, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 10_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let last_hop = nodes[2].node.list_usable_channels();
let mut hop_hints = vec![RouteHint(vec![RouteHintHop {
htlc_minimum_msat: None,
}])];
let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
- .with_features(InvoiceFeatures::known())
+ .with_features(channelmanager::provided_invoice_features())
.with_route_hints(hop_hints);
let (mut route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 10_000, 42);
assert_eq!(route.paths[0][1].short_channel_id, nodes[2].node.list_usable_channels()[0].inbound_scid_alias.unwrap());
.blamed_chan_closed(false).expected_htlc_error_data(0x1000|12, &err_data));
}
-// Receiver must have been initialized with manually_accept_inbound_channels set to true.
-fn open_zero_conf_channel<'a, 'b, 'c, 'd>(initiator: &'a Node<'b, 'c, 'd>, receiver: &'a Node<'b, 'c, 'd>, initiator_config: Option<UserConfig>) -> bitcoin::Transaction {
- initiator.node.create_channel(receiver.node.get_our_node_id(), 100_000, 10_001, 42, initiator_config).unwrap();
- let open_channel = get_event_msg!(initiator, MessageSendEvent::SendOpenChannel, receiver.node.get_our_node_id());
-
- receiver.node.handle_open_channel(&initiator.node.get_our_node_id(), InitFeatures::known(), &open_channel);
- let events = receiver.node.get_and_clear_pending_events();
- assert_eq!(events.len(), 1);
- match events[0] {
- Event::OpenChannelRequest { temporary_channel_id, .. } => {
- receiver.node.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, &initiator.node.get_our_node_id(), 0).unwrap();
- },
- _ => panic!("Unexpected event"),
- };
-
- let mut accept_channel = get_event_msg!(receiver, MessageSendEvent::SendAcceptChannel, initiator.node.get_our_node_id());
- assert_eq!(accept_channel.minimum_depth, 0);
- initiator.node.handle_accept_channel(&receiver.node.get_our_node_id(), InitFeatures::known(), &accept_channel);
-
- let (temporary_channel_id, tx, _) = create_funding_transaction(&initiator, &receiver.node.get_our_node_id(), 100_000, 42);
- initiator.node.funding_transaction_generated(&temporary_channel_id, &receiver.node.get_our_node_id(), tx.clone()).unwrap();
- let funding_created = get_event_msg!(initiator, MessageSendEvent::SendFundingCreated, receiver.node.get_our_node_id());
-
- receiver.node.handle_funding_created(&initiator.node.get_our_node_id(), &funding_created);
- check_added_monitors!(receiver, 1);
- let bs_signed_locked = receiver.node.get_and_clear_pending_msg_events();
- assert_eq!(bs_signed_locked.len(), 2);
- let as_channel_ready;
- match &bs_signed_locked[0] {
- MessageSendEvent::SendFundingSigned { node_id, msg } => {
- assert_eq!(*node_id, initiator.node.get_our_node_id());
- initiator.node.handle_funding_signed(&receiver.node.get_our_node_id(), &msg);
- check_added_monitors!(initiator, 1);
-
- assert_eq!(initiator.tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1);
- assert_eq!(initiator.tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0)[0], tx);
-
- as_channel_ready = get_event_msg!(initiator, MessageSendEvent::SendChannelReady, receiver.node.get_our_node_id());
- }
- _ => panic!("Unexpected event"),
- }
- match &bs_signed_locked[1] {
- MessageSendEvent::SendChannelReady { node_id, msg } => {
- assert_eq!(*node_id, initiator.node.get_our_node_id());
- initiator.node.handle_channel_ready(&receiver.node.get_our_node_id(), &msg);
- }
- _ => panic!("Unexpected event"),
- }
-
- receiver.node.handle_channel_ready(&initiator.node.get_our_node_id(), &as_channel_ready);
-
- let as_channel_update = get_event_msg!(initiator, MessageSendEvent::SendChannelUpdate, receiver.node.get_our_node_id());
- let bs_channel_update = get_event_msg!(receiver, MessageSendEvent::SendChannelUpdate, initiator.node.get_our_node_id());
-
- initiator.node.handle_channel_update(&receiver.node.get_our_node_id(), &bs_channel_update);
- receiver.node.handle_channel_update(&initiator.node.get_our_node_id(), &as_channel_update);
-
- assert_eq!(initiator.node.list_usable_channels().len(), 1);
- assert_eq!(receiver.node.list_usable_channels().len(), 1);
-
- tx
-}
-
#[test]
fn test_simple_0conf_channel() {
// If our peer tells us they will accept our channel with 0 confs, and we funded the channel,
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(chan_config), None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
chan_config.channel_handshake_config.announced_channel = false;
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, Some(chan_config)).unwrap();
let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
let events = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events[0] {
let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
assert_eq!(accept_channel.minimum_depth, 0);
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel);
let (temporary_channel_id, tx, funding_output) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
// This is the default but we force it on anyway
chan_config.channel_handshake_config.announced_channel = true;
- let tx = open_zero_conf_channel(&nodes[0], &nodes[1], Some(chan_config));
+ let (tx, ..) = open_zero_conf_channel(&nodes[0], &nodes[1], Some(chan_config));
// We can use the channel immediately, but we can't announce it until we get 6+ confirmations
send_payment(&nodes[0], &[&nodes[1]], 100_000);
// This is the default but we force it on anyway
chan_config.channel_handshake_config.announced_channel = true;
- let tx = open_zero_conf_channel(&nodes[0], &nodes[1], Some(chan_config));
+ let (tx, ..) = open_zero_conf_channel(&nodes[0], &nodes[1], Some(chan_config));
// We can use the channel immediately, but we can't announce it until we get 6+ confirmations
send_payment(&nodes[0], &[&nodes[1]], 100_000);
open_channel_msg.channel_type = Some(channel_type_features.clone());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel_msg);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel_msg);
let msg_events = nodes[1].node.get_and_clear_pending_msg_events();
match msg_events[0] {
open_channel_msg.channel_type = Some(channel_type_features.clone());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(),
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(),
&open_channel_msg);
// Assert that `nodes[1]` has no `MessageSendEvent::SendAcceptChannel` in the `msg_events`.
open_channel_msg.channel_type = Some(channel_type_features);
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(),
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(),
&open_channel_msg);
let events = nodes[1].node.get_and_clear_pending_events();
_ => panic!(),
}
}
+
+#[test]
+fn test_connect_before_funding() {
+ // Tests for a particularly dumb explicit panic that existed prior to 0.0.111 for 0conf
+ // channels. If we received a block while awaiting funding for 0-conf channels we'd hit an
+ // explicit panic when deciding if we should broadcast our channel_ready message.
+ let chanmon_cfgs = create_chanmon_cfgs(2);
+ let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+
+ let mut manually_accept_conf = test_default_channel_config();
+ manually_accept_conf.manually_accept_inbound_channels = true;
+
+ let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(manually_accept_conf)]);
+ let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+ nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 10_001, 42, None).unwrap();
+ let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
+
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
+ let events = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match events[0] {
+ Event::OpenChannelRequest { temporary_channel_id, .. } => {
+ nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0).unwrap();
+ },
+ _ => panic!("Unexpected event"),
+ };
+
+ let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
+ assert_eq!(accept_channel.minimum_depth, 0);
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), channelmanager::provided_init_features(), &accept_channel);
+
+ let events = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match events[0] {
+ Event::FundingGenerationReady { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+
+ connect_blocks(&nodes[0], 1);
+ connect_blocks(&nodes[1], 1);
+}
use chain::channelmonitor::{ANTI_REORG_DELAY, ChannelMonitor};
use chain::transaction::OutPoint;
use chain::{Confirm, Watch};
-use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs};
-use ln::features::InitFeatures;
+use ln::channelmanager::{self, ChannelManager, ChannelManagerReadArgs};
use ln::msgs::ChannelMessageHandler;
use util::enforcing_trait_impls::EnforcingSigner;
use util::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination};
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Make sure all nodes are at the same starting height
connect_blocks(&nodes[0], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1);
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_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
// Get the initial commitment transaction for broadcast, before any HTLCs are added at all.
let revoked_local_txn = get_local_commitment_txn!(nodes[0], chan.2);
// Connect blocks to confirm the unrevoked commitment transaction
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 2);
- expect_payment_failed!(nodes[1], payment_hash_4, true);
+ expect_payment_failed!(nodes[1], payment_hash_4, false);
}
fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_unconfirmed: bool, connect_style: ConnectStyle) {
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
*nodes[0].connect_style.borrow_mut() = connect_style;
- let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let channel_state = nodes[0].node.channel_state.lock().unwrap();
assert_eq!(channel_state.by_id.len(), 1);
nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clear();
// Now check that we can create a new channel
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
send_payment(&nodes[0], &[&nodes[1]], 8000000);
}
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_with_value(&nodes, 0, 1, 1000000, 59000000, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage_1, payment_hash_1, _) = route_payment(&nodes[1], &[&nodes[0]], 3_000_000);
let (payment_preimage_2, payment_hash_2, _) = route_payment(&nodes[1], &[&nodes[0]], 3_000_000);
*nodes[1].connect_style.borrow_mut() = style;
let (_, _, chan_id, funding_tx) =
- create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 100_000_000, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 100_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 };
assert_eq!(funding_outpoint.to_channel_id(), chan_id);
use bitcoin::secp256k1::PublicKey;
use bitcoin::util::address::WitnessVersion;
+use ln::channelmanager;
use ln::features::InitFeatures;
use ln::msgs::DecodeError;
use util::ser::{Readable, Writeable, Writer};
type Error = InvalidShutdownScript;
fn try_from(script: Script) -> Result<Self, Self::Error> {
- Self::try_from((script, &InitFeatures::known()))
+ Self::try_from((script, &channelmanager::provided_init_features()))
}
}
.into_script()
}
+ fn any_segwit_features() -> InitFeatures {
+ let mut features = InitFeatures::empty();
+ features.set_shutdown_any_segwit_optional();
+ features
+ }
+
#[test]
fn generates_p2wpkh_from_pubkey() {
let pubkey = pubkey();
let p2wpkh_script = Script::new_v0_p2wpkh(&pubkey_hash);
let shutdown_script = ShutdownScript::new_p2wpkh_from_pubkey(pubkey.inner);
- assert!(shutdown_script.is_compatible(&InitFeatures::known()));
- assert!(shutdown_script.is_compatible(&InitFeatures::known().clear_shutdown_anysegwit()));
+ assert!(shutdown_script.is_compatible(&any_segwit_features()));
+ assert!(shutdown_script.is_compatible(&InitFeatures::empty()));
assert_eq!(shutdown_script.into_inner(), p2wpkh_script);
}
let p2wpkh_script = Script::new_v0_p2wpkh(&pubkey_hash);
let shutdown_script = ShutdownScript::new_p2wpkh(&pubkey_hash);
- assert!(shutdown_script.is_compatible(&InitFeatures::known()));
- assert!(shutdown_script.is_compatible(&InitFeatures::known().clear_shutdown_anysegwit()));
+ assert!(shutdown_script.is_compatible(&any_segwit_features()));
+ assert!(shutdown_script.is_compatible(&InitFeatures::empty()));
assert_eq!(shutdown_script.into_inner(), p2wpkh_script);
assert!(ShutdownScript::try_from(p2wpkh_script).is_ok());
}
let p2wsh_script = Script::new_v0_p2wsh(&script_hash);
let shutdown_script = ShutdownScript::new_p2wsh(&script_hash);
- assert!(shutdown_script.is_compatible(&InitFeatures::known()));
- assert!(shutdown_script.is_compatible(&InitFeatures::known().clear_shutdown_anysegwit()));
+ assert!(shutdown_script.is_compatible(&any_segwit_features()));
+ assert!(shutdown_script.is_compatible(&InitFeatures::empty()));
assert_eq!(shutdown_script.into_inner(), p2wsh_script);
assert!(ShutdownScript::try_from(p2wsh_script).is_ok());
}
fn generates_segwit_from_non_v0_witness_program() {
let witness_program = Script::new_witness_program(WitnessVersion::V16, &[0; 40]);
let shutdown_script = ShutdownScript::new_witness_program(WitnessVersion::V16, &[0; 40]).unwrap();
- assert!(shutdown_script.is_compatible(&InitFeatures::known()));
- assert!(!shutdown_script.is_compatible(&InitFeatures::known().clear_shutdown_anysegwit()));
+ assert!(shutdown_script.is_compatible(&any_segwit_features()));
+ assert!(!shutdown_script.is_compatible(&InitFeatures::empty()));
assert_eq!(shutdown_script.into_inner(), witness_program);
}
use chain::keysinterface::KeysInterface;
use chain::transaction::OutPoint;
-use ln::channelmanager::PaymentSendFailure;
+use ln::channelmanager::{self, PaymentSendFailure};
use routing::router::{PaymentParameters, get_route};
-use ln::features::{InitFeatures, InvoiceFeatures};
use ln::msgs;
use ln::msgs::{ChannelMessageHandler, ErrorAction};
use ln::script::ShutdownScript;
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 tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 8000000, 0, InitFeatures::known(), InitFeatures::known());
+ let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 8000000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
mine_transaction(&nodes[0], &tx);
mine_transaction(&nodes[1], &tx);
nodes[0].node.close_channel(&OutPoint { txid: tx.txid(), index: 0 }.to_channel_id(), &nodes[1].node.get_our_node_id()).unwrap();
let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_1_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_1_shutdown);
let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id());
nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_closing_signed);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let logger = test_utils::TestLogger::new();
let scorer = test_utils::TestScorer::with_penalty(0);
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
nodes[0].node.close_channel(&chan_1.2, &nodes[1].node.get_our_node_id()).unwrap();
let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_1_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_1_shutdown);
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[0]);
- let payment_params_1 = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id()).with_features(InvoiceFeatures::known());
+ let payment_params_1 = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id()).with_features(channelmanager::provided_invoice_features());
let route_1 = get_route(&nodes[0].node.get_our_node_id(), &payment_params_1, &nodes[0].network_graph.read_only(), None, 100000, TEST_FINAL_CLTV, &logger, &scorer, &random_seed_bytes).unwrap();
- let payment_params_2 = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id()).with_features(InvoiceFeatures::known());
+ let payment_params_2 = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id()).with_features(channelmanager::provided_invoice_features());
let route_2 = get_route(&nodes[1].node.get_our_node_id(), &payment_params_2, &nodes[1].network_graph.read_only(), None, 100000, TEST_FINAL_CLTV, &logger, &scorer, &random_seed_bytes).unwrap();
unwrap_send_err!(nodes[0].node.send_payment(&route_1, payment_hash, &Some(payment_secret)), true, APIError::ChannelUnavailable {..}, {});
unwrap_send_err!(nodes[1].node.send_payment(&route_2, payment_hash, &Some(payment_secret)), true, APIError::ChannelUnavailable {..}, {});
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 100000);
nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
nodes[1].node.close_channel(&chan_1.2, &nodes[0].node.get_our_node_id()).unwrap();
let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_1_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_1_shutdown);
let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &updates.commitment_signed);
check_added_monitors!(nodes[1], 1);
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
commitment_signed_dance!(nodes[1], nodes[0], (), false, true, false);
let updates_2 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
+ let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000);
nodes[1].node.close_channel(&chan_1.2, &nodes[0].node.get_our_node_id()).unwrap();
let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
if recv_count > 0 {
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_1_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_1_shutdown);
let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
if recv_count > 1 {
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
}
}
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::empty(), remote_network_address: None });
- let node_0_reestablish = 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::empty(), remote_network_address: None });
- let node_1_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let node_0_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let node_1_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &node_0_reestablish);
let node_1_2nd_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &node_1_reestablish);
let node_0_2nd_shutdown = if recv_count > 0 {
let node_0_2nd_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_1_2nd_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_1_2nd_shutdown);
node_0_2nd_shutdown
} else {
let node_0_chan_update = get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
assert_eq!(node_0_chan_update.contents.flags & 2, 0); // "disabled" flag must not be set as we just reconnected.
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_1_2nd_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_1_2nd_shutdown);
get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id())
};
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_2nd_shutdown);
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_2nd_shutdown);
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
assert!(nodes[1].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[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
- let node_1_2nd_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
- nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None });
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
+ let node_1_2nd_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap();
if recv_count == 0 {
// If all closing_signeds weren't delivered we can just resume where we left off...
- let node_0_2nd_reestablish = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
+ let node_0_2nd_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap();
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &node_1_2nd_reestablish);
let node_0_msgs = nodes[0].node.get_and_clear_pending_msg_events();
let node_1_3rd_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
assert!(node_1_3rd_shutdown == node_1_2nd_shutdown);
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_3rd_shutdown);
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_3rd_shutdown);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_1_3rd_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_1_3rd_shutdown);
nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed);
let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id());
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
// We test that in case of peer committing upfront to a script, if it changes at closing, we refuse to sign
- let flags = InitFeatures::known();
+ let flags = channelmanager::provided_init_features();
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 1000000, 1000000, flags.clone(), flags.clone());
nodes[0].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[2].node.get_our_node_id()).unwrap();
let node_0_orig_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[2].node.get_our_node_id());
node_0_shutdown.scriptpubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script().to_p2sh();
// Test we enforce upfront_scriptpbukey if by providing a different one at closing that we warn
// the peer and ignore the message.
- nodes[2].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[2].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
assert!(regex::Regex::new(r"Got shutdown request with a scriptpubkey \([A-Fa-f0-9]+\) which did not match their previous scriptpubkey.")
.unwrap().is_match(&check_warn_msg!(nodes[2], nodes[0].node.get_our_node_id(), chan.2)));
// This allows nodes[2] to retry the shutdown message, which should get a response:
- nodes[2].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_orig_shutdown);
+ nodes[2].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_orig_shutdown);
get_event_msg!(nodes[2], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
// We test that in case of peer committing upfront to a script, if it doesn't change at closing, we sign
nodes[0].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[2].node.get_our_node_id()).unwrap();
let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[2].node.get_our_node_id());
// We test that in case of peer committing upfront to a script, if it oesn't change at closing, we sign
- nodes[2].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[2].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
let events = nodes[2].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
match events[0] {
}
// We test that if case of peer non-signaling we don't enforce committed script at channel opening
- let flags_no = InitFeatures::known().clear_upfront_shutdown_script();
+ let flags_no = channelmanager::provided_init_features().clear_upfront_shutdown_script();
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, flags_no, flags.clone());
nodes[0].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[1].node.get_our_node_id()).unwrap();
let node_1_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_1_shutdown);
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_1_shutdown);
check_added_monitors!(nodes[1], 1);
let events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id()).unwrap();
check_added_monitors!(nodes[1], 1);
let node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
let events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
match events[0] {
nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id()).unwrap();
check_added_monitors!(nodes[1], 1);
let node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
let events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 2);
match events[0] {
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Use a non-v0 segwit script supported by option_shutdown_anysegwit
- let node_features = InitFeatures::known().clear_shutdown_anysegwit();
+ let node_features = channelmanager::provided_init_features().clear_shutdown_anysegwit();
let anysegwit_shutdown_script = Builder::new()
.push_int(16)
.push_slice(&[0, 40])
// Check script when handling an accept_channel message
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel);
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
accept_channel.shutdown_scriptpubkey = Present(anysegwit_shutdown_script.clone());
nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), node_features, &accept_channel);
open_channel.shutdown_scriptpubkey = Present(Builder::new().push_int(0)
.push_slice(&[0, 0])
.into_script());
- nodes[0].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel);
+ nodes[0].node.handle_open_channel(&nodes[0].node.get_our_node_id(), channelmanager::provided_init_features(), &open_channel);
let events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &user_cfgs);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id()).unwrap();
check_added_monitors!(nodes[1], 1);
node_0_shutdown.scriptpubkey = Builder::new().push_int(0)
.push_slice(&[0; 20])
.into_script();
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
let events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 2);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &user_cfgs);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id()).unwrap();
check_added_monitors!(nodes[1], 1);
node_0_shutdown.scriptpubkey = Builder::new().push_int(16)
.push_slice(&[0, 0])
.into_script();
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
let events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 2);
let user_cfgs = [None, Some(config), None];
let chanmon_cfgs = create_chanmon_cfgs(3);
let mut node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
- node_cfgs[0].features = InitFeatures::known().clear_shutdown_anysegwit();
- node_cfgs[1].features = InitFeatures::known().clear_shutdown_anysegwit();
+ node_cfgs[0].features = channelmanager::provided_init_features().clear_shutdown_anysegwit();
+ node_cfgs[1].features = channelmanager::provided_init_features().clear_shutdown_anysegwit();
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &user_cfgs);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &user_cfgs);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
- let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id()).unwrap();
check_added_monitors!(nodes[1], 1);
node_0_shutdown.scriptpubkey = Builder::new().push_int(0)
.push_slice(&[0, 0])
.into_script();
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
assert_eq!(&check_warn_msg!(nodes[0], nodes[1].node.get_our_node_id(), chan.2),
"Got a nonstandard scriptpubkey (00020000) from remote peer");
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_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
+ let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
send_payment(&nodes[0], &[&nodes[1]], 8_000_000);
nodes[0].node.close_channel(&chan_id, &nodes[1].node.get_our_node_id()).unwrap();
let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_1_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_1_shutdown);
{
// Now we set nodes[1] to require a relatively high feerate for closing. This should result
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 chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
if high_initiator_fee {
// If high_initiator_fee is set, set nodes[0]'s feerate significantly higher. This
nodes[0].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[1].node.get_our_node_id()).unwrap();
let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_1_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_1_shutdown);
let mut node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id());
node_0_closing_signed.fee_range = None;
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 chan = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let chan_id = OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id();
nodes[0].node.close_channel_with_target_feerate(&chan_id, &nodes[1].node.get_our_node_id(), 253 * 10).unwrap();
nodes[1].node.close_channel_with_target_feerate(&chan_id, &nodes[0].node.get_our_node_id(), 253 * 5).unwrap();
let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
- nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
- nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_1_shutdown);
+ nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown);
+ nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_1_shutdown);
let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id());
nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_closing_signed);
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
-use chain::keysinterface::{KeysInterface, Sign};
+use chain::keysinterface::KeysInterface;
use super::utils;
use ln::msgs::DecodeError;
use util::chacha20poly1305rfc::ChaChaPolyWriteAdapter;
///
/// Errors if less than two hops are provided or if `node_pk`(s) are invalid.
// TODO: make all payloads the same size with padding + add dummy hops
- pub fn new<Signer: Sign, K: KeysInterface, T: secp256k1::Signing + secp256k1::Verification>
+ pub fn new<K: KeysInterface, T: secp256k1::Signing + secp256k1::Verification>
(node_pks: &[PublicKey], keys_manager: &K, secp_ctx: &Secp256k1<T>) -> Result<Self, ()>
{
if node_pks.len() < 2 { return Err(()) }
}
for idx in 0..num_messengers - 1 {
let i = idx as usize;
- let mut features = InitFeatures::known();
+ let mut features = InitFeatures::empty();
features.set_onion_messages_optional();
let init_msg = msgs::Init { features, remote_network_address: None };
- nodes[i].messenger.peer_connected(&nodes[i + 1].get_node_pk(), &init_msg.clone());
- nodes[i + 1].messenger.peer_connected(&nodes[i].get_node_pk(), &init_msg.clone());
+ nodes[i].messenger.peer_connected(&nodes[i + 1].get_node_pk(), &init_msg.clone()).unwrap();
+ nodes[i + 1].messenger.peer_connected(&nodes[i].get_node_pk(), &init_msg.clone()).unwrap();
}
nodes
}
let nodes = create_nodes(5);
let secp_ctx = Secp256k1::new();
- let blinded_route = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[3].get_node_pk(), nodes[4].get_node_pk()], &*nodes[4].keys_manager, &secp_ctx).unwrap();
+ let blinded_route = BlindedRoute::new(&[nodes[3].get_node_pk(), nodes[4].get_node_pk()], &*nodes[4].keys_manager, &secp_ctx).unwrap();
nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::BlindedRoute(blinded_route), None).unwrap();
pass_along_path(&nodes, None);
let nodes = create_nodes(4);
let secp_ctx = Secp256k1::new();
- let blinded_route = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
+ let blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), None).unwrap();
pass_along_path(&nodes, None);
// 0 hops
let secp_ctx = Secp256k1::new();
- let mut blinded_route = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
+ let mut blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
blinded_route.blinded_hops.clear();
let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), None).unwrap_err();
assert_eq!(err, SendError::TooFewBlindedHops);
// 1 hop
- let mut blinded_route = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
+ let mut blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
blinded_route.blinded_hops.remove(0);
assert_eq!(blinded_route.blinded_hops.len(), 1);
let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), None).unwrap_err();
let secp_ctx = Secp256k1::new();
// Destination::Node
- let reply_path = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
+ let reply_path = BlindedRoute::new(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::Node(nodes[3].get_node_pk()), Some(reply_path)).unwrap();
pass_along_path(&nodes, None);
// Make sure the last node successfully decoded the reply path.
format!("Received an onion message with path_id: None and reply_path").to_string(), 1);
// Destination::BlindedRoute
- let blinded_route = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
- let reply_path = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
+ let blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
+ let reply_path = BlindedRoute::new(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), Some(reply_path)).unwrap();
pass_along_path(&nodes, None);
use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};
use chain::keysinterface::{InMemorySigner, KeysInterface, KeysManager, Recipient, Sign};
+use ln::features::{InitFeatures, NodeFeatures};
use ln::msgs::{self, OnionMessageHandler};
use ln::onion_utils;
use super::blinded_route::{BlindedRoute, ForwardTlvs, ReceiveTlvs};
/// // Create a blinded route to yourself, for someone to send an onion message to.
/// # let your_node_id = hop_node_id1;
/// let hops = [hop_node_id3, hop_node_id4, your_node_id];
-/// let blinded_route = BlindedRoute::new::<InMemorySigner, _, _>(&hops, &keys_manager, &secp_ctx).unwrap();
+/// let blinded_route = BlindedRoute::new(&hops, &keys_manager, &secp_ctx).unwrap();
///
/// // Send an empty onion message to a blinded route.
/// # let intermediate_hops = [hop_node_id1, hop_node_id2];
};
}
- fn peer_connected(&self, their_node_id: &PublicKey, init: &msgs::Init) {
+ fn peer_connected(&self, their_node_id: &PublicKey, init: &msgs::Init) -> Result<(), ()> {
if init.features.supports_onion_messages() {
let mut peers = self.pending_messages.lock().unwrap();
peers.insert(their_node_id.clone(), VecDeque::new());
}
+ Ok(())
}
fn peer_disconnected(&self, their_node_id: &PublicKey, _no_connection_possible: bool) {
let mut pending_msgs = self.pending_messages.lock().unwrap();
pending_msgs.remove(their_node_id);
}
+
+ fn provided_node_features(&self) -> NodeFeatures {
+ let mut features = NodeFeatures::empty();
+ features.set_onion_messages_optional();
+ features
+ }
+
+ fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures {
+ let mut features = InitFeatures::empty();
+ features.set_onion_messages_optional();
+ features
+ }
}
impl<Signer: Sign, K: Deref, L: Deref> OnionMessageProvider for OnionMessenger<Signer, K, L>
/// Useful for simplifying the parameters of [`SimpleArcChannelManager`] and
/// [`SimpleArcPeerManager`]. See their docs for more details.
///
-///[`SimpleArcChannelManager`]: crate::ln::channelmanager::SimpleArcChannelManager
-///[`SimpleArcPeerManager`]: crate::ln::peer_handler::SimpleArcPeerManager
+/// (C-not exported) as `Arc`s don't make sense in bindings.
+///
+/// [`SimpleArcChannelManager`]: crate::ln::channelmanager::SimpleArcChannelManager
+/// [`SimpleArcPeerManager`]: crate::ln::peer_handler::SimpleArcPeerManager
pub type SimpleArcOnionMessenger<L> = OnionMessenger<InMemorySigner, Arc<KeysManager>, Arc<L>>;
/// Useful for simplifying the parameters of [`SimpleRefChannelManager`] and
/// [`SimpleRefPeerManager`]. See their docs for more details.
///
-///[`SimpleRefChannelManager`]: crate::ln::channelmanager::SimpleRefChannelManager
-///[`SimpleRefPeerManager`]: crate::ln::peer_handler::SimpleRefPeerManager
+/// (C-not exported) as general type aliases don't make sense in bindings.
+///
+/// [`SimpleRefChannelManager`]: crate::ln::channelmanager::SimpleRefChannelManager
+/// [`SimpleRefPeerManager`]: crate::ln::peer_handler::SimpleRefPeerManager
pub type SimpleRefOnionMessenger<'a, 'b, L> = OnionMessenger<InMemorySigner, &'a KeysManager, &'b L>;
/// Construct onion packet payloads and keys for sending an onion message along the given
use chain;
use chain::Access;
use ln::chan_utils::make_funding_redeemscript;
-use ln::features::{ChannelFeatures, NodeFeatures};
+use ln::features::{ChannelFeatures, NodeFeatures, InitFeatures};
use ln::msgs::{DecodeError, ErrorAction, Init, LightningError, RoutingMessageHandler, NetAddress, MAX_VALUE_MSAT};
use ln::msgs::{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, GossipTimestampFilter};
use ln::msgs::{QueryChannelRange, ReplyChannelRange, QueryShortChannelIds, ReplyShortChannelIdsEnd};
{
network_graph: G,
chain_access: Option<C>,
+ #[cfg(feature = "std")]
full_syncs_requested: AtomicUsize,
pending_events: Mutex<Vec<MessageSendEvent>>,
logger: L,
pub fn new(network_graph: G, chain_access: Option<C>, logger: L) -> Self {
P2PGossipSync {
network_graph,
+ #[cfg(feature = "std")]
full_syncs_requested: AtomicUsize::new(0),
chain_access,
pending_events: Mutex::new(vec![]),
&self.network_graph
}
+ #[cfg(feature = "std")]
/// Returns true when a full routing table sync should be performed with a peer.
fn should_request_full_sync(&self, _node_id: &PublicKey) -> bool {
//TODO: Determine whether to request a full sync based on the network map.
/// to request gossip messages for each channel. The sync is considered complete
/// when the final reply_scids_end message is received, though we are not
/// tracking this directly.
- fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &Init) {
+ fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &Init) -> Result<(), ()> {
// We will only perform a sync with peers that support gossip_queries.
if !init_msg.features.supports_gossip_queries() {
- return ();
+ // Don't disconnect peers for not supporting gossip queries. We may wish to have
+ // channels with peers even without being able to exchange gossip.
+ return Ok(());
}
// The lightning network's gossip sync system is completely broken in numerous ways.
// `gossip_timestamp_filter`, with the filter time set either two weeks ago or an hour ago.
//
// For no-std builds, we bury our head in the sand and do a full sync on each connection.
- let should_request_full_sync = self.should_request_full_sync(&their_node_id);
#[allow(unused_mut, unused_assignments)]
let mut gossip_start_time = 0;
#[cfg(feature = "std")]
{
gossip_start_time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs();
- if should_request_full_sync {
+ if self.should_request_full_sync(&their_node_id) {
gossip_start_time -= 60 * 60 * 24 * 7 * 2; // 2 weeks ago
} else {
gossip_start_time -= 60 * 60; // an hour ago
timestamp_range: u32::max_value(),
},
});
+ Ok(())
}
fn handle_reply_channel_range(&self, _their_node_id: &PublicKey, _msg: ReplyChannelRange) -> Result<(), LightningError> {
action: ErrorAction::IgnoreError,
})
}
+
+ fn provided_node_features(&self) -> NodeFeatures {
+ let mut features = NodeFeatures::empty();
+ features.set_gossip_queries_optional();
+ features
+ }
+
+ fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures {
+ let mut features = InitFeatures::empty();
+ features.set_gossip_queries_optional();
+ features
+ }
}
impl<G: Deref<Target=NetworkGraph<L>>, C: Deref, L: Deref> MessageSendEventsProvider for P2PGossipSync<G, C, L>
#[cfg(test)]
mod tests {
use chain;
+ use ln::channelmanager;
use ln::chan_utils::make_funding_redeemscript;
use ln::PaymentHash;
- use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
+ use ln::features::InitFeatures;
use routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate, NodeAlias, MAX_EXCESS_BYTES_FOR_RELAY, NodeId, RoutingFees, ChannelUpdateInfo, ChannelInfo, NodeAnnouncementInfo, NodeInfo};
- use ln::msgs::{Init, RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
+ use ln::msgs::{RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
UnsignedChannelAnnouncement, ChannelAnnouncement, UnsignedChannelUpdate, ChannelUpdate,
ReplyChannelRange, QueryChannelRange, QueryShortChannelIds, MAX_VALUE_MSAT};
use util::test_utils;
}
#[test]
+ #[cfg(feature = "std")]
fn request_full_sync_finite_times() {
let network_graph = create_network_graph();
let (secp_ctx, gossip_sync) = create_gossip_sync(&network_graph);
fn get_signed_node_announcement<F: Fn(&mut UnsignedNodeAnnouncement)>(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> NodeAnnouncement {
let node_id = PublicKey::from_secret_key(&secp_ctx, node_key);
let mut unsigned_announcement = UnsignedNodeAnnouncement {
- features: NodeFeatures::known(),
+ features: channelmanager::provided_node_features(),
timestamp: 100,
node_id: node_id,
rgb: [0; 3],
let node_2_btckey = &SecretKey::from_slice(&[39; 32]).unwrap();
let mut unsigned_announcement = UnsignedChannelAnnouncement {
- features: ChannelFeatures::known(),
+ features: channelmanager::provided_channel_features(),
chain_hash: genesis_block(Network::Testnet).header.block_hash(),
short_channel_id: 0,
node_id_1,
network_graph.handle_event(&Event::PaymentPathFailed {
payment_id: None,
payment_hash: PaymentHash([0; 32]),
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: true,
path: vec![],
network_update: Some(NetworkUpdate::ChannelUpdateMessage {
network_graph.handle_event(&Event::PaymentPathFailed {
payment_id: None,
payment_hash: PaymentHash([0; 32]),
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: true,
path: vec![],
network_update: Some(NetworkUpdate::ChannelFailure {
network_graph.handle_event(&Event::PaymentPathFailed {
payment_id: None,
payment_hash: PaymentHash([0; 32]),
- rejected_by_dest: false,
+ payment_failed_permanently: false,
all_paths_failed: true,
path: vec![],
network_update: Some(NetworkUpdate::ChannelFailure {
#[cfg(feature = "std")]
fn calling_sync_routing_table() {
use std::time::{SystemTime, UNIX_EPOCH};
+ use ln::msgs::Init;
let network_graph = create_network_graph();
let (secp_ctx, gossip_sync) = create_gossip_sync(&network_graph);
// It should ignore if gossip_queries feature is not enabled
{
- let init_msg = Init { features: InitFeatures::known().clear_gossip_queries(), remote_network_address: None };
- gossip_sync.peer_connected(&node_id_1, &init_msg);
+ let init_msg = Init { features: InitFeatures::empty(), remote_network_address: None };
+ gossip_sync.peer_connected(&node_id_1, &init_msg).unwrap();
let events = gossip_sync.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 0);
}
// It should send a gossip_timestamp_filter with the correct information
{
- let init_msg = Init { features: InitFeatures::known(), remote_network_address: None };
- gossip_sync.peer_connected(&node_id_1, &init_msg);
+ let mut features = InitFeatures::empty();
+ features.set_gossip_queries_optional();
+ let init_msg = Init { features, remote_network_address: None };
+ gossip_sync.peer_connected(&node_id_1, &init_msg).unwrap();
let events = gossip_sync.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
match &events[0] {
// 2. Test encoding/decoding of ChannelInfo
// Check we can encode/decode ChannelInfo without ChannelUpdateInfo fields present.
let chan_info_none_updates = ChannelInfo {
- features: ChannelFeatures::known(),
+ features: channelmanager::provided_channel_features(),
node_one: NodeId::from_pubkey(&nodes[0].node.get_our_node_id()),
one_to_two: None,
node_two: NodeId::from_pubkey(&nodes[1].node.get_our_node_id()),
// Check we can encode/decode ChannelInfo with ChannelUpdateInfo fields present.
let chan_info_some_updates = ChannelInfo {
- features: ChannelFeatures::known(),
+ features: channelmanager::provided_channel_features(),
node_one: NodeId::from_pubkey(&nodes[0].node.get_our_node_id()),
one_to_two: Some(chan_update_info.clone()),
node_two: NodeId::from_pubkey(&nodes[1].node.get_our_node_id()),
// 1. Check we can read a valid NodeAnnouncementInfo and fail on an invalid one
let valid_netaddr = ::ln::msgs::NetAddress::Hostname { hostname: ::util::ser::Hostname::try_from("A".to_string()).unwrap(), port: 1234 };
let valid_node_ann_info = NodeAnnouncementInfo {
- features: NodeFeatures::known(),
+ features: channelmanager::provided_node_features(),
last_update: 0,
rgb: [0u8; 3],
alias: NodeAlias([0u8; 32]),
use routing::scoring::{ChannelUsage, Score, ProbabilisticScorer, ProbabilisticScoringParameters};
use chain::transaction::OutPoint;
use chain::keysinterface::KeysInterface;
- use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
+ use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
use ln::msgs::{ErrorAction, LightningError, UnsignedChannelAnnouncement, ChannelAnnouncement, RoutingMessageHandler,
NodeAnnouncement, UnsignedNodeAnnouncement, ChannelUpdate, UnsignedChannelUpdate, MAX_VALUE_MSAT};
use ln::channelmanager;
fn htlc_minimum_overpay_test() {
let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
- let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(InvoiceFeatures::known());
+ let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features());
let scorer = test_utils::TestScorer::with_penalty(0);
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
let random_seed_bytes = keys_manager.get_secure_random_bytes();
// Disable nodes 1, 2, and 8 by requiring unknown feature bits
- let mut unknown_features = NodeFeatures::known();
+ let mut unknown_features = NodeFeatures::empty();
unknown_features.set_unknown_feature_required();
add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[0], unknown_features.clone(), 1);
add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[1], unknown_features.clone(), 1);
let scorer = test_utils::TestScorer::with_penalty(0);
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
- let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(InvoiceFeatures::known());
+ let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features());
// We will use a simple single-path route from
// our node to node2 via node0: channels {1, 3}.
let scorer = test_utils::TestScorer::with_penalty(0);
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
- let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(InvoiceFeatures::known());
+ let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(channelmanager::provided_invoice_features());
// Path via {node7, node2, node4} is channels {12, 13, 6, 11}.
// {12, 13, 11} have the capacities of 100, {6} has a capacity of 50.
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
let payment_params = PaymentParameters::from_node_id(nodes[2])
- .with_features(InvoiceFeatures::known());
+ .with_features(channelmanager::provided_invoice_features());
// We need a route consisting of 3 paths:
// From our node to node2 via node0, node7, node1 (three paths one hop each).
let scorer = test_utils::TestScorer::with_penalty(0);
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
- let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(InvoiceFeatures::known());
+ let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(channelmanager::provided_invoice_features());
// We need a route consisting of 3 paths:
// From our node to node3 via {node0, node2}, {node7, node2, node4} and {node7, node2}.
let scorer = test_utils::TestScorer::with_penalty(0);
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
- let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(InvoiceFeatures::known());
+ let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(channelmanager::provided_invoice_features());
// This test checks that if we have two cheaper paths and one more expensive path,
// so that liquidity-wise any 2 of 3 combination is sufficient,
let scorer = test_utils::TestScorer::with_penalty(0);
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
- let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(InvoiceFeatures::known());
+ let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(channelmanager::provided_invoice_features());
// We need a route consisting of 2 paths:
// From our node to node3 via {node0, node2} and {node7, node2, node4}.
let scorer = test_utils::TestScorer::with_penalty(0);
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
- let payment_params = PaymentParameters::from_node_id(PublicKey::from_slice(&[02; 33]).unwrap()).with_features(InvoiceFeatures::known())
+ let payment_params = PaymentParameters::from_node_id(PublicKey::from_slice(&[02; 33]).unwrap()).with_features(channelmanager::provided_invoice_features())
.with_route_hints(vec![RouteHint(vec![RouteHintHop {
src_node_id: nodes[2],
short_channel_id: 42,
let scorer = test_utils::TestScorer::with_penalty(0);
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
- let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(InvoiceFeatures::known())
+ let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features())
.with_max_channel_saturation_power_of_half(0);
// We need a route consisting of 3 paths:
let scorer = test_utils::TestScorer::with_penalty(0);
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
- let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(InvoiceFeatures::known());
+ let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features());
// We modify the graph to set the htlc_minimum of channel 2 and 4 as needed - channel 2
// gets an htlc_maximum_msat of 80_000 and channel 4 an htlc_minimum_msat of 90_000. We
assert_eq!(route.paths[0][1].short_channel_id, 13);
assert_eq!(route.paths[0][1].fee_msat, 90_000);
assert_eq!(route.paths[0][1].cltv_expiry_delta, 42);
- assert_eq!(route.paths[0][1].node_features.le_flags(), InvoiceFeatures::known().le_flags());
+ assert_eq!(route.paths[0][1].node_features.le_flags(), channelmanager::provided_invoice_features().le_flags());
assert_eq!(route.paths[0][1].channel_features.le_flags(), &id_to_feature_flags(13));
}
}
let logger = Arc::new(test_utils::TestLogger::new());
let network_graph = NetworkGraph::new(genesis_hash, Arc::clone(&logger));
let scorer = test_utils::TestScorer::with_penalty(0);
- let payment_params = PaymentParameters::from_node_id(nodes[0]).with_features(InvoiceFeatures::known());
+ let payment_params = PaymentParameters::from_node_id(nodes[0]).with_features(channelmanager::provided_invoice_features());
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
{
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[
- &get_channel_details(Some(3), nodes[0], InitFeatures::known(), 200_000),
- &get_channel_details(Some(2), nodes[0], InitFeatures::known(), 10_000),
+ &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(), 200_000),
+ &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(), 10_000),
]), 100_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].len(), 1);
}
{
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[
- &get_channel_details(Some(3), nodes[0], InitFeatures::known(), 50_000),
- &get_channel_details(Some(2), nodes[0], InitFeatures::known(), 50_000),
+ &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(), 50_000),
+ &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(), 50_000),
]), 100_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 2);
assert_eq!(route.paths[0].len(), 1);
// smallest of them, avoiding further fragmenting our available outbound balance to
// this node.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[
- &get_channel_details(Some(2), nodes[0], InitFeatures::known(), 50_000),
- &get_channel_details(Some(3), nodes[0], InitFeatures::known(), 50_000),
- &get_channel_details(Some(5), nodes[0], InitFeatures::known(), 50_000),
- &get_channel_details(Some(6), nodes[0], InitFeatures::known(), 300_000),
- &get_channel_details(Some(7), nodes[0], InitFeatures::known(), 50_000),
- &get_channel_details(Some(8), nodes[0], InitFeatures::known(), 50_000),
- &get_channel_details(Some(9), nodes[0], InitFeatures::known(), 50_000),
- &get_channel_details(Some(4), nodes[0], InitFeatures::known(), 1_000_000),
+ &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(), 50_000),
+ &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(), 50_000),
+ &get_channel_details(Some(5), nodes[0], channelmanager::provided_init_features(), 50_000),
+ &get_channel_details(Some(6), nodes[0], channelmanager::provided_init_features(), 300_000),
+ &get_channel_details(Some(7), nodes[0], channelmanager::provided_init_features(), 50_000),
+ &get_channel_details(Some(8), nodes[0], channelmanager::provided_init_features(), 50_000),
+ &get_channel_details(Some(9), nodes[0], channelmanager::provided_init_features(), 50_000),
+ &get_channel_details(Some(4), nodes[0], channelmanager::provided_init_features(), 1_000_000),
]), 100_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].len(), 1);
excess_data: Vec::new()
});
- let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(InvoiceFeatures::known());
+ let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features());
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
// 100,000 sats is less than the available liquidity on each channel, set above.
let src = &PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
seed = seed.overflowing_mul(0xdeadbeef).0;
let dst = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
- let payment_params = PaymentParameters::from_node_id(dst).with_features(InvoiceFeatures::known());
+ let payment_params = PaymentParameters::from_node_id(dst).with_features(channelmanager::provided_invoice_features());
let amt = seed as u64 % 200_000_000;
let params = ProbabilisticScoringParameters::default();
let scorer = ProbabilisticScorer::new(params, &graph, &logger);
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
use chain::transaction::OutPoint;
use chain::keysinterface::{KeysManager,KeysInterface};
- use ln::channelmanager::{ChannelCounterparty, ChannelDetails};
+ use ln::channelmanager::{self, ChannelCounterparty, ChannelDetails};
use ln::features::{InitFeatures, InvoiceFeatures};
use routing::gossip::NetworkGraph;
use routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringParameters};
ChannelDetails {
channel_id: [0; 32],
counterparty: ChannelCounterparty {
- features: InitFeatures::known(),
+ features: channelmanager::provided_init_features(),
node_id,
unspendable_punishment_reserve: 0,
forwarding_info: None,
let logger = DummyLogger {};
let network_graph = read_network_graph(&logger);
let scorer = FixedPenaltyScorer::with_penalty(0);
- generate_routes(bench, &network_graph, scorer, InvoiceFeatures::known());
+ generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features());
}
#[bench]
let network_graph = read_network_graph(&logger);
let params = ProbabilisticScoringParameters::default();
let scorer = ProbabilisticScorer::new(params, &network_graph, &logger);
- generate_routes(bench, &network_graph, scorer, InvoiceFeatures::known());
+ generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features());
}
fn generate_routes<S: Score>(
/// use the Persister to persist it.
pub trait WriteableScore<'a>: LockableScore<'a> + Writeable {}
+#[cfg(not(c_bindings))]
impl<'a, T> WriteableScore<'a> for T where T: LockableScore<'a> + Writeable {}
/// (C-not exported)
use util::time::Time;
use util::time::tests::SinceEpoch;
- use ln::features::{ChannelFeatures, NodeFeatures};
+ use ln::channelmanager;
use ln::msgs::{ChannelAnnouncement, ChannelUpdate, UnsignedChannelAnnouncement, UnsignedChannelUpdate};
use routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId};
use routing::router::RouteHop;
let node_2_secret = &SecretKey::from_slice(&[40; 32]).unwrap();
let secp_ctx = Secp256k1::new();
let unsigned_announcement = UnsignedChannelAnnouncement {
- features: ChannelFeatures::known(),
+ features: channelmanager::provided_channel_features(),
chain_hash: genesis_hash,
short_channel_id,
node_id_1: PublicKey::from_secret_key(&secp_ctx, &node_1_key),
vec![
RouteHop {
pubkey: source_pubkey(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: 41,
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: 1,
cltv_expiry_delta: 18,
},
RouteHop {
pubkey: target_pubkey(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: 42,
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: 2,
cltv_expiry_delta: 18,
},
RouteHop {
pubkey: recipient_pubkey(),
- node_features: NodeFeatures::known(),
+ node_features: channelmanager::provided_node_features(),
short_channel_id: 43,
- channel_features: ChannelFeatures::known(),
+ channel_features: channelmanager::provided_channel_features(),
fee_msat: amount_msat,
cltv_expiry_delta: 18,
},
self.mac.raw_result(out_tag);
}
+ pub fn encrypt_full_message_in_place(&mut self, input_output: &mut [u8], out_tag: &mut [u8]) {
+ self.encrypt_in_place(input_output);
+ self.finish_and_get_tag(out_tag);
+ }
+
// Encrypt `input_output` in-place. To finish and calculate the tag, use `finish_and_get_tag`
// below.
pub(super) fn encrypt_in_place(&mut self, input_output: &mut [u8]) {
self.finished = true;
}
+ pub fn encrypt_full_message_in_place(&mut self, input_output: &mut [u8], out_tag: &mut [u8]) {
+ self.encrypt_in_place(input_output);
+ self.finish_and_get_tag(out_tag);
+ }
+
pub(super) fn encrypt_in_place(&mut self, _input_output: &mut [u8]) {
assert!(self.finished == false);
}
/// to such payments may be sustantial if there are many dust HTLCs present when the
/// channel is force-closed.
///
+ /// The dust threshold for each HTLC is based on the `dust_limit_satoshis` for each party in a
+ /// channel negotiated throughout the channel open process, along with the fees required to have
+ /// a broadcastable HTLC spending transaction. When a channel supports anchor outputs
+ /// (specifically the zero fee HTLC transaction variant), this threshold no longer takes into
+ /// account the HTLC transaction fee as it is zero.
+ ///
/// This limit is applied for sent, forwarded, and received HTLCs and limits the total
/// exposure across all three types per-channel. Setting this too low may prevent the
/// sending or receipt of low-value HTLCs on high-traffic nodes, and this limit is very
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&this_htlc, self.opt_anchors(), &keys);
- let sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, this_htlc.amount_msat / 1000, EcdsaSighashType::All).unwrap()[..]);
+ let sighash_type = if self.opt_anchors() {
+ EcdsaSighashType::SinglePlusAnyoneCanPay
+ } else {
+ EcdsaSighashType::All
+ };
+ let sighash = hash_to_message!(
+ &sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(
+ 0, &htlc_redeemscript, this_htlc.amount_msat / 1000, sighash_type,
+ ).unwrap()[..]
+ );
secp_ctx.verify_ecdsa(&sighash, sig, &keys.countersignatory_htlc_key).unwrap();
}
/// Indicates the payment was rejected for some reason by the recipient. This implies that
/// the payment has failed, not just the route in question. If this is not set, you may
/// retry the payment via a different route.
- rejected_by_dest: bool,
+ payment_failed_permanently: bool,
/// Any failure information conveyed via the Onion return packet by a node along the failed
/// payment route.
///
});
},
&Event::PaymentPathFailed {
- ref payment_id, ref payment_hash, ref rejected_by_dest, ref network_update,
+ ref payment_id, ref payment_hash, ref payment_failed_permanently, ref network_update,
ref all_paths_failed, ref path, ref short_channel_id, ref retry,
#[cfg(test)]
ref error_code,
write_tlv_fields!(writer, {
(0, payment_hash, required),
(1, network_update, option),
- (2, rejected_by_dest, required),
+ (2, payment_failed_permanently, required),
(3, all_paths_failed, required),
(5, path, vec_type),
(7, short_channel_id, option),
#[cfg(test)]
let error_data = Readable::read(reader)?;
let mut payment_hash = PaymentHash([0; 32]);
- let mut rejected_by_dest = false;
+ let mut payment_failed_permanently = false;
let mut network_update = None;
let mut all_paths_failed = Some(true);
let mut path: Option<Vec<RouteHop>> = Some(vec![]);
read_tlv_fields!(reader, {
(0, payment_hash, required),
(1, network_update, ignorable),
- (2, rejected_by_dest, required),
+ (2, payment_failed_permanently, required),
(3, all_paths_failed, option),
(5, path, vec_type),
(7, short_channel_id, option),
Ok(Some(Event::PaymentPathFailed {
payment_id,
payment_hash,
- rejected_by_dest,
+ payment_failed_permanently,
network_update,
all_paths_failed: all_paths_failed.unwrap(),
path: path.unwrap(),
(4, path, vec_type),
(6, short_channel_id, option),
});
- Ok(Some(Event::ProbeFailed{
+ Ok(Some(Event::ProbeFailed {
payment_id,
payment_hash,
path: path.unwrap(),
};
f()
},
+ 25u8 => {
+ let f = || {
+ let mut prev_channel_id = [0; 32];
+ let mut failed_next_destination_opt = None;
+ read_tlv_fields!(reader, {
+ (0, prev_channel_id, required),
+ (2, failed_next_destination_opt, ignorable),
+ });
+ if let Some(failed_next_destination) = failed_next_destination_opt {
+ Ok(Some(Event::HTLCHandlingFailed {
+ prev_channel_id,
+ failed_next_destination,
+ }))
+ } else {
+ // If we fail to read a `failed_next_destination` assume it's because
+ // `MaybeReadable::read` returned `Ok(None)`, though it's also possible we
+ // were simply missing the field.
+ Ok(None)
+ }
+ };
+ f()
+ },
// Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
// Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt
// reads.
/// The message which should be sent.
msg: msgs::ChannelReestablish,
},
+ /// Used to send a channel_announcement and channel_update to a specific peer, likely on
+ /// initial connection to ensure our peers know about our channels.
+ SendChannelAnnouncement {
+ /// The node_id of the node which should receive this message
+ node_id: PublicKey,
+ /// The channel_announcement which should be sent.
+ msg: msgs::ChannelAnnouncement,
+ /// The followup channel_update which should be sent.
+ update_msg: msgs::ChannelUpdate,
+ },
/// Used to indicate that a channel_announcement and channel_update should be broadcast to all
/// peers (except the peer with node_id either msg.contents.node_id_1 or msg.contents.node_id_2).
///
- /// Note that after doing so, you very likely (unless you did so very recently) want to call
- /// ChannelManager::broadcast_node_announcement to trigger a BroadcastNodeAnnouncement event.
- /// This ensures that any nodes which see our channel_announcement also have a relevant
+ /// Note that after doing so, you very likely (unless you did so very recently) want to
+ /// broadcast a node_announcement (e.g. via [`PeerManager::broadcast_node_announcement`]). This
+ /// ensures that any nodes which see our channel_announcement also have a relevant
/// node_announcement, including relevant feature flags which may be important for routing
/// through or to us.
+ ///
+ /// [`PeerManager::broadcast_node_announcement`]: crate::ln::peer_handler::PeerManager::broadcast_node_announcement
BroadcastChannelAnnouncement {
/// The channel_announcement which should be sent.
msg: msgs::ChannelAnnouncement,
/// The followup channel_update which should be sent.
update_msg: msgs::ChannelUpdate,
},
- /// Used to indicate that a node_announcement should be broadcast to all peers.
- BroadcastNodeAnnouncement {
- /// The node_announcement which should be sent.
- msg: msgs::NodeAnnouncement,
- },
/// Used to indicate that a channel_update should be broadcast to all peers.
BroadcastChannelUpdate {
/// The channel_update which should be sent.
///
/// # Requirements
///
-/// See [`process_pending_events`] for requirements around event processing.
-///
/// When using this trait, [`process_pending_events`] will call [`handle_event`] for each pending
-/// event since the last invocation. The handler must either act upon the event immediately
-/// or preserve it for later handling.
+/// event since the last invocation.
+///
+/// In order to ensure no [`Event`]s are lost, implementors of this trait will persist [`Event`]s
+/// and replay any unhandled events on startup. An [`Event`] is considered handled when
+/// [`process_pending_events`] returns, thus handlers MUST fully handle [`Event`]s and persist any
+/// relevant changes to disk *before* returning.
+///
+/// Further, because an application may crash between an [`Event`] being handled and the
+/// implementor of this trait being re-serialized, [`Event`] handling must be idempotent - in
+/// effect, [`Event`]s may be replayed.
///
/// Note, handlers may call back into the provider and thus deadlocking must be avoided. Be sure to
/// consult the provider's documentation on the implication of processing events and how a handler
pub trait EventsProvider {
/// Processes any events generated since the last call using the given event handler.
///
- /// Subsequent calls must only process new events. However, handlers must be capable of handling
- /// duplicate events across process restarts. This may occur if the provider was recovered from
- /// an old state (i.e., it hadn't been successfully persisted after processing pending events).
+ /// See the trait-level documentation for requirements.
fn process_pending_events<H: Deref>(&self, handler: H) where H::Target: EventHandler;
}
use bitcoin::secp256k1::PublicKey;
use routing::router::Route;
-use ln::chan_utils::HTLCType;
+use ln::chan_utils::HTLCClaim;
use util::logger::DebugBytes;
pub(crate) struct DebugPubKey<'a>(pub &'a PublicKey);
impl<'a> core::fmt::Display for DebugTx<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
if self.0.input.len() >= 1 && self.0.input.iter().any(|i| !i.witness.is_empty()) {
- if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 71 &&
- (self.0.input[0].sequence.0 >> 8*3) as u8 == 0x80 {
+ let first_input = &self.0.input[0];
+ let witness_script_len = first_input.witness.last().unwrap_or(&[]).len();
+ if self.0.input.len() == 1 && witness_script_len == 71 &&
+ (first_input.sequence.0 >> 8*3) as u8 == 0x80 {
write!(f, "commitment tx ")?;
- } else if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 71 {
+ } else if self.0.input.len() == 1 && witness_script_len == 71 {
write!(f, "closing tx ")?;
- } else if self.0.input.len() == 1 && HTLCType::scriptlen_to_htlctype(self.0.input[0].witness.last().unwrap().len()) == Some(HTLCType::OfferedHTLC) &&
- self.0.input[0].witness.len() == 5 {
+ } else if self.0.input.len() == 1 && HTLCClaim::from_witness(&first_input.witness) == Some(HTLCClaim::OfferedTimeout) {
write!(f, "HTLC-timeout tx ")?;
- } else if self.0.input.len() == 1 && HTLCType::scriptlen_to_htlctype(self.0.input[0].witness.last().unwrap().len()) == Some(HTLCType::AcceptedHTLC) &&
- self.0.input[0].witness.len() == 5 {
+ } else if self.0.input.len() == 1 && HTLCClaim::from_witness(&first_input.witness) == Some(HTLCClaim::AcceptedPreimage) {
write!(f, "HTLC-success tx ")?;
} else {
+ let mut num_preimage = 0;
+ let mut num_timeout = 0;
+ let mut num_revoked = 0;
for inp in &self.0.input {
- if !inp.witness.is_empty() {
- if HTLCType::scriptlen_to_htlctype(inp.witness.last().unwrap().len()) == Some(HTLCType::OfferedHTLC) { write!(f, "preimage-")?; break }
- else if HTLCType::scriptlen_to_htlctype(inp.witness.last().unwrap().len()) == Some(HTLCType::AcceptedHTLC) { write!(f, "timeout-")?; break }
+ let htlc_claim = HTLCClaim::from_witness(&inp.witness);
+ match htlc_claim {
+ Some(HTLCClaim::AcceptedPreimage)|Some(HTLCClaim::OfferedPreimage) => num_preimage += 1,
+ Some(HTLCClaim::AcceptedTimeout)|Some(HTLCClaim::OfferedTimeout) => num_timeout += 1,
+ Some(HTLCClaim::Revocation) => num_revoked += 1,
+ None => continue,
}
}
- write!(f, "tx ")?;
+ if num_preimage > 0 || num_timeout > 0 || num_revoked > 0 {
+ write!(f, "HTLC claim tx ({} preimage, {} timeout, {} revoked)",
+ num_preimage, num_timeout, num_revoked)?;
+ }
}
} else {
debug_assert!(false, "We should never generate unknown transaction types");
pub mod message_signing;
pub mod invoice;
pub mod persist;
+pub mod wakers;
pub(crate) mod atomic_counter;
pub(crate) mod byte_utils;
}
/// Trait that handles persisting a [`ChannelManager`], [`NetworkGraph`], and [`WriteableScore`] to disk.
-pub trait Persister<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref, S>
+pub trait Persister<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref, S: WriteableScore<'a>>
where M::Target: 'static + chain::Watch<Signer>,
T::Target: 'static + BroadcasterInterface,
K::Target: 'static + KeysInterface<Signer = Signer>,
F::Target: 'static + FeeEstimator,
L::Target: 'static + Logger,
- S: WriteableScore<'a>,
{
/// Persist the given ['ChannelManager'] to disk, returning an error if persistence failed.
fn persist_manager(&self, channel_manager: &ChannelManager<Signer, M, T, K, F, L>) -> Result<(), io::Error>;
fn persist_scorer(&self, scorer: &S) -> Result<(), io::Error>;
}
-impl<'a, A: KVStorePersister, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref, S> Persister<'a, Signer, M, T, K, F, L, S> for A
+impl<'a, A: KVStorePersister, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref, S: WriteableScore<'a>> Persister<'a, Signer, M, T, K, F, L, S> for A
where M::Target: 'static + chain::Watch<Signer>,
T::Target: 'static + BroadcasterInterface,
K::Target: 'static + KeysInterface<Signer = Signer>,
F::Target: 'static + FeeEstimator,
L::Target: 'static + Logger,
- S: WriteableScore<'a>,
{
/// Persist the given ['ChannelManager'] to disk with the name "manager", returning an error if persistence failed.
fn persist_manager(&self, channel_manager: &ChannelManager<Signer, M, T, K, F, L>) -> Result<(), io::Error> {
use chain::channelmonitor::MonitorEvent;
use chain::transaction::OutPoint;
use chain::keysinterface;
-use ln::features::{ChannelFeatures, InitFeatures};
+use ln::channelmanager;
+use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
use ln::{msgs, wire};
use ln::script::ShutdownScript;
use routing::scoring::FixedPenaltyScorer;
impl Drop for TestChannelMessageHandler {
fn drop(&mut self) {
- let l = self.expected_recv_msgs.lock().unwrap();
#[cfg(feature = "std")]
{
+ let l = self.expected_recv_msgs.lock().unwrap();
if !std::thread::panicking() {
assert!(l.is_none() || l.as_ref().unwrap().is_empty());
}
self.received_msg(wire::Message::ChannelReestablish(msg.clone()));
}
fn peer_disconnected(&self, _their_node_id: &PublicKey, _no_connection_possible: bool) {}
- fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &msgs::Init) {
+ fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &msgs::Init) -> Result<(), ()> {
// Don't bother with `received_msg` for Init as its auto-generated and we don't want to
// bother re-generating the expected Init message in all tests.
+ Ok(())
}
fn handle_error(&self, _their_node_id: &PublicKey, msg: &msgs::ErrorMessage) {
self.received_msg(wire::Message::Error(msg.clone()));
}
+ fn provided_node_features(&self) -> NodeFeatures {
+ channelmanager::provided_node_features()
+ }
+ fn provided_init_features(&self, _their_init_features: &PublicKey) -> InitFeatures {
+ channelmanager::provided_init_features()
+ }
}
impl events::MessageSendEventsProvider for TestChannelMessageHandler {
let node_1_btckey = SecretKey::from_slice(&[40; 32]).unwrap();
let node_2_btckey = SecretKey::from_slice(&[39; 32]).unwrap();
let unsigned_ann = msgs::UnsignedChannelAnnouncement {
- features: ChannelFeatures::known(),
+ features: ChannelFeatures::empty(),
chain_hash: genesis_block(network).header.block_hash(),
short_channel_id: short_chan_id,
node_id_1: PublicKey::from_secret_key(&secp_ctx, &node_1_privkey),
None
}
- fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &msgs::Init) {
+ fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &msgs::Init) -> Result<(), ()> {
if !init_msg.features.supports_gossip_queries() {
- return ();
+ return Ok(());
}
- let should_request_full_sync = self.request_full_sync.load(Ordering::Acquire);
-
#[allow(unused_mut, unused_assignments)]
let mut gossip_start_time = 0;
#[cfg(feature = "std")]
{
gossip_start_time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs();
- if should_request_full_sync {
+ if self.request_full_sync.load(Ordering::Acquire) {
gossip_start_time -= 60 * 60 * 24 * 7 * 2; // 2 weeks ago
} else {
gossip_start_time -= 60 * 60; // an hour ago
timestamp_range: u32::max_value(),
},
});
+ Ok(())
}
fn handle_reply_channel_range(&self, _their_node_id: &PublicKey, _msg: msgs::ReplyChannelRange) -> Result<(), msgs::LightningError> {
fn handle_query_short_channel_ids(&self, _their_node_id: &PublicKey, _msg: msgs::QueryShortChannelIds) -> Result<(), msgs::LightningError> {
Ok(())
}
+
+ fn provided_node_features(&self) -> NodeFeatures {
+ let mut features = NodeFeatures::empty();
+ features.set_gossip_queries_optional();
+ features
+ }
+
+ fn provided_init_features(&self, _their_init_features: &PublicKey) -> InitFeatures {
+ let mut features = InitFeatures::empty();
+ features.set_gossip_queries_optional();
+ features
+ }
}
impl events::MessageSendEventsProvider for TestRoutingMessageHandler {
pub struct TestLogger {
level: Level,
- #[cfg(feature = "std")]
- id: String,
- #[cfg(not(feature = "std"))]
- _id: String,
+ pub(crate) id: String,
pub lines: Mutex<HashMap<(String, String), usize>>,
}
pub fn with_id(id: String) -> TestLogger {
TestLogger {
level: Level::Trace,
- #[cfg(feature = "std")]
id,
- #[cfg(not(feature = "std"))]
- _id: id,
lines: Mutex::new(HashMap::new())
}
}
assert_eq!(l, count)
}
- /// Search for the number of occurrences of logged lines which
- /// 1. belong to the specified module and
- /// 2. match the given regex pattern.
- /// Assert that the number of occurrences equals the given `count`
+ /// Search for the number of occurrences of logged lines which
+ /// 1. belong to the specified module and
+ /// 2. match the given regex pattern.
+ /// Assert that the number of occurrences equals the given `count`
pub fn assert_log_regex(&self, module: String, pattern: regex::Regex, count: usize) {
let log_entries = self.lines.lock().unwrap();
let l: usize = log_entries.iter().filter(|&(&(ref m, ref l), _c)| {
--- /dev/null
+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! Utilities which allow users to block on some future notification from LDK. These are
+//! specifically used by [`ChannelManager`] to allow waiting until the [`ChannelManager`] needs to
+//! be re-persisted.
+//!
+//! [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
+
+use alloc::sync::Arc;
+use core::mem;
+use sync::{Condvar, Mutex};
+
+use prelude::*;
+
+#[cfg(any(test, feature = "std"))]
+use std::time::{Duration, Instant};
+
+use core::future::Future as StdFuture;
+use core::task::{Context, Poll};
+use core::pin::Pin;
+
+
+/// Used to signal to one of many waiters that the condition they're waiting on has happened.
+pub(crate) struct Notifier {
+ notify_pending: Mutex<(bool, Option<Arc<Mutex<FutureState>>>)>,
+ condvar: Condvar,
+}
+
+impl Notifier {
+ pub(crate) fn new() -> Self {
+ Self {
+ notify_pending: Mutex::new((false, None)),
+ condvar: Condvar::new(),
+ }
+ }
+
+ pub(crate) fn wait(&self) {
+ loop {
+ let mut guard = self.notify_pending.lock().unwrap();
+ if guard.0 {
+ guard.0 = false;
+ return;
+ }
+ guard = self.condvar.wait(guard).unwrap();
+ let result = guard.0;
+ if result {
+ guard.0 = false;
+ return
+ }
+ }
+ }
+
+ #[cfg(any(test, feature = "std"))]
+ pub(crate) fn wait_timeout(&self, max_wait: Duration) -> bool {
+ let current_time = Instant::now();
+ loop {
+ let mut guard = self.notify_pending.lock().unwrap();
+ if guard.0 {
+ guard.0 = false;
+ return true;
+ }
+ guard = self.condvar.wait_timeout(guard, max_wait).unwrap().0;
+ // Due to spurious wakeups that can happen on `wait_timeout`, here we need to check if the
+ // desired wait time has actually passed, and if not then restart the loop with a reduced wait
+ // time. Note that this logic can be highly simplified through the use of
+ // `Condvar::wait_while` and `Condvar::wait_timeout_while`, if and when our MSRV is raised to
+ // 1.42.0.
+ let elapsed = current_time.elapsed();
+ let result = guard.0;
+ if result || elapsed >= max_wait {
+ guard.0 = false;
+ return result;
+ }
+ match max_wait.checked_sub(elapsed) {
+ None => return result,
+ Some(_) => continue
+ }
+ }
+ }
+
+ /// Wake waiters, tracking that wake needs to occur even if there are currently no waiters.
+ pub(crate) fn notify(&self) {
+ let mut lock = self.notify_pending.lock().unwrap();
+ lock.0 = true;
+ if let Some(future_state) = lock.1.take() {
+ future_state.lock().unwrap().complete();
+ }
+ mem::drop(lock);
+ self.condvar.notify_all();
+ }
+
+ /// Gets a [`Future`] that will get woken up with any waiters
+ pub(crate) fn get_future(&self) -> Future {
+ let mut lock = self.notify_pending.lock().unwrap();
+ if lock.0 {
+ Future {
+ state: Arc::new(Mutex::new(FutureState {
+ callbacks: Vec::new(),
+ complete: false,
+ }))
+ }
+ } else if let Some(existing_state) = &lock.1 {
+ Future { state: Arc::clone(&existing_state) }
+ } else {
+ let state = Arc::new(Mutex::new(FutureState {
+ callbacks: Vec::new(),
+ complete: false,
+ }));
+ lock.1 = Some(Arc::clone(&state));
+ Future { state }
+ }
+ }
+
+ #[cfg(any(test, feature = "_test_utils"))]
+ pub fn notify_pending(&self) -> bool {
+ self.notify_pending.lock().unwrap().0
+ }
+}
+
+/// A callback which is called when a [`Future`] completes.
+///
+/// Note that this MUST NOT call back into LDK directly, it must instead schedule actions to be
+/// taken later. Rust users should use the [`std::future::Future`] implementation for [`Future`]
+/// instead.
+///
+/// Note that the [`std::future::Future`] implementation may only work for runtimes which schedule
+/// futures when they receive a wake, rather than immediately executing them.
+pub trait FutureCallback : Send {
+ /// The method which is called.
+ fn call(&self);
+}
+
+impl<F: Fn() + Send> FutureCallback for F {
+ fn call(&self) { (self)(); }
+}
+
+pub(crate) struct FutureState {
+ callbacks: Vec<Box<dyn FutureCallback>>,
+ complete: bool,
+}
+
+impl FutureState {
+ fn complete(&mut self) {
+ for callback in self.callbacks.drain(..) {
+ callback.call();
+ }
+ self.complete = true;
+ }
+}
+
+/// A simple future which can complete once, and calls some callback(s) when it does so.
+pub struct Future {
+ state: Arc<Mutex<FutureState>>,
+}
+
+impl Future {
+ /// Registers a callback to be called upon completion of this future. If the future has already
+ /// completed, the callback will be called immediately.
+ pub fn register_callback(&self, callback: Box<dyn FutureCallback>) {
+ let mut state = self.state.lock().unwrap();
+ if state.complete {
+ mem::drop(state);
+ callback.call();
+ } else {
+ state.callbacks.push(callback);
+ }
+ }
+}
+
+mod std_future {
+ use core::task::Waker;
+ pub struct StdWaker(pub Waker);
+ impl super::FutureCallback for StdWaker {
+ fn call(&self) { self.0.wake_by_ref() }
+ }
+}
+
+/// (C-not exported) as Rust Futures aren't usable in language bindings.
+impl<'a> StdFuture for Future {
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ let mut state = self.state.lock().unwrap();
+ if state.complete {
+ Poll::Ready(())
+ } else {
+ let waker = cx.waker().clone();
+ state.callbacks.push(Box::new(std_future::StdWaker(waker)));
+ Poll::Pending
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use core::sync::atomic::{AtomicBool, Ordering};
+ use core::future::Future as FutureTrait;
+ use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
+
+ #[cfg(feature = "std")]
+ #[test]
+ fn test_wait_timeout() {
+ use sync::Arc;
+ use std::thread;
+
+ let persistence_notifier = Arc::new(Notifier::new());
+ let thread_notifier = Arc::clone(&persistence_notifier);
+
+ let exit_thread = Arc::new(AtomicBool::new(false));
+ let exit_thread_clone = exit_thread.clone();
+ thread::spawn(move || {
+ loop {
+ let mut lock = thread_notifier.notify_pending.lock().unwrap();
+ lock.0 = true;
+ thread_notifier.condvar.notify_all();
+
+ if exit_thread_clone.load(Ordering::SeqCst) {
+ break
+ }
+ }
+ });
+
+ // Check that we can block indefinitely until updates are available.
+ let _ = persistence_notifier.wait();
+
+ // Check that the Notifier will return after the given duration if updates are
+ // available.
+ loop {
+ if persistence_notifier.wait_timeout(Duration::from_millis(100)) {
+ break
+ }
+ }
+
+ exit_thread.store(true, Ordering::SeqCst);
+
+ // Check that the Notifier will return after the given duration even if no updates
+ // are available.
+ loop {
+ if !persistence_notifier.wait_timeout(Duration::from_millis(100)) {
+ break
+ }
+ }
+ }
+
+ #[test]
+ fn test_future_callbacks() {
+ let future = Future {
+ state: Arc::new(Mutex::new(FutureState {
+ callbacks: Vec::new(),
+ complete: false,
+ }))
+ };
+ let callback = Arc::new(AtomicBool::new(false));
+ let callback_ref = Arc::clone(&callback);
+ future.register_callback(Box::new(move || assert!(!callback_ref.fetch_or(true, Ordering::SeqCst))));
+
+ assert!(!callback.load(Ordering::SeqCst));
+ future.state.lock().unwrap().complete();
+ assert!(callback.load(Ordering::SeqCst));
+ future.state.lock().unwrap().complete();
+ }
+
+ #[test]
+ fn test_pre_completed_future_callbacks() {
+ let future = Future {
+ state: Arc::new(Mutex::new(FutureState {
+ callbacks: Vec::new(),
+ complete: false,
+ }))
+ };
+ future.state.lock().unwrap().complete();
+
+ let callback = Arc::new(AtomicBool::new(false));
+ let callback_ref = Arc::clone(&callback);
+ future.register_callback(Box::new(move || assert!(!callback_ref.fetch_or(true, Ordering::SeqCst))));
+
+ assert!(callback.load(Ordering::SeqCst));
+ assert!(future.state.lock().unwrap().callbacks.is_empty());
+ }
+
+ // Rather annoyingly, there's no safe way in Rust std to construct a Waker despite it being
+ // totally possible to construct from a trait implementation (though somewhat less effecient
+ // compared to a raw VTable). Instead, we have to write out a lot of boilerplate to build a
+ // waker, which we do here with a trivial Arc<AtomicBool> data element to track woke-ness.
+ const WAKER_V_TABLE: RawWakerVTable = RawWakerVTable::new(waker_clone, wake, wake_by_ref, drop);
+ unsafe fn wake_by_ref(ptr: *const ()) { let p = ptr as *const Arc<AtomicBool>; assert!(!(*p).fetch_or(true, Ordering::SeqCst)); }
+ unsafe fn drop(ptr: *const ()) { let p = ptr as *mut Arc<AtomicBool>; let _freed = Box::from_raw(p); }
+ unsafe fn wake(ptr: *const ()) { wake_by_ref(ptr); drop(ptr); }
+ unsafe fn waker_clone(ptr: *const ()) -> RawWaker {
+ let p = ptr as *const Arc<AtomicBool>;
+ RawWaker::new(Box::into_raw(Box::new(Arc::clone(&*p))) as *const (), &WAKER_V_TABLE)
+ }
+
+ fn create_waker() -> (Arc<AtomicBool>, Waker) {
+ let a = Arc::new(AtomicBool::new(false));
+ let waker = unsafe { Waker::from_raw(waker_clone((&a as *const Arc<AtomicBool>) as *const ())) };
+ (a, waker)
+ }
+
+ #[test]
+ fn test_future() {
+ let mut future = Future {
+ state: Arc::new(Mutex::new(FutureState {
+ callbacks: Vec::new(),
+ complete: false,
+ }))
+ };
+ let mut second_future = Future { state: Arc::clone(&future.state) };
+
+ let (woken, waker) = create_waker();
+ assert_eq!(Pin::new(&mut future).poll(&mut Context::from_waker(&waker)), Poll::Pending);
+ assert!(!woken.load(Ordering::SeqCst));
+
+ let (second_woken, second_waker) = create_waker();
+ assert_eq!(Pin::new(&mut second_future).poll(&mut Context::from_waker(&second_waker)), Poll::Pending);
+ assert!(!second_woken.load(Ordering::SeqCst));
+
+ future.state.lock().unwrap().complete();
+ assert!(woken.load(Ordering::SeqCst));
+ assert!(second_woken.load(Ordering::SeqCst));
+ assert_eq!(Pin::new(&mut future).poll(&mut Context::from_waker(&waker)), Poll::Ready(()));
+ assert_eq!(Pin::new(&mut second_future).poll(&mut Context::from_waker(&second_waker)), Poll::Ready(()));
+ }
+}
edition = "2018"
[features]
-default = ["lightning/no-std", "lightning-invoice/no-std"]
+default = ["lightning/no-std", "lightning-invoice/no-std", "lightning-rapid-gossip-sync/no-std"]
[dependencies]
lightning = { path = "../lightning", default-features = false }
lightning-invoice = { path = "../lightning-invoice", default-features = false }
+lightning-rapid-gossip-sync = { path = "../lightning-rapid-gossip-sync", default-features = false }