EXPECTED_ROUTING_GRAPH_SNAPSHOT_SHASUM: 05a5361278f68ee2afd086cc04a1f927a63924be451f3221d380533acfacc303
- name: Fetch rapid graph sync reference input
run: |
- curl --verbose -L -o lightning-rapid-gossip-sync/res/full_graph.lngossip https://bitcoin.ninja/ldk-compressed_graph-bc08df7542-2022-05-05.bin
+ curl --verbose -L -o lightning-rapid-gossip-sync/res/full_graph.lngossip https://bitcoin.ninja/ldk-compressed_graph-285cb27df79-2022-07-21.bin
echo "Sha sum: $(sha256sum lightning-rapid-gossip-sync/res/full_graph.lngossip | awk '{ print $1 }')"
if [ "$(sha256sum lightning-rapid-gossip-sync/res/full_graph.lngossip | awk '{ print $1 }')" != "${EXPECTED_RAPID_GOSSIP_SHASUM}" ]; then
echo "Bad hash"
exit 1
fi
env:
- EXPECTED_RAPID_GOSSIP_SHASUM: 9637b91cea9d64320cf48fc0787c70fe69fc062f90d3512e207044110cadfd7b
+ EXPECTED_RAPID_GOSSIP_SHASUM: e0f5d11641c11896d7af3a2246d3d6c3f1720b7d2d17aab321ecce82e6b7deb8
- name: Test with Network Graph on Rust ${{ matrix.toolchain }}
run: |
cd lightning
};
let deserialized_monitor = <(BlockHash, channelmonitor::ChannelMonitor<EnforcingSigner>)>::
read(&mut Cursor::new(&map_entry.get().1), &*self.keys).unwrap().1;
- deserialized_monitor.update_monitor(&update, &&TestBroadcaster{}, &&FuzzEstimator { ret_val: atomic::AtomicU32::new(253) }, &self.logger).unwrap();
+ deserialized_monitor.update_monitor(&update, &&TestBroadcaster{}, &FuzzEstimator { ret_val: atomic::AtomicU32::new(253) }, &self.logger).unwrap();
let mut ser = VecWriter(Vec::new());
deserialized_monitor.write(&mut ser).unwrap();
map_entry.insert((update.update_id, ser.0));
type T = ValidatedBlockHeader;
fn validate(self, block_hash: BlockHash) -> BlockSourceResult<Self::T> {
- self.header
+ let pow_valid_block_hash = self.header
.validate_pow(&self.header.target())
.or_else(|e| Err(BlockSourceError::persistent(e)))?;
- // TODO: Use the result of validate_pow instead of recomputing the block hash once upstream.
- if self.header.block_hash() != block_hash {
+ if pow_valid_block_hash != block_hash {
return Err(BlockSourceError::persistent("invalid block hash"));
}
type T = ValidatedBlock;
fn validate(self, block_hash: BlockHash) -> BlockSourceResult<Self::T> {
- self.header
+ let pow_valid_block_hash = self.header
.validate_pow(&self.header.target())
.or_else(|e| Err(BlockSourceError::persistent(e)))?;
- // TODO: Use the result of validate_pow instead of recomputing the block hash once upstream.
- if self.block_hash() != block_hash {
+ if pow_valid_block_hash != block_hash {
return Err(BlockSourceError::persistent("invalid block hash"));
}
use lightning::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, NetAddress};
use lightning::util::logger::Logger;
+use std::ops::Deref;
use std::task;
use std::net::SocketAddr;
use std::net::TcpStream as StdTcpStream;
id: u64,
}
impl Connection {
- async fn poll_event_process<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, Arc<CMH>, Arc<RMH>, Arc<L>, Arc<UMH>>>, mut event_receiver: mpsc::Receiver<()>) where
- CMH: ChannelMessageHandler + 'static + Send + Sync,
- RMH: RoutingMessageHandler + 'static + Send + Sync,
- L: Logger + 'static + ?Sized + Send + Sync,
- UMH: CustomMessageHandler + 'static + Send + Sync {
+ async fn poll_event_process<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, CMH, RMH, L, UMH>>, mut event_receiver: mpsc::Receiver<()>) where
+ CMH: Deref + 'static + Send + Sync,
+ RMH: Deref + 'static + Send + Sync,
+ L: Deref + 'static + Send + Sync,
+ UMH: Deref + 'static + Send + Sync,
+ CMH::Target: ChannelMessageHandler + Send + Sync,
+ RMH::Target: RoutingMessageHandler + Send + Sync,
+ L::Target: Logger + Send + Sync,
+ UMH::Target: CustomMessageHandler + Send + Sync,
+ {
loop {
if event_receiver.recv().await.is_none() {
return;
}
}
- async fn schedule_read<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, Arc<CMH>, Arc<RMH>, Arc<L>, Arc<UMH>>>, us: Arc<Mutex<Self>>, mut reader: io::ReadHalf<TcpStream>, mut read_wake_receiver: mpsc::Receiver<()>, mut write_avail_receiver: mpsc::Receiver<()>) where
- CMH: ChannelMessageHandler + 'static + Send + Sync,
- RMH: RoutingMessageHandler + 'static + Send + Sync,
- L: Logger + 'static + ?Sized + Send + Sync,
- UMH: CustomMessageHandler + 'static + Send + Sync {
+ async fn schedule_read<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, CMH, RMH, L, UMH>>, us: Arc<Mutex<Self>>, mut reader: io::ReadHalf<TcpStream>, mut read_wake_receiver: mpsc::Receiver<()>, mut write_avail_receiver: mpsc::Receiver<()>) where
+ CMH: Deref + 'static + Send + Sync,
+ RMH: Deref + 'static + Send + Sync,
+ L: Deref + 'static + Send + Sync,
+ UMH: Deref + 'static + Send + Sync,
+ CMH::Target: ChannelMessageHandler + 'static + Send + Sync,
+ RMH::Target: RoutingMessageHandler + 'static + Send + Sync,
+ L::Target: Logger + 'static + Send + Sync,
+ UMH::Target: CustomMessageHandler + 'static + Send + Sync,
+ {
// Create a waker to wake up poll_event_process, above
let (event_waker, event_receiver) = mpsc::channel(1);
tokio::spawn(Self::poll_event_process(Arc::clone(&peer_manager), event_receiver));
/// The returned future will complete when the peer is disconnected and associated handling
/// futures are freed, though, because all processing futures are spawned with tokio::spawn, you do
/// not need to poll the provided future in order to make progress.
-pub fn setup_inbound<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, Arc<CMH>, Arc<RMH>, Arc<L>, Arc<UMH>>>, stream: StdTcpStream) -> impl std::future::Future<Output=()> where
- CMH: ChannelMessageHandler + 'static + Send + Sync,
- RMH: RoutingMessageHandler + 'static + Send + Sync,
- L: Logger + 'static + ?Sized + Send + Sync,
- UMH: CustomMessageHandler + 'static + Send + Sync {
+pub fn setup_inbound<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, CMH, RMH, L, UMH>>, stream: StdTcpStream) -> impl std::future::Future<Output=()> where
+ CMH: Deref + 'static + Send + Sync,
+ RMH: Deref + 'static + Send + Sync,
+ L: Deref + 'static + Send + Sync,
+ UMH: Deref + 'static + Send + Sync,
+ CMH::Target: ChannelMessageHandler + Send + Sync,
+ RMH::Target: RoutingMessageHandler + Send + Sync,
+ L::Target: Logger + Send + Sync,
+ UMH::Target: CustomMessageHandler + Send + Sync,
+{
let remote_addr = get_addr_from_stream(&stream);
let (reader, write_receiver, read_receiver, us) = Connection::new(stream);
#[cfg(debug_assertions)]
/// The returned future will complete when the peer is disconnected and associated handling
/// futures are freed, though, because all processing futures are spawned with tokio::spawn, you do
/// not need to poll the provided future in order to make progress.
-pub fn setup_outbound<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, Arc<CMH>, Arc<RMH>, Arc<L>, Arc<UMH>>>, their_node_id: PublicKey, stream: StdTcpStream) -> impl std::future::Future<Output=()> where
- CMH: ChannelMessageHandler + 'static + Send + Sync,
- RMH: RoutingMessageHandler + 'static + Send + Sync,
- L: Logger + 'static + ?Sized + Send + Sync,
- UMH: CustomMessageHandler + 'static + Send + Sync {
+pub fn setup_outbound<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, CMH, RMH, L, UMH>>, their_node_id: PublicKey, stream: StdTcpStream) -> impl std::future::Future<Output=()> where
+ CMH: Deref + 'static + Send + Sync,
+ RMH: Deref + 'static + Send + Sync,
+ L: Deref + 'static + Send + Sync,
+ UMH: Deref + 'static + Send + Sync,
+ CMH::Target: ChannelMessageHandler + Send + Sync,
+ RMH::Target: RoutingMessageHandler + Send + Sync,
+ L::Target: Logger + Send + Sync,
+ UMH::Target: CustomMessageHandler + Send + Sync,
+{
let remote_addr = get_addr_from_stream(&stream);
let (reader, mut write_receiver, read_receiver, us) = Connection::new(stream);
#[cfg(debug_assertions)]
/// disconnected and associated handling futures are freed, though, because all processing in said
/// futures are spawned with tokio::spawn, you do not need to poll the second future in order to
/// make progress.
-pub async fn connect_outbound<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, Arc<CMH>, Arc<RMH>, Arc<L>, Arc<UMH>>>, their_node_id: PublicKey, addr: SocketAddr) -> Option<impl std::future::Future<Output=()>> where
- CMH: ChannelMessageHandler + 'static + Send + Sync,
- RMH: RoutingMessageHandler + 'static + Send + Sync,
- L: Logger + 'static + ?Sized + Send + Sync,
- UMH: CustomMessageHandler + 'static + Send + Sync {
+pub async fn connect_outbound<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, CMH, RMH, L, UMH>>, their_node_id: PublicKey, addr: SocketAddr) -> Option<impl std::future::Future<Output=()>> where
+ CMH: Deref + 'static + Send + Sync,
+ RMH: Deref + 'static + Send + Sync,
+ L: Deref + 'static + Send + Sync,
+ UMH: Deref + 'static + Send + Sync,
+ CMH::Target: ChannelMessageHandler + Send + Sync,
+ RMH::Target: RoutingMessageHandler + Send + Sync,
+ L::Target: Logger + Send + Sync,
+ UMH::Target: CustomMessageHandler + Send + Sync,
+{
if let Ok(Ok(stream)) = time::timeout(Duration::from_secs(10), async { TcpStream::connect(&addr).await.map(|s| s.into_std().unwrap()) }).await {
Some(setup_outbound(peer_manager, their_node_id, stream))
} else { None }
let sync_result = rapid_sync
.sync_network_graph_with_file_path("./res/full_graph.lngossip");
if let Err(crate::error::GraphSyncError::DecodeError(DecodeError::Io(io_error))) = &sync_result {
- let error_string = format!("Input file lightning-rapid-gossip-sync/res/full_graph.lngossip is missing! Download it from https://bitcoin.ninja/ldk-compressed_graph-bc08df7542-2022-05-05.bin\n\n{:?}", io_error);
+ let error_string = format!("Input file lightning-rapid-gossip-sync/res/full_graph.lngossip is missing! Download it from https://bitcoin.ninja/ldk-compressed_graph-285cb27df79-2022-07-21.bin\n\n{:?}", io_error);
#[cfg(not(require_route_graph_test))]
{
println!("{}", error_string);
use bitcoin::secp256k1::PublicKey;
use lightning::ln::msgs::{
- DecodeError, ErrorAction, LightningError, OptionalField, UnsignedChannelUpdate,
+ DecodeError, ErrorAction, LightningError, UnsignedChannelUpdate,
};
use lightning::routing::gossip::NetworkGraph;
use lightning::util::logger::Logger;
let default_htlc_minimum_msat: u64 = Readable::read(&mut read_cursor)?;
let default_fee_base_msat: u32 = Readable::read(&mut read_cursor)?;
let default_fee_proportional_millionths: u32 = Readable::read(&mut read_cursor)?;
- let tentative_default_htlc_maximum_msat: u64 = Readable::read(&mut read_cursor)?;
- let default_htlc_maximum_msat = if tentative_default_htlc_maximum_msat == u64::max_value() {
- OptionalField::Absent
- } else {
- OptionalField::Present(tentative_default_htlc_maximum_msat)
- };
+ let default_htlc_maximum_msat: u64 = Readable::read(&mut read_cursor)?;
for _ in 0..update_count {
let scid_delta: BigSize = Readable::read(read_cursor)?;
flags: standard_channel_flags,
cltv_expiry_delta: default_cltv_expiry_delta,
htlc_minimum_msat: default_htlc_minimum_msat,
- htlc_maximum_msat: default_htlc_maximum_msat.clone(),
+ htlc_maximum_msat: default_htlc_maximum_msat,
fee_base_msat: default_fee_base_msat,
fee_proportional_millionths: default_fee_proportional_millionths,
excess_data: vec![],
action: ErrorAction::IgnoreError,
})?;
- let htlc_maximum_msat =
- if let Some(htlc_maximum_msat) = directional_info.htlc_maximum_msat {
- OptionalField::Present(htlc_maximum_msat)
- } else {
- OptionalField::Absent
- };
-
UnsignedChannelUpdate {
chain_hash,
short_channel_id,
flags: standard_channel_flags,
cltv_expiry_delta: directional_info.cltv_expiry_delta,
htlc_minimum_msat: directional_info.htlc_minimum_msat,
- htlc_maximum_msat,
+ htlc_maximum_msat: directional_info.htlc_maximum_msat,
fee_base_msat: directional_info.fees.base_msat,
fee_proportional_millionths: directional_info.fees.proportional_millionths,
excess_data: vec![],
}
if channel_flags & 0b_0000_0100 > 0 {
- let tentative_htlc_maximum_msat: u64 = Readable::read(read_cursor)?;
- synthetic_update.htlc_maximum_msat = if tentative_htlc_maximum_msat == u64::max_value()
- {
- OptionalField::Absent
- } else {
- OptionalField::Present(tentative_htlc_maximum_msat)
- };
+ let htlc_maximum_msat: u64 = Readable::read(read_cursor)?;
+ synthetic_update.htlc_maximum_msat = htlc_maximum_msat;
}
network_graph.update_channel_unsigned(&synthetic_update)?;
fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32;
}
-// We need `FeeEstimator` implemented so that in some places where we only have a shared
-// reference to a `Deref` to a `FeeEstimator`, we can still wrap it.
-impl<D: Deref> FeeEstimator for D where D::Target: FeeEstimator {
- fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32 {
- (**self).get_est_sat_per_1000_weight(confirmation_target)
- }
-}
-
/// Minimum relay fee as required by bitcoin network mempool policy.
pub const MIN_RELAY_FEE_SAT_PER_1000_WEIGHT: u64 = 4000;
/// Minimum feerate that takes a sane approach to bitcoind weight-to-vbytes rounding.
/// See the following Core Lightning commit for an explanation:
-/// https://github.com/ElementsProject/lightning/commit/2e687b9b352c9092b5e8bd4a688916ac50b44af0
+/// <https://github.com/ElementsProject/lightning/commit/2e687b9b352c9092b5e8bd4a688916ac50b44af0>
pub const FEERATE_FLOOR_SATS_PER_KW: u32 = 253;
/// Wraps a `Deref` to a `FeeEstimator` so that any fee estimations provided by it
-/// are bounded below by `FEERATE_FLOOR_SATS_PER_KW` (253 sats/KW)
+/// are bounded below by `FEERATE_FLOOR_SATS_PER_KW` (253 sats/KW).
+///
+/// Note that this does *not* implement [`FeeEstimator`] to make it harder to accidentally mix the
+/// two.
pub(crate) struct LowerBoundedFeeEstimator<F: Deref>(pub F) where F::Target: FeeEstimator;
impl<F: Deref> LowerBoundedFeeEstimator<F> where F::Target: FeeEstimator {
pub fn new(fee_estimator: F) -> Self {
LowerBoundedFeeEstimator(fee_estimator)
}
-}
-impl<F: Deref> FeeEstimator for LowerBoundedFeeEstimator<F> where F::Target: FeeEstimator {
- fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32 {
+ pub fn bounded_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32 {
cmp::max(
self.0.get_est_sat_per_1000_weight(confirmation_target),
FEERATE_FLOOR_SATS_PER_KW,
let test_fee_estimator = &TestFeeEstimator { sat_per_kw };
let fee_estimator = LowerBoundedFeeEstimator::new(test_fee_estimator);
- assert_eq!(fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background), FEERATE_FLOOR_SATS_PER_KW);
+ assert_eq!(fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Background), FEERATE_FLOOR_SATS_PER_KW);
}
#[test]
let test_fee_estimator = &TestFeeEstimator { sat_per_kw };
let fee_estimator = LowerBoundedFeeEstimator::new(test_fee_estimator);
- assert_eq!(fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background), sat_per_kw);
+ assert_eq!(fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Background), sat_per_kw);
}
}
Some(monitor_state) => {
let monitor = &monitor_state.monitor;
log_trace!(self.logger, "Updating ChannelMonitor for channel {}", log_funding_info!(monitor));
- let update_res = monitor.update_monitor(&update, &self.broadcaster, &self.fee_estimator, &self.logger);
+ let update_res = monitor.update_monitor(&update, &self.broadcaster, &*self.fee_estimator, &self.logger);
if update_res.is_err() {
log_error!(self.logger, "Failed to update ChannelMonitor for channel {}.", log_funding_info!(monitor));
}
}
impl<Signer: Sign> ChannelMonitor<Signer> {
+ /// For lockorder enforcement purposes, we need to have a single site which constructs the
+ /// `inner` mutex, otherwise cases where we lock two monitors at the same time (eg in our
+ /// PartialEq implementation) we may decide a lockorder violation has occurred.
+ fn from_impl(imp: ChannelMonitorImpl<Signer>) -> Self {
+ ChannelMonitor { inner: Mutex::new(imp) }
+ }
+
pub(crate) fn new(secp_ctx: Secp256k1<secp256k1::All>, keys: Signer, shutdown_script: Option<Script>,
on_counterparty_tx_csv: u16, destination_script: &Script, funding_info: (OutPoint, Script),
channel_parameters: &ChannelTransactionParameters,
let mut outputs_to_watch = HashMap::new();
outputs_to_watch.insert(funding_info.0.txid, vec![(funding_info.0.index as u32, funding_info.1.clone())]);
- ChannelMonitor {
- inner: Mutex::new(ChannelMonitorImpl {
- latest_update_id: 0,
- commitment_transaction_number_obscure_factor,
+ Self::from_impl(ChannelMonitorImpl {
+ latest_update_id: 0,
+ commitment_transaction_number_obscure_factor,
- destination_script: destination_script.clone(),
- broadcasted_holder_revokable_script: None,
- counterparty_payment_script,
- shutdown_script,
+ destination_script: destination_script.clone(),
+ broadcasted_holder_revokable_script: None,
+ counterparty_payment_script,
+ shutdown_script,
- channel_keys_id,
- holder_revocation_basepoint,
- funding_info,
- current_counterparty_commitment_txid: None,
- prev_counterparty_commitment_txid: None,
+ channel_keys_id,
+ holder_revocation_basepoint,
+ funding_info,
+ current_counterparty_commitment_txid: None,
+ prev_counterparty_commitment_txid: None,
- counterparty_commitment_params,
- funding_redeemscript,
- channel_value_satoshis,
- their_cur_per_commitment_points: None,
+ counterparty_commitment_params,
+ funding_redeemscript,
+ channel_value_satoshis,
+ their_cur_per_commitment_points: None,
- on_holder_tx_csv: counterparty_channel_parameters.selected_contest_delay,
+ on_holder_tx_csv: counterparty_channel_parameters.selected_contest_delay,
- commitment_secrets: CounterpartyCommitmentSecrets::new(),
- counterparty_claimable_outpoints: HashMap::new(),
- counterparty_commitment_txn_on_chain: HashMap::new(),
- counterparty_hash_commitment_number: HashMap::new(),
+ commitment_secrets: CounterpartyCommitmentSecrets::new(),
+ counterparty_claimable_outpoints: HashMap::new(),
+ counterparty_commitment_txn_on_chain: HashMap::new(),
+ counterparty_hash_commitment_number: HashMap::new(),
- prev_holder_signed_commitment_tx: None,
- current_holder_commitment_tx: holder_commitment_tx,
- current_counterparty_commitment_number: 1 << 48,
- current_holder_commitment_number,
+ prev_holder_signed_commitment_tx: None,
+ current_holder_commitment_tx: holder_commitment_tx,
+ current_counterparty_commitment_number: 1 << 48,
+ current_holder_commitment_number,
- payment_preimages: HashMap::new(),
- pending_monitor_events: Vec::new(),
- pending_events: Vec::new(),
+ payment_preimages: HashMap::new(),
+ pending_monitor_events: Vec::new(),
+ pending_events: Vec::new(),
- onchain_events_awaiting_threshold_conf: Vec::new(),
- outputs_to_watch,
+ onchain_events_awaiting_threshold_conf: Vec::new(),
+ outputs_to_watch,
- onchain_tx_handler,
+ onchain_tx_handler,
- lockdown_from_offchain: false,
- holder_tx_signed: false,
- funding_spend_seen: false,
- funding_spend_confirmed: None,
- htlcs_resolved_on_chain: Vec::new(),
+ lockdown_from_offchain: false,
+ holder_tx_signed: false,
+ funding_spend_seen: false,
+ funding_spend_confirmed: None,
+ htlcs_resolved_on_chain: Vec::new(),
- best_block,
- counterparty_node_id: Some(counterparty_node_id),
+ best_block,
+ counterparty_node_id: Some(counterparty_node_id),
- secp_ctx,
- }),
- }
+ secp_ctx,
+ })
}
#[cfg(test)]
&self,
updates: &ChannelMonitorUpdate,
broadcaster: &B,
- fee_estimator: &F,
+ fee_estimator: F,
logger: &L,
) -> Result<(), ()>
where
self.pending_monitor_events.push(MonitorEvent::CommitmentTxConfirmed(self.funding_info.0));
}
- pub fn update_monitor<B: Deref, F: Deref, L: Deref>(&mut self, updates: &ChannelMonitorUpdate, broadcaster: &B, fee_estimator: &F, logger: &L) -> Result<(), ()>
+ pub fn update_monitor<B: Deref, F: Deref, L: Deref>(&mut self, updates: &ChannelMonitorUpdate, broadcaster: &B, fee_estimator: F, logger: &L) -> Result<(), ()>
where B::Target: BroadcasterInterface,
- F::Target: FeeEstimator,
- L::Target: Logger,
+ F::Target: FeeEstimator,
+ L::Target: Logger,
{
log_info!(logger, "Applying update to monitor {}, bringing update_id from {} to {} with {} changes.",
log_funding_info!(self), self.latest_update_id, updates.update_id, updates.updates.len());
},
ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } => {
log_trace!(logger, "Updating ChannelMonitor with payment preimage");
- let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator);
+ let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&*fee_estimator);
self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage, broadcaster, &bounded_fee_estimator, logger)
},
ChannelMonitorUpdateStep::CommitmentSecret { idx, secret } => {
let mut secp_ctx = Secp256k1::new();
secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes());
- Ok((best_block.block_hash(), ChannelMonitor {
- inner: Mutex::new(ChannelMonitorImpl {
- latest_update_id,
- commitment_transaction_number_obscure_factor,
+ Ok((best_block.block_hash(), ChannelMonitor::from_impl(ChannelMonitorImpl {
+ latest_update_id,
+ commitment_transaction_number_obscure_factor,
- destination_script,
- broadcasted_holder_revokable_script,
- counterparty_payment_script,
- shutdown_script,
+ destination_script,
+ broadcasted_holder_revokable_script,
+ counterparty_payment_script,
+ shutdown_script,
- channel_keys_id,
- holder_revocation_basepoint,
- funding_info,
- current_counterparty_commitment_txid,
- prev_counterparty_commitment_txid,
+ channel_keys_id,
+ holder_revocation_basepoint,
+ funding_info,
+ current_counterparty_commitment_txid,
+ prev_counterparty_commitment_txid,
- counterparty_commitment_params,
- funding_redeemscript,
- channel_value_satoshis,
- their_cur_per_commitment_points,
+ counterparty_commitment_params,
+ funding_redeemscript,
+ channel_value_satoshis,
+ their_cur_per_commitment_points,
- on_holder_tx_csv,
+ on_holder_tx_csv,
- commitment_secrets,
- counterparty_claimable_outpoints,
- counterparty_commitment_txn_on_chain,
- counterparty_hash_commitment_number,
+ commitment_secrets,
+ counterparty_claimable_outpoints,
+ counterparty_commitment_txn_on_chain,
+ counterparty_hash_commitment_number,
- prev_holder_signed_commitment_tx,
- current_holder_commitment_tx,
- current_counterparty_commitment_number,
- current_holder_commitment_number,
+ prev_holder_signed_commitment_tx,
+ current_holder_commitment_tx,
+ current_counterparty_commitment_number,
+ current_holder_commitment_number,
- payment_preimages,
- pending_monitor_events: pending_monitor_events.unwrap(),
- pending_events,
+ payment_preimages,
+ pending_monitor_events: pending_monitor_events.unwrap(),
+ pending_events,
- onchain_events_awaiting_threshold_conf,
- outputs_to_watch,
+ onchain_events_awaiting_threshold_conf,
+ outputs_to_watch,
- onchain_tx_handler,
+ onchain_tx_handler,
- lockdown_from_offchain,
- holder_tx_signed,
- funding_spend_seen: funding_spend_seen.unwrap(),
- funding_spend_confirmed,
- htlcs_resolved_on_chain: htlcs_resolved_on_chain.unwrap(),
+ lockdown_from_offchain,
+ holder_tx_signed,
+ funding_spend_seen: funding_spend_seen.unwrap(),
+ funding_spend_confirmed,
+ htlcs_resolved_on_chain: htlcs_resolved_on_chain.unwrap(),
- best_block,
- counterparty_node_id,
+ best_block,
+ counterparty_node_id,
- secp_ctx,
- }),
- }))
+ secp_ctx,
+ })))
}
}
let broadcaster = TestBroadcaster::new(Arc::clone(&nodes[1].blocks));
assert!(
- pre_update_monitor.update_monitor(&replay_update, &&broadcaster, &&chanmon_cfgs[1].fee_estimator, &nodes[1].logger)
+ pre_update_monitor.update_monitor(&replay_update, &&broadcaster, &chanmon_cfgs[1].fee_estimator, &nodes[1].logger)
.is_err());
// Even though we error'd on the first update, we should still have generated an HTLC claim
// transaction
where F::Target: FeeEstimator,
L::Target: Logger,
{
- let mut updated_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) as u64;
+ let mut updated_feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::HighPriority) as u64;
let mut fee = updated_feerate * (predicted_weight as u64) / 1000;
if input_amounts <= fee {
- updated_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal) as u64;
+ updated_feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal) as u64;
fee = updated_feerate * (predicted_weight as u64) / 1000;
if input_amounts <= fee {
- updated_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background) as u64;
+ updated_feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Background) as u64;
fee = updated_feerate * (predicted_weight as u64) / 1000;
if input_amounts <= fee {
log_error!(logger, "Failed to generate an on-chain punishment tx as even low priority fee ({} sat) was more than the entire claim balance ({} sat)",
use core::ops::{Deref, DerefMut};
use core::time::Duration;
-use std::collections::HashSet;
use std::cell::RefCell;
use std::sync::atomic::{AtomicUsize, Ordering};
-
use std::sync::Mutex as StdMutex;
use std::sync::MutexGuard as StdMutexGuard;
use std::sync::RwLock as StdRwLock;
use std::sync::RwLockWriteGuard as StdRwLockWriteGuard;
use std::sync::Condvar as StdCondvar;
+use prelude::HashMap;
+
#[cfg(feature = "backtrace")]
-use backtrace::Backtrace;
+use {prelude::hash_map, backtrace::Backtrace, std::sync::Once};
+
+#[cfg(not(feature = "backtrace"))]
+struct Backtrace{}
+#[cfg(not(feature = "backtrace"))]
+impl Backtrace { fn new() -> Backtrace { Backtrace {} } }
pub type LockResult<Guard> = Result<Guard, ()>;
thread_local! {
/// We track the set of locks currently held by a reference to their `LockMetadata`
- static LOCKS_HELD: RefCell<HashSet<Arc<LockMetadata>>> = RefCell::new(HashSet::new());
+ static LOCKS_HELD: RefCell<HashMap<u64, Arc<LockMetadata>>> = RefCell::new(HashMap::new());
}
static LOCK_IDX: AtomicUsize = AtomicUsize::new(0);
+#[cfg(feature = "backtrace")]
+static mut LOCKS: Option<StdMutex<HashMap<String, Arc<LockMetadata>>>> = None;
+#[cfg(feature = "backtrace")]
+static LOCKS_INIT: Once = Once::new();
+
/// Metadata about a single lock, by id, the set of things locked-before it, and the backtrace of
/// when the Mutex itself was constructed.
struct LockMetadata {
lock_idx: u64,
- locked_before: StdMutex<HashSet<Arc<LockMetadata>>>,
- #[cfg(feature = "backtrace")]
- lock_construction_bt: Backtrace,
+ locked_before: StdMutex<HashMap<u64, LockDep>>,
+ _lock_construction_bt: Backtrace,
}
-impl PartialEq for LockMetadata {
- fn eq(&self, o: &LockMetadata) -> bool { self.lock_idx == o.lock_idx }
+
+struct LockDep {
+ lock: Arc<LockMetadata>,
+ lockdep_trace: Backtrace,
}
-impl Eq for LockMetadata {}
-impl std::hash::Hash for LockMetadata {
- fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) { hasher.write_u64(self.lock_idx); }
+
+#[cfg(feature = "backtrace")]
+fn get_construction_location(backtrace: &Backtrace) -> String {
+ // Find the first frame that is after `debug_sync` (or that is in our tests) and use
+ // that as the mutex construction site. Note that the first few frames may be in
+ // the `backtrace` crate, so we have to ignore those.
+ let sync_mutex_constr_regex = regex::Regex::new(r"lightning.*debug_sync.*new").unwrap();
+ let mut found_debug_sync = false;
+ for frame in backtrace.frames() {
+ for symbol in frame.symbols() {
+ let symbol_name = symbol.name().unwrap().as_str().unwrap();
+ if !sync_mutex_constr_regex.is_match(symbol_name) {
+ if found_debug_sync {
+ if let Some(col) = symbol.colno() {
+ return format!("{}:{}:{}", symbol.filename().unwrap().display(), symbol.lineno().unwrap(), col);
+ } else {
+ // Windows debug symbols don't support column numbers, so fall back to
+ // line numbers only if no `colno` is available
+ return format!("{}:{}", symbol.filename().unwrap().display(), symbol.lineno().unwrap());
+ }
+ }
+ } else { found_debug_sync = true; }
+ }
+ }
+ panic!("Couldn't find mutex construction callsite");
}
impl LockMetadata {
- fn new() -> LockMetadata {
- LockMetadata {
- locked_before: StdMutex::new(HashSet::new()),
- lock_idx: LOCK_IDX.fetch_add(1, Ordering::Relaxed) as u64,
- #[cfg(feature = "backtrace")]
- lock_construction_bt: Backtrace::new(),
+ fn new() -> Arc<LockMetadata> {
+ let backtrace = Backtrace::new();
+ let lock_idx = LOCK_IDX.fetch_add(1, Ordering::Relaxed) as u64;
+
+ let res = Arc::new(LockMetadata {
+ locked_before: StdMutex::new(HashMap::new()),
+ lock_idx,
+ _lock_construction_bt: backtrace,
+ });
+
+ #[cfg(feature = "backtrace")]
+ {
+ let lock_constr_location = get_construction_location(&res._lock_construction_bt);
+ LOCKS_INIT.call_once(|| { unsafe { LOCKS = Some(StdMutex::new(HashMap::new())); } });
+ let mut locks = unsafe { LOCKS.as_ref() }.unwrap().lock().unwrap();
+ match locks.entry(lock_constr_location) {
+ hash_map::Entry::Occupied(e) => return Arc::clone(e.get()),
+ hash_map::Entry::Vacant(e) => { e.insert(Arc::clone(&res)); },
+ }
}
+ res
}
// Returns whether we were a recursive lock (only relevant for read)
// For each lock which is currently locked, check that no lock's locked-before
// set includes the lock we're about to lock, which would imply a lockorder
// inversion.
- for locked in held.borrow().iter() {
- if read && *locked == *this {
+ for (locked_idx, _locked) in held.borrow().iter() {
+ if read && *locked_idx == this.lock_idx {
// Recursive read locks are explicitly allowed
return;
}
}
- for locked in held.borrow().iter() {
- if !read && *locked == *this {
- panic!("Tried to lock a lock while it was held!");
+ for (locked_idx, locked) in held.borrow().iter() {
+ if !read && *locked_idx == this.lock_idx {
+ // With `feature = "backtrace"` set, we may be looking at different instances
+ // of the same lock.
+ debug_assert!(cfg!(feature = "backtrace"), "Tried to acquire a lock while it was held!");
}
- for locked_dep in locked.locked_before.lock().unwrap().iter() {
- if *locked_dep == *this {
+ for (locked_dep_idx, locked_dep) in locked.locked_before.lock().unwrap().iter() {
+ if *locked_dep_idx == this.lock_idx && *locked_dep_idx != locked.lock_idx {
#[cfg(feature = "backtrace")]
- panic!("Tried to violate existing lockorder.\nMutex that should be locked after the current lock was created at the following backtrace.\nNote that to get a backtrace for the lockorder violation, you should set RUST_BACKTRACE=1\n{:?}", locked.lock_construction_bt);
+ panic!("Tried to violate existing lockorder.\nMutex that should be locked after the current lock was created at the following backtrace.\nNote that to get a backtrace for the lockorder violation, you should set RUST_BACKTRACE=1\nLock being taken constructed at: {} ({}):\n{:?}\nLock constructed at: {} ({})\n{:?}\n\nLock dep created at:\n{:?}\n\n",
+ get_construction_location(&this._lock_construction_bt), this.lock_idx, this._lock_construction_bt,
+ get_construction_location(&locked._lock_construction_bt), locked.lock_idx, locked._lock_construction_bt,
+ locked_dep.lockdep_trace);
#[cfg(not(feature = "backtrace"))]
panic!("Tried to violate existing lockorder. Build with the backtrace feature for more info.");
}
}
// Insert any already-held locks in our locked-before set.
- this.locked_before.lock().unwrap().insert(Arc::clone(locked));
+ let mut locked_before = this.locked_before.lock().unwrap();
+ if !locked_before.contains_key(&locked.lock_idx) {
+ let lockdep = LockDep { lock: Arc::clone(locked), lockdep_trace: Backtrace::new() };
+ locked_before.insert(lockdep.lock.lock_idx, lockdep);
+ }
}
- held.borrow_mut().insert(Arc::clone(this));
+ held.borrow_mut().insert(this.lock_idx, Arc::clone(this));
inserted = true;
});
inserted
// Since a try-lock will simply fail if the lock is held already, we do not
// consider try-locks to ever generate lockorder inversions. However, if a try-lock
// succeeds, we do consider it to have created lockorder dependencies.
- for locked in held.borrow().iter() {
- this.locked_before.lock().unwrap().insert(Arc::clone(locked));
+ let mut locked_before = this.locked_before.lock().unwrap();
+ for (locked_idx, locked) in held.borrow().iter() {
+ if !locked_before.contains_key(locked_idx) {
+ let lockdep = LockDep { lock: Arc::clone(locked), lockdep_trace: Backtrace::new() };
+ locked_before.insert(*locked_idx, lockdep);
+ }
}
- held.borrow_mut().insert(Arc::clone(this));
+ held.borrow_mut().insert(this.lock_idx, Arc::clone(this));
});
}
}
impl<T: Sized> Drop for MutexGuard<'_, T> {
fn drop(&mut self) {
LOCKS_HELD.with(|held| {
- held.borrow_mut().remove(&self.mutex.deps);
+ held.borrow_mut().remove(&self.mutex.deps.lock_idx);
});
}
}
impl<T> Mutex<T> {
pub fn new(inner: T) -> Mutex<T> {
- Mutex { inner: StdMutex::new(inner), deps: Arc::new(LockMetadata::new()) }
+ Mutex { inner: StdMutex::new(inner), deps: LockMetadata::new() }
}
pub fn lock<'a>(&'a self) -> LockResult<MutexGuard<'a, T>> {
return;
}
LOCKS_HELD.with(|held| {
- held.borrow_mut().remove(&self.lock.deps);
+ held.borrow_mut().remove(&self.lock.deps.lock_idx);
});
}
}
impl<T: Sized> Drop for RwLockWriteGuard<'_, T> {
fn drop(&mut self) {
LOCKS_HELD.with(|held| {
- held.borrow_mut().remove(&self.lock.deps);
+ held.borrow_mut().remove(&self.lock.deps.lock_idx);
});
}
}
impl<T> RwLock<T> {
pub fn new(inner: T) -> RwLock<T> {
- RwLock { inner: StdRwLock::new(inner), deps: Arc::new(LockMetadata::new()) }
+ RwLock { inner: StdRwLock::new(inner), deps: LockMetadata::new() }
}
pub fn read<'a>(&'a self) -> LockResult<RwLockReadGuard<'a, T>> {
}
}
-#[test]
-#[should_panic]
-fn recursive_lock_fail() {
- let mutex = Mutex::new(());
- let _a = mutex.lock().unwrap();
- let _b = mutex.lock().unwrap();
-}
-
-#[test]
-fn recursive_read() {
- let lock = RwLock::new(());
- let _a = lock.read().unwrap();
- let _b = lock.read().unwrap();
-}
+pub type FairRwLock<T> = RwLock<T>;
-#[test]
-#[should_panic]
-fn lockorder_fail() {
- let a = Mutex::new(());
- let b = Mutex::new(());
- {
- let _a = a.lock().unwrap();
- let _b = b.lock().unwrap();
- }
- {
- let _b = b.lock().unwrap();
- let _a = a.lock().unwrap();
+mod tests {
+ use super::{RwLock, Mutex};
+
+ #[test]
+ #[should_panic]
+ #[cfg(not(feature = "backtrace"))]
+ fn recursive_lock_fail() {
+ let mutex = Mutex::new(());
+ let _a = mutex.lock().unwrap();
+ let _b = mutex.lock().unwrap();
+ }
+
+ #[test]
+ fn recursive_read() {
+ let lock = RwLock::new(());
+ let _a = lock.read().unwrap();
+ let _b = lock.read().unwrap();
+ }
+
+ #[test]
+ #[should_panic]
+ fn lockorder_fail() {
+ let a = Mutex::new(());
+ let b = Mutex::new(());
+ {
+ let _a = a.lock().unwrap();
+ let _b = b.lock().unwrap();
+ }
+ {
+ let _b = b.lock().unwrap();
+ let _a = a.lock().unwrap();
+ }
}
-}
-#[test]
-#[should_panic]
-fn write_lockorder_fail() {
- let a = RwLock::new(());
- let b = RwLock::new(());
- {
- let _a = a.write().unwrap();
- let _b = b.write().unwrap();
- }
- {
- let _b = b.write().unwrap();
- let _a = a.write().unwrap();
+ #[test]
+ #[should_panic]
+ fn write_lockorder_fail() {
+ let a = RwLock::new(());
+ let b = RwLock::new(());
+ {
+ let _a = a.write().unwrap();
+ let _b = b.write().unwrap();
+ }
+ {
+ let _b = b.write().unwrap();
+ let _a = a.write().unwrap();
+ }
}
-}
-#[test]
-#[should_panic]
-fn read_lockorder_fail() {
- let a = RwLock::new(());
- let b = RwLock::new(());
- {
- let _a = a.read().unwrap();
- let _b = b.read().unwrap();
- }
- {
- let _b = b.read().unwrap();
- let _a = a.read().unwrap();
+ #[test]
+ #[should_panic]
+ fn read_lockorder_fail() {
+ let a = RwLock::new(());
+ let b = RwLock::new(());
+ {
+ let _a = a.read().unwrap();
+ let _b = b.read().unwrap();
+ }
+ {
+ let _b = b.read().unwrap();
+ let _a = a.read().unwrap();
+ }
}
-}
-#[test]
-fn read_recurisve_no_lockorder() {
- // Like the above, but note that no lockorder is implied when we recursively read-lock a
- // RwLock, causing this to pass just fine.
- let a = RwLock::new(());
- let b = RwLock::new(());
- let _outer = a.read().unwrap();
- {
- let _a = a.read().unwrap();
- let _b = b.read().unwrap();
- }
- {
- let _b = b.read().unwrap();
- let _a = a.read().unwrap();
+ #[test]
+ fn read_recursive_no_lockorder() {
+ // Like the above, but note that no lockorder is implied when we recursively read-lock a
+ // RwLock, causing this to pass just fine.
+ let a = RwLock::new(());
+ let b = RwLock::new(());
+ let _outer = a.read().unwrap();
+ {
+ let _a = a.read().unwrap();
+ let _b = b.read().unwrap();
+ }
+ {
+ let _b = b.read().unwrap();
+ let _a = a.read().unwrap();
+ }
}
-}
-#[test]
-#[should_panic]
-fn read_write_lockorder_fail() {
- let a = RwLock::new(());
- let b = RwLock::new(());
- {
- let _a = a.write().unwrap();
- let _b = b.read().unwrap();
- }
- {
- let _b = b.read().unwrap();
- let _a = a.write().unwrap();
+ #[test]
+ #[should_panic]
+ fn read_write_lockorder_fail() {
+ let a = RwLock::new(());
+ let b = RwLock::new(());
+ {
+ let _a = a.write().unwrap();
+ let _b = b.read().unwrap();
+ }
+ {
+ let _b = b.read().unwrap();
+ let _a = a.write().unwrap();
+ }
}
}
-
-pub type FairRwLock<T> = RwLock<T>;
return Err(APIError::APIMisuseError { err: format!("Holder selected channel reserve below implemention limit dust_limit_satoshis {}", holder_selected_channel_reserve_satoshis) });
}
- let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
+ let feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
let value_to_self_msat = channel_value_satoshis * 1000 - push_msat;
let commitment_tx_fee = Self::commit_tx_fee_msat(feerate, MIN_AFFORDABLE_HTLC_COUNT, opt_anchors);
// We generally don't care too much if they set the feerate to something very high, but it
// could result in the channel being useless due to everything being dust.
let upper_limit = cmp::max(250 * 25,
- fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) as u64 * 10);
+ fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::HighPriority) as u64 * 10);
if feerate_per_kw as u64 > upper_limit {
return Err(ChannelError::Close(format!("Peer's feerate much too high. Actual: {}. Our expected upper limit: {}", feerate_per_kw, upper_limit)));
}
- let lower_limit = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
+ let lower_limit = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Background);
// Some fee estimators round up to the next full sat/vbyte (ie 250 sats per kw), causing
// occasional issues with feerate disagreements between an initiator that wants a feerate
// of 1.1 sat/vbyte and a receiver that wants 1.1 rounded up to 2. Thus, we always add 250
// Propose a range from our current Background feerate to our Normal feerate plus our
// force_close_avoidance_max_fee_satoshis.
// If we fail to come to consensus, we'll have to force-close.
- let mut proposed_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
- let normal_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
+ let mut proposed_feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Background);
+ let normal_feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
let mut proposed_max_feerate = if self.is_outbound() { normal_feerate } else { u32::max_value() };
// The spec requires that (when the channel does not have anchors) we only send absolute
use ln::channel::{Channel, InboundHTLCOutput, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator};
use ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS};
use ln::features::{InitFeatures, ChannelTypeFeatures};
- use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate};
+ use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate, MAX_VALUE_MSAT};
use ln::script::ShutdownScript;
use ln::chan_utils;
use ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight};
flags: 0,
cltv_expiry_delta: 100,
htlc_minimum_msat: 5,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 110,
fee_proportional_millionths: 11,
excess_data: Vec::new(),
use ln::msgs;
use ln::msgs::NetAddress;
use ln::onion_utils;
-use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, MAX_VALUE_MSAT, OptionalField};
+use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, MAX_VALUE_MSAT};
use ln::wire::Encode;
use chain::keysinterface::{Sign, KeysInterface, KeysManager, InMemorySigner, Recipient};
use util::config::{UserConfig, ChannelConfig};
flags: (!were_node_one) as u8 | ((!chan.is_live() as u8) << 1),
cltv_expiry_delta: chan.get_cltv_expiry_delta(),
htlc_minimum_msat: chan.get_counterparty_htlc_minimum_msat(),
- htlc_maximum_msat: OptionalField::Present(chan.get_announced_htlc_max_msat()),
+ htlc_maximum_msat: chan.get_announced_htlc_max_msat(),
fee_base_msat: chan.get_outbound_forwarding_fee_base_msat(),
fee_proportional_millionths: chan.get_fee_proportional_millionths(),
excess_data: Vec::new(),
PersistenceNotifierGuard::optionally_notify(&self.total_consistency_lock, &self.persistence_notifier, || {
let mut should_persist = NotifyOption::SkipPersist;
- let new_feerate = self.fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
+ let new_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
let mut handle_errors = Vec::new();
{
let mut should_persist = NotifyOption::SkipPersist;
if self.process_background_events() { should_persist = NotifyOption::DoPersist; }
- let new_feerate = self.fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
+ let new_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
let mut handle_errors = Vec::new();
let mut timed_out_mpp_htlcs = Vec::new();
}
}
+ let broadcaster = test_utils::TestBroadcaster {
+ txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()),
+ blocks: Arc::new(Mutex::new(self.tx_broadcaster.blocks.lock().unwrap().clone())),
+ };
+
// Before using all the new monitors to check the watch outpoints, use the full set of
// them to ensure we can write and reload our ChannelManager.
{
keys_manager: self.keys_manager,
fee_estimator: &test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) },
chain_monitor: self.chain_monitor,
- tx_broadcaster: &test_utils::TestBroadcaster {
- txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()),
- blocks: Arc::new(Mutex::new(self.tx_broadcaster.blocks.lock().unwrap().clone())),
- },
+ tx_broadcaster: &broadcaster,
logger: &self.logger,
channel_monitors,
}).unwrap();
}
let persister = test_utils::TestPersister::new();
- let broadcaster = test_utils::TestBroadcaster {
- txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()),
- blocks: Arc::new(Mutex::new(self.tx_broadcaster.blocks.lock().unwrap().clone())),
- };
let chain_source = test_utils::TestChainSource::new(Network::Testnet);
let chain_monitor = test_utils::TestChainMonitor::new(Some(&chain_source), &broadcaster, &self.logger, &feeest, &persister, &self.keys_manager);
for deserialized_monitor in deserialized_monitors.drain(..) {
use routing::router::{PaymentParameters, Route, RouteHop, RouteParameters, find_route, get_route};
use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
use ln::msgs;
-use ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, OptionalField, ErrorAction};
+use ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, ErrorAction};
use util::enforcing_trait_impls::EnforcingSigner;
use util::{byte_utils, test_utils};
use util::events::{Event, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose, ClosureReason};
check_added_monitors!(nodes[0], 1);
check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed);
- let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
assert_eq!(node_txn.len(), 3);
assert_eq!(node_txn[0], node_txn[1]);
check_added_monitors!(nodes[0], 1);
check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed);
- let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
assert_eq!(node_txn.len(), 1);
check_spends!(node_txn[0], chan.3);
assert_eq!(node_txn[0].output.len(), 2); // We can't force trimming of to_remote output as channel_reserve_satoshis block us to do so at channel opening
check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed);
connect_blocks(&nodes[0], TEST_FINAL_CLTV - 1); // Confirm blocks until the HTLC expires
- let revoked_htlc_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ let revoked_htlc_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
assert_eq!(revoked_htlc_txn.len(), 2);
check_spends!(revoked_htlc_txn[0], chan_1.3);
assert_eq!(revoked_htlc_txn[1].input.len(), 1);
check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed);
connect_blocks(&nodes[1], 49); // Confirm blocks until the HTLC expires (note CLTV was explicitly 50 above)
- let revoked_htlc_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ let revoked_htlc_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
assert_eq!(revoked_htlc_txn.len(), 3);
check_spends!(revoked_htlc_txn[1], chan.3);
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 mut guard = nodes[0].node.channel_state.lock().unwrap();
- let keys = guard.by_id.get_mut(&channel_id).unwrap().get_signer();
+ let per_commitment_secret;
+ let next_per_commitment_point;
+ {
+ let mut guard = nodes[0].node.channel_state.lock().unwrap();
+ let keys = guard.by_id.get_mut(&channel_id).unwrap().get_signer();
- const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
+ const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
- // Make signer believe we got a counterparty signature, so that it allows the revocation
- keys.get_enforcement_state().last_holder_commitment -= 1;
- let per_commitment_secret = keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER);
+ // Make signer believe we got a counterparty signature, so that it allows the revocation
+ keys.get_enforcement_state().last_holder_commitment -= 1;
+ per_commitment_secret = keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER);
- // Must revoke without gaps
- keys.get_enforcement_state().last_holder_commitment -= 1;
- keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 1);
+ // Must revoke without gaps
+ keys.get_enforcement_state().last_holder_commitment -= 1;
+ keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 1);
- keys.get_enforcement_state().last_holder_commitment -= 1;
- let next_per_commitment_point = PublicKey::from_secret_key(&Secp256k1::new(),
- &SecretKey::from_slice(&keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2)).unwrap());
+ keys.get_enforcement_state().last_holder_commitment -= 1;
+ next_per_commitment_point = PublicKey::from_secret_key(&Secp256k1::new(),
+ &SecretKey::from_slice(&keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2)).unwrap());
+ }
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(),
&msgs::RevokeAndACK { channel_id, per_commitment_secret, next_per_commitment_point });
// 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`.
- assert_eq!(node_0_chan_update.contents.htlc_maximum_msat, OptionalField::Present(channel_value_50_percent_msat));
+ assert_eq!(node_0_chan_update.contents.htlc_maximum_msat, channel_value_50_percent_msat);
// Assert that `node[1]`'s `ChannelUpdate` is capped at 30 percent of the `channel_value`, as
// that's the value of `node[0]`'s `holder_max_htlc_value_in_flight_msat`.
- assert_eq!(node_1_chan_update.contents.htlc_maximum_msat, OptionalField::Present(channel_value_30_percent_msat));
+ assert_eq!(node_1_chan_update.contents.htlc_maximum_msat, channel_value_30_percent_msat);
// Assert that `node[2]`'s `ChannelUpdate` is capped at 90 percent of the `channel_value`, as
// the value of `node[3]`'s `holder_max_htlc_value_in_flight_msat` (100%), exceeds 90% of the
// `channel_value`.
- assert_eq!(node_2_chan_update.contents.htlc_maximum_msat, OptionalField::Present(channel_value_90_percent_msat));
+ assert_eq!(node_2_chan_update.contents.htlc_maximum_msat, channel_value_90_percent_msat);
// Assert that `node[3]`'s `ChannelUpdate` is capped at 90 percent of the `channel_value`, as
// the value of `node[2]`'s `holder_max_htlc_value_in_flight_msat` (95%), exceeds 90% of the
// `channel_value`.
- assert_eq!(node_3_chan_update.contents.htlc_maximum_msat, OptionalField::Present(channel_value_90_percent_msat));
+ assert_eq!(node_3_chan_update.contents.htlc_maximum_msat, channel_value_90_percent_msat);
}
#[test]
// `MessageSendEvent::SendAcceptChannel` event. The message is passed to `nodes[0]`
// `handle_accept_channel`, which is required in order for `create_funding_transaction` to
// succeed when `nodes[0]` is passed to it.
- {
+ let accept_chan_msg = {
let mut lock;
let channel = get_channel_ref!(&nodes[1], lock, temp_channel_id);
- let accept_chan_msg = channel.get_accept_channel_message();
- nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_chan_msg);
- }
+ channel.get_accept_channel_message()
+ };
+ nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_chan_msg);
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
pub cltv_expiry_delta: u16,
/// The minimum HTLC size incoming to sender, in milli-satoshi
pub htlc_minimum_msat: u64,
- /// Optionally, the maximum HTLC value incoming to sender, in milli-satoshi
- pub htlc_maximum_msat: OptionalField<u64>,
+ /// The maximum HTLC value incoming to sender, in milli-satoshi. Used to be optional.
+ pub htlc_maximum_msat: u64,
/// The base HTLC fee charged by sender, in milli-satoshi
pub fee_base_msat: u32,
/// The amount to fee multiplier, in micro-satoshi
impl Writeable for UnsignedChannelUpdate {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
- let mut message_flags: u8 = 0;
- if let OptionalField::Present(_) = self.htlc_maximum_msat {
- message_flags = 1;
- }
+ // `message_flags` used to indicate presence of `htlc_maximum_msat`, but was deprecated in the spec.
+ const MESSAGE_FLAGS: u8 = 1;
self.chain_hash.write(w)?;
self.short_channel_id.write(w)?;
self.timestamp.write(w)?;
- let all_flags = self.flags as u16 | ((message_flags as u16) << 8);
+ let all_flags = self.flags as u16 | ((MESSAGE_FLAGS as u16) << 8);
all_flags.write(w)?;
self.cltv_expiry_delta.write(w)?;
self.htlc_minimum_msat.write(w)?;
impl Readable for UnsignedChannelUpdate {
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
- let has_htlc_maximum_msat;
Ok(Self {
chain_hash: Readable::read(r)?,
short_channel_id: Readable::read(r)?,
timestamp: Readable::read(r)?,
flags: {
let flags: u16 = Readable::read(r)?;
- let message_flags = flags >> 8;
- has_htlc_maximum_msat = (message_flags as i32 & 1) == 1;
+ // Note: we ignore the `message_flags` for now, since it was deprecated by the spec.
flags as u8
},
cltv_expiry_delta: Readable::read(r)?,
htlc_minimum_msat: Readable::read(r)?,
fee_base_msat: Readable::read(r)?,
fee_proportional_millionths: Readable::read(r)?,
- htlc_maximum_msat: if has_htlc_maximum_msat { Readable::read(r)? } else { OptionalField::Absent },
+ htlc_maximum_msat: Readable::read(r)?,
excess_data: read_to_end(r)?,
})
}
do_encoding_node_announcement(false, false, true, false, true, false, false, false);
}
- fn do_encoding_channel_update(direction: bool, disable: bool, htlc_maximum_msat: bool, excess_data: bool) {
+ fn do_encoding_channel_update(direction: bool, disable: bool, excess_data: bool) {
let secp_ctx = Secp256k1::new();
let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
flags: if direction { 1 } else { 0 } | if disable { 1 << 1 } else { 0 },
cltv_expiry_delta: 144,
htlc_minimum_msat: 1000000,
- htlc_maximum_msat: if htlc_maximum_msat { OptionalField::Present(131355275467161) } else { OptionalField::Absent },
+ htlc_maximum_msat: 131355275467161,
fee_base_msat: 10000,
fee_proportional_millionths: 20,
excess_data: if excess_data { vec![0, 0, 0, 0, 59, 154, 202, 0] } else { Vec::new() }
let mut target_value = hex::decode("d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a").unwrap();
target_value.append(&mut hex::decode("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f").unwrap());
target_value.append(&mut hex::decode("00083a840000034d013413a7").unwrap());
- if htlc_maximum_msat {
- target_value.append(&mut hex::decode("01").unwrap());
- } else {
- target_value.append(&mut hex::decode("00").unwrap());
- }
+ target_value.append(&mut hex::decode("01").unwrap());
target_value.append(&mut hex::decode("00").unwrap());
if direction {
let flag = target_value.last_mut().unwrap();
*flag = *flag | 1 << 1;
}
target_value.append(&mut hex::decode("009000000000000f42400000271000000014").unwrap());
- if htlc_maximum_msat {
- target_value.append(&mut hex::decode("0000777788889999").unwrap());
- }
+ target_value.append(&mut hex::decode("0000777788889999").unwrap());
if excess_data {
target_value.append(&mut hex::decode("000000003b9aca00").unwrap());
}
#[test]
fn encoding_channel_update() {
- do_encoding_channel_update(false, false, false, false);
- do_encoding_channel_update(false, false, false, true);
- do_encoding_channel_update(true, false, false, false);
- do_encoding_channel_update(true, false, false, true);
- do_encoding_channel_update(false, true, false, false);
- do_encoding_channel_update(false, true, false, true);
- do_encoding_channel_update(false, false, true, false);
- do_encoding_channel_update(false, false, true, true);
- do_encoding_channel_update(true, true, true, false);
- do_encoding_channel_update(true, true, true, true);
+ do_encoding_channel_update(false, false, false);
+ do_encoding_channel_update(false, false, true);
+ do_encoding_channel_update(true, false, false);
+ do_encoding_channel_update(true, false, true);
+ do_encoding_channel_update(false, true, false);
+ do_encoding_channel_update(false, true, true);
+ do_encoding_channel_update(true, true, false);
+ do_encoding_channel_update(true, true, true);
}
fn do_encoding_open_channel(random_bit: bool, shutdown: bool, incl_chan_type: bool) {
use routing::router::{get_route, PaymentParameters, Route, RouteHint, RouteHintHop};
use ln::features::{InitFeatures, InvoiceFeatures, NodeFeatures};
use ln::msgs;
-use ln::msgs::{ChannelMessageHandler, ChannelUpdate, OptionalField};
+use ln::msgs::{ChannelMessageHandler, ChannelUpdate};
use ln::wire::Encode;
use util::events::{Event, MessageSendEvent, MessageSendEventsProvider};
use util::ser::{ReadableArgs, Writeable, Writer};
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: msgs::MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: vec![],
/// peer using the init message.
/// The user should pass the remote network address of the host they are connected to.
///
- /// Note that if an Err is returned here you MUST NOT call socket_disconnected for the new
- /// descriptor but must disconnect the connection immediately.
+ /// If an `Err` is returned here you must disconnect the connection immediately.
///
/// Returns a small number of bytes to send to the remote node (currently always 50).
///
/// The user should pass the remote network address of the host they are connected to.
///
/// May refuse the connection by returning an Err, but will never write bytes to the remote end
- /// (outbound connector always speaks first). Note that if an Err is returned here you MUST NOT
- /// call socket_disconnected for the new descriptor but must disconnect the connection
- /// immediately.
+ /// (outbound connector always speaks first). If an `Err` is returned here you must disconnect
+ /// the connection immediately.
///
/// Panics if descriptor is duplicative with some other descriptor which has not yet been
/// [`socket_disconnected()`].
peer_a.new_inbound_connection(fd_a.clone(), None).unwrap();
assert_eq!(peer_a.read_event(&mut fd_a, &initial_data).unwrap(), false);
peer_a.process_events();
- assert_eq!(peer_b.read_event(&mut fd_b, &fd_a.outbound_data.lock().unwrap().split_off(0)).unwrap(), false);
+
+ let a_data = fd_a.outbound_data.lock().unwrap().split_off(0);
+ assert_eq!(peer_b.read_event(&mut fd_b, &a_data).unwrap(), false);
+
peer_b.process_events();
- assert_eq!(peer_a.read_event(&mut fd_a, &fd_b.outbound_data.lock().unwrap().split_off(0)).unwrap(), false);
+ let b_data = fd_b.outbound_data.lock().unwrap().split_off(0);
+ assert_eq!(peer_a.read_event(&mut fd_a, &b_data).unwrap(), false);
+
peer_a.process_events();
- assert_eq!(peer_b.read_event(&mut fd_b, &fd_a.outbound_data.lock().unwrap().split_off(0)).unwrap(), false);
+ let a_data = fd_a.outbound_data.lock().unwrap().split_off(0);
+ assert_eq!(peer_b.read_event(&mut fd_b, &a_data).unwrap(), false);
+
(fd_a.clone(), fd_b.clone())
}
assert_eq!(peers[0].read_event(&mut fd_a, &initial_data).unwrap(), false);
peers[0].process_events();
- assert_eq!(peers[1].read_event(&mut fd_b, &fd_a.outbound_data.lock().unwrap().split_off(0)).unwrap(), false);
+ let a_data = fd_a.outbound_data.lock().unwrap().split_off(0);
+ assert_eq!(peers[1].read_event(&mut fd_b, &a_data).unwrap(), false);
peers[1].process_events();
// ...but if we get a second timer tick, we should disconnect the peer
peers[0].timer_tick_occurred();
assert_eq!(peers[0].peers.read().unwrap().len(), 0);
- assert!(peers[0].read_event(&mut fd_a, &fd_b.outbound_data.lock().unwrap().split_off(0)).is_err());
+ let b_data = fd_b.outbound_data.lock().unwrap().split_off(0);
+ assert!(peers[0].read_event(&mut fd_a, &b_data).is_err());
}
#[test]
use routing::router::{PaymentParameters, RouteHint, RouteHintHop};
use ln::features::{InitFeatures, InvoiceFeatures, ChannelTypeFeatures};
use ln::msgs;
-use ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, OptionalField, ChannelUpdate, ErrorAction};
+use ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, ChannelUpdate, ErrorAction};
use ln::wire::Encode;
use util::enforcing_trait_impls::EnforcingSigner;
use util::events::{ClosureReason, Event, MessageSendEvent, MessageSendEventsProvider};
flags: 1,
cltv_expiry_delta: accept_forward_cfg.channel_config.cltv_expiry_delta,
htlc_minimum_msat: 1_000,
- htlc_maximum_msat: OptionalField::Present(1_000_000), // Defaults to 10% of the channel value
+ htlc_maximum_msat: 1_000_000, // Defaults to 10% of the channel value
fee_base_msat: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_base_msat,
fee_proportional_millionths: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_proportional_millionths,
excess_data: Vec::new(),
check_added_monitors!(nodes[2], 1);
check_closed_broadcast!(nodes[2], true); // We should get a BroadcastChannelUpdate (and *only* a BroadcstChannelUpdate)
check_closed_event!(nodes[2], 1, ClosureReason::CommitmentTxConfirmed);
- let node_2_commitment_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ let node_2_commitment_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
assert_eq!(node_2_commitment_txn.len(), 3); // ChannelMonitor: 1 offered HTLC-Claim, ChannelManger: 1 local commitment tx, 1 Received HTLC-Claim
assert_eq!(node_2_commitment_txn[1].output.len(), 2); // to-remote and Received HTLC (to-self is dust)
check_spends!(node_2_commitment_txn[1], chan_2.3);
use chain::Access;
use ln::features::{ChannelFeatures, NodeFeatures};
use ln::msgs::{DecodeError, ErrorAction, Init, LightningError, RoutingMessageHandler, NetAddress, MAX_VALUE_MSAT};
-use ln::msgs::{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, OptionalField, GossipTimestampFilter};
+use ln::msgs::{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, GossipTimestampFilter};
use ln::msgs::{QueryChannelRange, ReplyChannelRange, QueryShortChannelIds, ReplyShortChannelIdsEnd};
use ln::msgs;
-use util::ser::{Readable, ReadableArgs, Writeable, Writer};
+use util::ser::{Readable, ReadableArgs, Writeable, Writer, MaybeReadable};
use util::logger::{Logger, Level};
use util::events::{Event, EventHandler, MessageSendEvent, MessageSendEventsProvider};
use util::scid_utils::{block_from_scid, scid_from_parts, MAX_SCID_BLOCK};
use io;
+use io_extras::{copy, sink};
use prelude::*;
use alloc::collections::{BTreeMap, btree_map::Entry as BtreeEntry};
use core::{cmp, fmt};
/// The minimum value, which must be relayed to the next hop via the channel
pub htlc_minimum_msat: u64,
/// The maximum value which may be relayed to the next hop via the channel.
- pub htlc_maximum_msat: Option<u64>,
+ pub htlc_maximum_msat: u64,
/// Fees charged when the channel is used for routing
pub fees: RoutingFees,
/// Most recent update for the channel received from the network
}
}
-impl_writeable_tlv_based!(ChannelUpdateInfo, {
- (0, last_update, required),
- (2, enabled, required),
- (4, cltv_expiry_delta, required),
- (6, htlc_minimum_msat, required),
- (8, htlc_maximum_msat, required),
- (10, fees, required),
- (12, last_update_message, required),
-});
+impl Writeable for ChannelUpdateInfo {
+ fn write<W: ::util::ser::Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+ write_tlv_fields!(writer, {
+ (0, self.last_update, required),
+ (2, self.enabled, required),
+ (4, self.cltv_expiry_delta, required),
+ (6, self.htlc_minimum_msat, required),
+ // Writing htlc_maximum_msat as an Option<u64> is required to maintain backwards
+ // compatibility with LDK versions prior to v0.0.110.
+ (8, Some(self.htlc_maximum_msat), required),
+ (10, self.fees, required),
+ (12, self.last_update_message, required),
+ });
+ Ok(())
+ }
+}
+
+impl Readable for ChannelUpdateInfo {
+ fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+ init_tlv_field_var!(last_update, required);
+ init_tlv_field_var!(enabled, required);
+ init_tlv_field_var!(cltv_expiry_delta, required);
+ init_tlv_field_var!(htlc_minimum_msat, required);
+ init_tlv_field_var!(htlc_maximum_msat, option);
+ init_tlv_field_var!(fees, required);
+ init_tlv_field_var!(last_update_message, required);
+
+ read_tlv_fields!(reader, {
+ (0, last_update, required),
+ (2, enabled, required),
+ (4, cltv_expiry_delta, required),
+ (6, htlc_minimum_msat, required),
+ (8, htlc_maximum_msat, required),
+ (10, fees, required),
+ (12, last_update_message, required)
+ });
+
+ if let Some(htlc_maximum_msat) = htlc_maximum_msat {
+ Ok(ChannelUpdateInfo {
+ last_update: init_tlv_based_struct_field!(last_update, required),
+ enabled: init_tlv_based_struct_field!(enabled, required),
+ cltv_expiry_delta: init_tlv_based_struct_field!(cltv_expiry_delta, required),
+ htlc_minimum_msat: init_tlv_based_struct_field!(htlc_minimum_msat, required),
+ htlc_maximum_msat,
+ fees: init_tlv_based_struct_field!(fees, required),
+ last_update_message: init_tlv_based_struct_field!(last_update_message, required),
+ })
+ } else {
+ Err(DecodeError::InvalidValue)
+ }
+ }
+}
#[derive(Clone, Debug, PartialEq)]
/// Details about a channel (both directions).
}
}
-impl_writeable_tlv_based!(ChannelInfo, {
- (0, features, required),
- (1, announcement_received_time, (default_value, 0)),
- (2, node_one, required),
- (4, one_to_two, required),
- (6, node_two, required),
- (8, two_to_one, required),
- (10, capacity_sats, required),
- (12, announcement_message, required),
-});
+impl Writeable for ChannelInfo {
+ fn write<W: ::util::ser::Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+ write_tlv_fields!(writer, {
+ (0, self.features, required),
+ (1, self.announcement_received_time, (default_value, 0)),
+ (2, self.node_one, required),
+ (4, self.one_to_two, required),
+ (6, self.node_two, required),
+ (8, self.two_to_one, required),
+ (10, self.capacity_sats, required),
+ (12, self.announcement_message, required),
+ });
+ Ok(())
+ }
+}
+
+// A wrapper allowing for the optional deseralization of ChannelUpdateInfo. Utilizing this is
+// necessary to maintain backwards compatibility with previous serializations of `ChannelUpdateInfo`
+// that may have no `htlc_maximum_msat` field set. In case the field is absent, we simply ignore
+// the error and continue reading the `ChannelInfo`. Hopefully, we'll then eventually receive newer
+// channel updates via the gossip network.
+struct ChannelUpdateInfoDeserWrapper(Option<ChannelUpdateInfo>);
+
+impl MaybeReadable for ChannelUpdateInfoDeserWrapper {
+ fn read<R: io::Read>(reader: &mut R) -> Result<Option<Self>, DecodeError> {
+ match ::util::ser::Readable::read(reader) {
+ Ok(channel_update_option) => Ok(Some(Self(channel_update_option))),
+ Err(DecodeError::ShortRead) => Ok(None),
+ Err(DecodeError::InvalidValue) => Ok(None),
+ Err(err) => Err(err),
+ }
+ }
+}
+
+impl Readable for ChannelInfo {
+ fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+ init_tlv_field_var!(features, required);
+ init_tlv_field_var!(announcement_received_time, (default_value, 0));
+ init_tlv_field_var!(node_one, required);
+ let mut one_to_two_wrap: Option<ChannelUpdateInfoDeserWrapper> = None;
+ init_tlv_field_var!(node_two, required);
+ let mut two_to_one_wrap: Option<ChannelUpdateInfoDeserWrapper> = None;
+ init_tlv_field_var!(capacity_sats, required);
+ init_tlv_field_var!(announcement_message, required);
+ read_tlv_fields!(reader, {
+ (0, features, required),
+ (1, announcement_received_time, (default_value, 0)),
+ (2, node_one, required),
+ (4, one_to_two_wrap, ignorable),
+ (6, node_two, required),
+ (8, two_to_one_wrap, ignorable),
+ (10, capacity_sats, required),
+ (12, announcement_message, required),
+ });
+
+ Ok(ChannelInfo {
+ features: init_tlv_based_struct_field!(features, required),
+ node_one: init_tlv_based_struct_field!(node_one, required),
+ one_to_two: one_to_two_wrap.map(|w| w.0).unwrap_or(None),
+ node_two: init_tlv_based_struct_field!(node_two, required),
+ two_to_one: two_to_one_wrap.map(|w| w.0).unwrap_or(None),
+ capacity_sats: init_tlv_based_struct_field!(capacity_sats, required),
+ announcement_message: init_tlv_based_struct_field!(announcement_message, required),
+ announcement_received_time: init_tlv_based_struct_field!(announcement_received_time, (default_value, 0)),
+ })
+ }
+}
/// A wrapper around [`ChannelInfo`] representing information about the channel as directed from a
/// source node to a target node.
impl<'a> DirectedChannelInfo<'a> {
#[inline]
fn new(channel: &'a ChannelInfo, direction: Option<&'a ChannelUpdateInfo>) -> Self {
- let htlc_maximum_msat = direction.and_then(|direction| direction.htlc_maximum_msat);
+ let htlc_maximum_msat = direction.map(|direction| direction.htlc_maximum_msat);
let capacity_msat = channel.capacity_sats.map(|capacity_sats| capacity_sats * 1000);
let (htlc_maximum_msat, effective_capacity) = match (htlc_maximum_msat, capacity_msat) {
}
}
-impl_writeable_tlv_based!(NodeInfo, {
- (0, lowest_inbound_channel_fees, option),
- (2, announcement_info, option),
- (4, channels, vec_type),
-});
+impl Writeable for NodeInfo {
+ fn write<W: ::util::ser::Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+ write_tlv_fields!(writer, {
+ (0, self.lowest_inbound_channel_fees, option),
+ (2, self.announcement_info, option),
+ (4, self.channels, vec_type),
+ });
+ Ok(())
+ }
+}
+
+// A wrapper allowing for the optional deseralization of `NodeAnnouncementInfo`. Utilizing this is
+// necessary to maintain compatibility with previous serializations of `NetAddress` that have an
+// invalid hostname set. We ignore and eat all errors until we are either able to read a
+// `NodeAnnouncementInfo` or hit a `ShortRead`, i.e., read the TLV field to the end.
+struct NodeAnnouncementInfoDeserWrapper(NodeAnnouncementInfo);
+
+impl MaybeReadable for NodeAnnouncementInfoDeserWrapper {
+ fn read<R: io::Read>(reader: &mut R) -> Result<Option<Self>, DecodeError> {
+ match ::util::ser::Readable::read(reader) {
+ Ok(node_announcement_info) => return Ok(Some(Self(node_announcement_info))),
+ Err(_) => {
+ copy(reader, &mut sink()).unwrap();
+ return Ok(None)
+ },
+ };
+ }
+}
+
+impl Readable for NodeInfo {
+ fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+ init_tlv_field_var!(lowest_inbound_channel_fees, option);
+ let mut announcement_info_wrap: Option<NodeAnnouncementInfoDeserWrapper> = None;
+ init_tlv_field_var!(channels, vec_type);
+
+ read_tlv_fields!(reader, {
+ (0, lowest_inbound_channel_fees, option),
+ (2, announcement_info_wrap, ignorable),
+ (4, channels, vec_type),
+ });
+
+ Ok(NodeInfo {
+ lowest_inbound_channel_fees: init_tlv_based_struct_field!(lowest_inbound_channel_fees, option),
+ announcement_info: announcement_info_wrap.map(|w| w.0),
+ channels: init_tlv_based_struct_field!(channels, vec_type),
+ })
+ }
+}
const SERIALIZATION_VERSION: u8 = 1;
const MIN_SERIALIZATION_VERSION: u8 = 1;
match channels.get_mut(&msg.short_channel_id) {
None => return Err(LightningError{err: "Couldn't find channel for update".to_owned(), action: ErrorAction::IgnoreError}),
Some(channel) => {
- if let OptionalField::Present(htlc_maximum_msat) = msg.htlc_maximum_msat {
- if htlc_maximum_msat > MAX_VALUE_MSAT {
- return Err(LightningError{err: "htlc_maximum_msat is larger than maximum possible msats".to_owned(), action: ErrorAction::IgnoreError});
- }
+ if msg.htlc_maximum_msat > MAX_VALUE_MSAT {
+ return Err(LightningError{err:
+ "htlc_maximum_msat is larger than maximum possible msats".to_owned(),
+ action: ErrorAction::IgnoreError});
+ }
- if let Some(capacity_sats) = channel.capacity_sats {
- // It's possible channel capacity is available now, although it wasn't available at announcement (so the field is None).
- // Don't query UTXO set here to reduce DoS risks.
- if capacity_sats > MAX_VALUE_MSAT / 1000 || htlc_maximum_msat > capacity_sats * 1000 {
- return Err(LightningError{err: "htlc_maximum_msat is larger than channel capacity or capacity is bogus".to_owned(), action: ErrorAction::IgnoreError});
- }
+ if let Some(capacity_sats) = channel.capacity_sats {
+ // It's possible channel capacity is available now, although it wasn't available at announcement (so the field is None).
+ // Don't query UTXO set here to reduce DoS risks.
+ if capacity_sats > MAX_VALUE_MSAT / 1000 || msg.htlc_maximum_msat > capacity_sats * 1000 {
+ return Err(LightningError{err:
+ "htlc_maximum_msat is larger than channel capacity or capacity is bogus".to_owned(),
+ action: ErrorAction::IgnoreError});
}
}
macro_rules! check_update_latest {
last_update: msg.timestamp,
cltv_expiry_delta: msg.cltv_expiry_delta,
htlc_minimum_msat: msg.htlc_minimum_msat,
- htlc_maximum_msat: if let OptionalField::Present(max_value) = msg.htlc_maximum_msat { Some(max_value) } else { None },
+ htlc_maximum_msat: msg.htlc_maximum_msat,
fees: RoutingFees {
base_msat: msg.fee_base_msat,
proportional_millionths: msg.fee_proportional_millionths,
use chain;
use ln::PaymentHash;
use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
- use routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate, NodeAlias, MAX_EXCESS_BYTES_FOR_RELAY};
- use ln::msgs::{Init, OptionalField, RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
+ 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,
UnsignedChannelAnnouncement, ChannelAnnouncement, UnsignedChannelUpdate, ChannelUpdate,
ReplyChannelRange, QueryChannelRange, QueryShortChannelIds, MAX_VALUE_MSAT};
use util::test_utils;
flags: 0,
cltv_expiry_delta: 144,
htlc_minimum_msat: 1_000_000,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: 1_000_000,
fee_base_msat: 10_000,
fee_proportional_millionths: 20,
excess_data: Vec::new()
let valid_channel_update = get_signed_channel_update(|_| {}, node_1_privkey, &secp_ctx);
match gossip_sync.handle_channel_update(&valid_channel_update) {
Ok(res) => assert!(res),
- _ => panic!()
+ _ => panic!(),
};
{
};
let valid_channel_update = get_signed_channel_update(|unsigned_channel_update| {
- unsigned_channel_update.htlc_maximum_msat = OptionalField::Present(MAX_VALUE_MSAT + 1);
+ unsigned_channel_update.htlc_maximum_msat = MAX_VALUE_MSAT + 1;
unsigned_channel_update.timestamp += 110;
}, node_1_privkey, &secp_ctx);
match gossip_sync.handle_channel_update(&valid_channel_update) {
};
let valid_channel_update = get_signed_channel_update(|unsigned_channel_update| {
- unsigned_channel_update.htlc_maximum_msat = OptionalField::Present(amount_sats * 1000 + 1);
+ unsigned_channel_update.htlc_maximum_msat = amount_sats * 1000 + 1;
unsigned_channel_update.timestamp += 110;
}, node_1_privkey, &secp_ctx);
match gossip_sync.handle_channel_update(&valid_channel_update) {
assert_eq!(format_bytes_alias(b"\xFFI <heart>\0LDK!"), "\u{FFFD}I <heart>");
assert_eq!(format_bytes_alias(b"\xFFI <heart>\tLDK!"), "\u{FFFD}I <heart>\u{FFFD}LDK!");
}
+
+ #[test]
+ fn channel_info_is_readable() {
+ let chanmon_cfgs = ::ln::functional_test_utils::create_chanmon_cfgs(2);
+ let node_cfgs = ::ln::functional_test_utils::create_node_cfgs(2, &chanmon_cfgs);
+ let node_chanmgrs = ::ln::functional_test_utils::create_node_chanmgrs(2, &node_cfgs, &[None, None, None, None]);
+ let nodes = ::ln::functional_test_utils::create_network(2, &node_cfgs, &node_chanmgrs);
+
+ // 1. Test encoding/decoding of ChannelUpdateInfo
+ let chan_update_info = ChannelUpdateInfo {
+ last_update: 23,
+ enabled: true,
+ cltv_expiry_delta: 42,
+ htlc_minimum_msat: 1234,
+ htlc_maximum_msat: 5678,
+ fees: RoutingFees { base_msat: 9, proportional_millionths: 10 },
+ last_update_message: None,
+ };
+
+ let mut encoded_chan_update_info: Vec<u8> = Vec::new();
+ assert!(chan_update_info.write(&mut encoded_chan_update_info).is_ok());
+
+ // First make sure we can read ChannelUpdateInfos we just wrote
+ let read_chan_update_info: ChannelUpdateInfo = ::util::ser::Readable::read(&mut encoded_chan_update_info.as_slice()).unwrap();
+ assert_eq!(chan_update_info, read_chan_update_info);
+
+ // Check the serialization hasn't changed.
+ let legacy_chan_update_info_with_some: Vec<u8> = hex::decode("340004000000170201010402002a060800000000000004d2080909000000000000162e0a0d0c00040000000902040000000a0c0100").unwrap();
+ assert_eq!(encoded_chan_update_info, legacy_chan_update_info_with_some);
+
+ // Check we fail if htlc_maximum_msat is not present in either the ChannelUpdateInfo itself
+ // or the ChannelUpdate enclosed with `last_update_message`.
+ let legacy_chan_update_info_with_some_and_fail_update: Vec<u8> = hex::decode("b40004000000170201010402002a060800000000000004d2080909000000000000162e0a0d0c00040000000902040000000a0c8181d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f00083a840000034d013413a70000009000000000000f42400000271000000014").unwrap();
+ let read_chan_update_info_res: Result<ChannelUpdateInfo, ::ln::msgs::DecodeError> = ::util::ser::Readable::read(&mut legacy_chan_update_info_with_some_and_fail_update.as_slice());
+ assert!(read_chan_update_info_res.is_err());
+
+ let legacy_chan_update_info_with_none: Vec<u8> = hex::decode("2c0004000000170201010402002a060800000000000004d20801000a0d0c00040000000902040000000a0c0100").unwrap();
+ let read_chan_update_info_res: Result<ChannelUpdateInfo, ::ln::msgs::DecodeError> = ::util::ser::Readable::read(&mut legacy_chan_update_info_with_none.as_slice());
+ assert!(read_chan_update_info_res.is_err());
+
+ // 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(),
+ 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()),
+ two_to_one: None,
+ capacity_sats: None,
+ announcement_message: None,
+ announcement_received_time: 87654,
+ };
+
+ let mut encoded_chan_info: Vec<u8> = Vec::new();
+ assert!(chan_info_none_updates.write(&mut encoded_chan_info).is_ok());
+
+ let read_chan_info: ChannelInfo = ::util::ser::Readable::read(&mut encoded_chan_info.as_slice()).unwrap();
+ assert_eq!(chan_info_none_updates, read_chan_info);
+
+ // Check we can encode/decode ChannelInfo with ChannelUpdateInfo fields present.
+ let chan_info_some_updates = ChannelInfo {
+ features: ChannelFeatures::known(),
+ 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()),
+ two_to_one: Some(chan_update_info.clone()),
+ capacity_sats: None,
+ announcement_message: None,
+ announcement_received_time: 87654,
+ };
+
+ let mut encoded_chan_info: Vec<u8> = Vec::new();
+ assert!(chan_info_some_updates.write(&mut encoded_chan_info).is_ok());
+
+ let read_chan_info: ChannelInfo = ::util::ser::Readable::read(&mut encoded_chan_info.as_slice()).unwrap();
+ assert_eq!(chan_info_some_updates, read_chan_info);
+
+ // Check the serialization hasn't changed.
+ let legacy_chan_info_with_some: Vec<u8> = hex::decode("ca00020000010800000000000156660221027f921585f2ac0c7c70e36110adecfd8fd14b8a99bfb3d000a283fcac358fce88043636340004000000170201010402002a060800000000000004d2080909000000000000162e0a0d0c00040000000902040000000a0c010006210355f8d2238a322d16b602bd0ceaad5b01019fb055971eaadcc9b29226a4da6c23083636340004000000170201010402002a060800000000000004d2080909000000000000162e0a0d0c00040000000902040000000a0c01000a01000c0100").unwrap();
+ assert_eq!(encoded_chan_info, legacy_chan_info_with_some);
+
+ // Check we can decode legacy ChannelInfo, even if the `two_to_one` / `one_to_two` /
+ // `last_update_message` fields fail to decode due to missing htlc_maximum_msat.
+ let legacy_chan_info_with_some_and_fail_update = hex::decode("fd01ca00020000010800000000000156660221027f921585f2ac0c7c70e36110adecfd8fd14b8a99bfb3d000a283fcac358fce8804b6b6b40004000000170201010402002a060800000000000004d2080909000000000000162e0a0d0c00040000000902040000000a0c8181d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f00083a840000034d013413a70000009000000000000f4240000027100000001406210355f8d2238a322d16b602bd0ceaad5b01019fb055971eaadcc9b29226a4da6c2308b6b6b40004000000170201010402002a060800000000000004d2080909000000000000162e0a0d0c00040000000902040000000a0c8181d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f00083a840000034d013413a70000009000000000000f424000002710000000140a01000c0100").unwrap();
+ let read_chan_info: ChannelInfo = ::util::ser::Readable::read(&mut legacy_chan_info_with_some_and_fail_update.as_slice()).unwrap();
+ assert_eq!(read_chan_info.announcement_received_time, 87654);
+ assert_eq!(read_chan_info.one_to_two, None);
+ assert_eq!(read_chan_info.two_to_one, None);
+
+ let legacy_chan_info_with_none: Vec<u8> = hex::decode("ba00020000010800000000000156660221027f921585f2ac0c7c70e36110adecfd8fd14b8a99bfb3d000a283fcac358fce88042e2e2c0004000000170201010402002a060800000000000004d20801000a0d0c00040000000902040000000a0c010006210355f8d2238a322d16b602bd0ceaad5b01019fb055971eaadcc9b29226a4da6c23082e2e2c0004000000170201010402002a060800000000000004d20801000a0d0c00040000000902040000000a0c01000a01000c0100").unwrap();
+ let read_chan_info: ChannelInfo = ::util::ser::Readable::read(&mut legacy_chan_info_with_none.as_slice()).unwrap();
+ assert_eq!(read_chan_info.announcement_received_time, 87654);
+ assert_eq!(read_chan_info.one_to_two, None);
+ assert_eq!(read_chan_info.two_to_one, None);
+ }
+
+ #[test]
+ fn node_info_is_readable() {
+ use std::convert::TryFrom;
+
+ // 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(),
+ last_update: 0,
+ rgb: [0u8; 3],
+ alias: NodeAlias([0u8; 32]),
+ addresses: vec![valid_netaddr],
+ announcement_message: None,
+ };
+
+ let mut encoded_valid_node_ann_info = Vec::new();
+ assert!(valid_node_ann_info.write(&mut encoded_valid_node_ann_info).is_ok());
+ let read_valid_node_ann_info: NodeAnnouncementInfo = ::util::ser::Readable::read(&mut encoded_valid_node_ann_info.as_slice()).unwrap();
+ assert_eq!(read_valid_node_ann_info, valid_node_ann_info);
+
+ let encoded_invalid_node_ann_info = hex::decode("3f0009000788a000080a51a20204000000000403000000062000000000000000000000000000000000000000000000000000000000000000000a0505014004d2").unwrap();
+ let read_invalid_node_ann_info_res: Result<NodeAnnouncementInfo, ::ln::msgs::DecodeError> = ::util::ser::Readable::read(&mut encoded_invalid_node_ann_info.as_slice());
+ assert!(read_invalid_node_ann_info_res.is_err());
+
+ // 2. Check we can read a NodeInfo anyways, but set the NodeAnnouncementInfo to None if invalid
+ let valid_node_info = NodeInfo {
+ channels: Vec::new(),
+ lowest_inbound_channel_fees: None,
+ announcement_info: Some(valid_node_ann_info),
+ };
+
+ let mut encoded_valid_node_info = Vec::new();
+ assert!(valid_node_info.write(&mut encoded_valid_node_info).is_ok());
+ let read_valid_node_info: NodeInfo = ::util::ser::Readable::read(&mut encoded_valid_node_info.as_slice()).unwrap();
+ assert_eq!(read_valid_node_info, valid_node_info);
+
+ let encoded_invalid_node_info_hex = hex::decode("4402403f0009000788a000080a51a20204000000000403000000062000000000000000000000000000000000000000000000000000000000000000000a0505014004d20400").unwrap();
+ let read_invalid_node_info: NodeInfo = ::util::ser::Readable::read(&mut encoded_invalid_node_info_hex.as_slice()).unwrap();
+ assert_eq!(read_invalid_node_info.announcement_info, None);
+ }
}
#[cfg(all(test, feature = "_bench_unstable"))]
use chain::transaction::OutPoint;
use chain::keysinterface::KeysInterface;
use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
- use ln::msgs::{ErrorAction, LightningError, OptionalField, UnsignedChannelAnnouncement, ChannelAnnouncement, RoutingMessageHandler,
- NodeAnnouncement, UnsignedNodeAnnouncement, ChannelUpdate, UnsignedChannelUpdate};
+ use ln::msgs::{ErrorAction, LightningError, UnsignedChannelAnnouncement, ChannelAnnouncement, RoutingMessageHandler,
+ NodeAnnouncement, UnsignedNodeAnnouncement, ChannelUpdate, UnsignedChannelUpdate, MAX_VALUE_MSAT};
use ln::channelmanager;
use util::test_utils;
use util::chacha20::ChaCha20;
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 1,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 1,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (5 << 4) | 3,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: u32::max_value(),
fee_proportional_millionths: u32::max_value(),
excess_data: Vec::new()
flags: 1,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (5 << 4) | 3,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: u32::max_value(),
fee_proportional_millionths: u32::max_value(),
excess_data: Vec::new()
flags: 1,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (3 << 4) | 1,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 1,
cltv_expiry_delta: (3 << 4) | 2,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 100,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (4 << 4) | 1,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 1000000,
excess_data: Vec::new()
flags: 1,
cltv_expiry_delta: (4 << 4) | 2,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (13 << 4) | 1,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 2000000,
excess_data: Vec::new()
flags: 1,
cltv_expiry_delta: (13 << 4) | 2,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (6 << 4) | 1,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 1,
cltv_expiry_delta: (6 << 4) | 2,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new(),
flags: 0,
cltv_expiry_delta: (11 << 4) | 1,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 1,
cltv_expiry_delta: (11 << 4) | 2,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (7 << 4) | 1,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 1000000,
excess_data: Vec::new()
flags: 1,
cltv_expiry_delta: (7 << 4) | 2,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2, // to disable
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2, // to disable
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2, // to disable
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2, // to disable
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2, // to disable
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 200_000_000,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(199_999_999),
+ htlc_maximum_msat: 199_999_999,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 35_000,
- htlc_maximum_msat: OptionalField::Present(40_000),
+ htlc_maximum_msat: 40_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 35_000,
- htlc_maximum_msat: OptionalField::Present(40_000),
+ htlc_maximum_msat: 40_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2, // to disable
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 65_000,
- htlc_maximum_msat: OptionalField::Present(80_000),
+ htlc_maximum_msat: 80_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 100_000,
excess_data: Vec::new()
flags: 2, // to disable
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2, // to disable
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2, // to disable
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2, // to disable
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2, // to disable
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2, // to disable
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(1_000_000_000),
+ htlc_maximum_msat: 1_000_000_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: 250_000_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(1_000_000_000),
+ htlc_maximum_msat: 1_000_000_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(1_000_000_000),
+ htlc_maximum_msat: 1_000_000_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(15_000),
+ htlc_maximum_msat: 15_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (3 << 4) | 1,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: 15_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 1,
cltv_expiry_delta: (3 << 4) | 2,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: 15_000,
fee_base_msat: 100,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(10_000),
+ htlc_maximum_msat: 10_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(50_000),
+ htlc_maximum_msat: 50_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 1_000_000,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(50_000),
+ htlc_maximum_msat: 50_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(50_000),
+ htlc_maximum_msat: 50_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(60_000),
+ htlc_maximum_msat: 60_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(60_000),
+ htlc_maximum_msat: 60_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(200_000),
+ htlc_maximum_msat: 200_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(180_000),
+ htlc_maximum_msat: 180_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(200_000),
+ htlc_maximum_msat: 200_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(200_000),
+ htlc_maximum_msat: 200_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(200_000),
+ htlc_maximum_msat: 200_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(200_000),
+ htlc_maximum_msat: 200_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(200_000),
+ htlc_maximum_msat: 200_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(200_000),
+ htlc_maximum_msat: 200_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 1_000,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 2,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(250_000),
+ htlc_maximum_msat: 250_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 150_000,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (5 << 4) | 5,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(99_000),
+ htlc_maximum_msat: 99_000,
fee_base_msat: u32::max_value(),
fee_proportional_millionths: u32::max_value(),
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (5 << 4) | 3,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(99_000),
+ htlc_maximum_msat: 99_000,
fee_base_msat: u32::max_value(),
fee_proportional_millionths: u32::max_value(),
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (4 << 4) | 1,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 1,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0|2, // Channel disabled
cltv_expiry_delta: (13 << 4) | 1,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 2000000,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(100_000),
+ htlc_maximum_msat: 100_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(50_000),
+ htlc_maximum_msat: 50_000,
fee_base_msat: 100,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(60_000),
+ htlc_maximum_msat: 60_000,
fee_base_msat: 100,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(60_000),
+ htlc_maximum_msat: 60_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(20_000),
+ htlc_maximum_msat: 20_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(20_000),
+ htlc_maximum_msat: 20_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (6 << 4) | 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (5 << 4) | 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 100,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (4 << 4) | 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (3 << 4) | 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (2 << 4) | 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (1 << 4) | 0,
htlc_minimum_msat: 100,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(85_000),
+ htlc_maximum_msat: 85_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (4 << 4) | 1,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(270_000),
+ htlc_maximum_msat: 270_000,
fee_base_msat: 0,
fee_proportional_millionths: 1000000,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(80_000),
+ htlc_maximum_msat: 80_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (4 << 4) | 1,
htlc_minimum_msat: 90_000,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (4 << 4) | 1,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(250_000_000),
+ htlc_maximum_msat: 250_000_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
flags: 0,
cltv_expiry_delta: (13 << 4) | 1,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(250_000_000),
+ htlc_maximum_msat: 250_000_000,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: Vec::new()
use util::time::tests::SinceEpoch;
use ln::features::{ChannelFeatures, NodeFeatures};
- use ln::msgs::{ChannelAnnouncement, ChannelUpdate, OptionalField, UnsignedChannelAnnouncement, UnsignedChannelUpdate};
+ use ln::msgs::{ChannelAnnouncement, ChannelUpdate, UnsignedChannelAnnouncement, UnsignedChannelUpdate};
use routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId};
use routing::router::RouteHop;
use routing::scoring::{ChannelUsage, Score};
flags,
cltv_expiry_delta: 18,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Present(1_000),
+ htlc_maximum_msat: 1_000,
fee_base_msat: 1,
fee_proportional_millionths: 0,
excess_data: Vec::new(),
use chain::keysinterface;
use ln::features::{ChannelFeatures, InitFeatures};
use ln::{msgs, wire};
-use ln::msgs::OptionalField;
use ln::script::ShutdownScript;
use routing::scoring::FixedPenaltyScorer;
use util::enforcing_trait_impls::{EnforcingSigner, EnforcementState};
flags: 0,
cltv_expiry_delta: 0,
htlc_minimum_msat: 0,
- htlc_maximum_msat: OptionalField::Absent,
+ htlc_maximum_msat: msgs::MAX_VALUE_MSAT,
fee_base_msat: 0,
fee_proportional_millionths: 0,
excess_data: vec![],