res
} };
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $failed_forwards: expr, $failed_fails: expr) => {
- handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, $failed_forwards, $failed_fails, Vec::new());
+ handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, $failed_forwards, $failed_fails, Vec::new())
}
}
let peer_state = peer_state.lock().unwrap();
let their_features = &peer_state.latest_features;
let config = if override_config.is_some() { override_config.as_ref().unwrap() } else { &self.default_configuration };
- Channel::new_outbound(&self.fee_estimator, &self.keys_manager, their_network_key, their_features, channel_value_satoshis, push_msat, user_channel_id, config)?
+ Channel::new_outbound(&self.fee_estimator, &self.keys_manager, their_network_key, their_features,
+ channel_value_satoshis, push_msat, user_channel_id, config, self.best_block.read().unwrap().height())?
},
None => return Err(APIError::ChannelUnavailable { err: format!("Not connected to node: {}", their_network_key) }),
}
break Some(("Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta", 0x1000 | 13, Some(self.get_channel_update_for_unicast(chan).unwrap())));
}
let cur_height = self.best_block.read().unwrap().height() + 1;
- // Theoretically, channel counterparty shouldn't send us a HTLC expiring now, but we want to be robust wrt to counterparty
- // packet sanitization (see HTLC_FAIL_BACK_BUFFER rational)
+ // Theoretically, channel counterparty shouldn't send us a HTLC expiring now,
+ // but we want to be robust wrt to counterparty packet sanitization (see
+ // HTLC_FAIL_BACK_BUFFER rationale).
if msg.cltv_expiry <= cur_height + HTLC_FAIL_BACK_BUFFER as u32 { // expiry_too_soon
break Some(("CLTV expiry is too close", 0x1000 | 14, Some(self.get_channel_update_for_unicast(chan).unwrap())));
}
if msg.cltv_expiry > cur_height + CLTV_FAR_FAR_AWAY as u32 { // expiry_too_far
break Some(("CLTV expiry is too far in the future", 21, None));
}
- // In theory, we would be safe against unintentional channel-closure, if we only required a margin of LATENCY_GRACE_PERIOD_BLOCKS.
- // But, to be safe against policy reception, we use a longer delay.
- if (*outgoing_cltv_value) as u64 <= (cur_height + HTLC_FAIL_BACK_BUFFER) as u64 {
+ // If the HTLC expires ~now, don't bother trying to forward it to our
+ // counterparty. They should fail it anyway, but we don't want to bother with
+ // the round-trips or risk them deciding they definitely want the HTLC and
+ // force-closing to ensure they get it if we're offline.
+ // We previously had a much more aggressive check here which tried to ensure
+ // our counterparty receives an HTLC which has *our* risk threshold met on it,
+ // but there is no need to do that, and since we're a bit conservative with our
+ // risk threshold it just results in failing to forward payments.
+ if (*outgoing_cltv_value) as u64 <= (cur_height + LATENCY_GRACE_PERIOD_BLOCKS) as u64 {
break Some(("Outgoing CLTV value is too soon", 0x1000 | 14, Some(self.get_channel_update_for_unicast(chan).unwrap())));
}
Some(id) => id.clone(),
};
+ macro_rules! insert_outbound_payment {
+ () => {
+ let payment = payment_entry.or_insert_with(|| PendingOutboundPayment::Retryable {
+ session_privs: HashSet::new(),
+ pending_amt_msat: 0,
+ pending_fee_msat: Some(0),
+ payment_hash: *payment_hash,
+ payment_secret: *payment_secret,
+ starting_block_height: self.best_block.read().unwrap().height(),
+ total_msat: total_value,
+ });
+ assert!(payment.insert(session_priv_bytes, path));
+ }
+ }
+
let channel_state = &mut *channel_lock;
if let hash_map::Entry::Occupied(mut chan) = channel_state.by_id.entry(id) {
match {
if !chan.get().is_live() {
return Err(APIError::ChannelUnavailable{err: "Peer for first hop currently disconnected/pending monitor update!".to_owned()});
}
- let send_res = break_chan_entry!(self, chan.get_mut().send_htlc_and_commit(
+ break_chan_entry!(self, chan.get_mut().send_htlc_and_commit(
htlc_msat, payment_hash.clone(), htlc_cltv, HTLCSource::OutboundRoute {
path: path.clone(),
session_priv: session_priv.clone(),
payment_secret: payment_secret.clone(),
payee: payee.clone(),
}, onion_packet, &self.logger),
- channel_state, chan);
-
- let payment = payment_entry.or_insert_with(|| PendingOutboundPayment::Retryable {
- session_privs: HashSet::new(),
- pending_amt_msat: 0,
- pending_fee_msat: Some(0),
- payment_hash: *payment_hash,
- payment_secret: *payment_secret,
- starting_block_height: self.best_block.read().unwrap().height(),
- total_msat: total_value,
- });
- assert!(payment.insert(session_priv_bytes, path));
-
- send_res
+ channel_state, chan)
} {
Some((update_add, commitment_signed, monitor_update)) => {
if let Err(e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
// is restored. Therefore, we must return an error indicating that
// it is unsafe to retry the payment wholesale, which we do in the
// send_payment check for MonitorUpdateFailed, below.
+ insert_outbound_payment!(); // Only do this after possibly break'ing on Perm failure above.
return Err(APIError::MonitorUpdateFailed);
}
+ insert_outbound_payment!();
log_debug!(self.logger, "Sending payment along path resulted in a commitment_signed for channel {}", log_bytes!(chan.get().channel_id()));
channel_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
},
});
},
- None => {},
+ None => { insert_outbound_payment!(); },
}
} else { unreachable!(); }
return Ok(());
} else { None },
})
} else if has_err {
+ // If we failed to send any paths, we shouldn't have inserted the new PaymentId into
+ // our `pending_outbound_payments` map at all.
+ debug_assert!(self.pending_outbound_payments.lock().unwrap().get(&payment_id).is_none());
Err(PaymentSendFailure::AllFailedRetrySafe(results.drain(..).map(|r| r.unwrap_err()).collect()))
} else {
Ok(payment_id)
htlc_id: prev_htlc_id,
incoming_packet_shared_secret: incoming_shared_secret,
});
- match chan.get_mut().send_htlc(amt_to_forward, payment_hash, outgoing_cltv_value, htlc_source.clone(), onion_packet) {
+ match chan.get_mut().send_htlc(amt_to_forward, payment_hash, outgoing_cltv_value, htlc_source.clone(), onion_packet, &self.logger) {
Err(e) => {
if let ChannelError::Ignore(msg) = e {
log_trace!(self.logger, "Failed to forward HTLC with payment_hash {}: {}", log_bytes!(payment_hash.0), msg);
return Err(MsgHandleErrInternal::send_err_msg_no_close("Unknown genesis block hash".to_owned(), msg.temporary_channel_id.clone()));
}
- let channel = Channel::new_from_req(&self.fee_estimator, &self.keys_manager, counterparty_node_id.clone(), &their_features, msg, 0, &self.default_configuration)
+ if !self.default_configuration.accept_inbound_channels {
+ return Err(MsgHandleErrInternal::send_err_msg_no_close("No inbound channels accepted".to_owned(), msg.temporary_channel_id.clone()));
+ }
+
+ let channel = Channel::new_from_req(&self.fee_estimator, &self.keys_manager, counterparty_node_id.clone(),
+ &their_features, msg, 0, &self.default_configuration, self.best_block.read().unwrap().height())
.map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, msg.temporary_channel_id))?;
let mut channel_state_lock = self.channel_state.lock().unwrap();
let channel_state = &mut *channel_state_lock;
/// Calls a function which handles an on-chain event (blocks dis/connected, transactions
/// un/confirmed, etc) on each channel, handling any resulting errors or messages generated by
/// the function.
- fn do_chain_event<FN: Fn(&mut Channel<Signer>) -> Result<(Option<msgs::FundingLocked>, Vec<(HTLCSource, PaymentHash)>), msgs::ErrorMessage>>
+ fn do_chain_event<FN: Fn(&mut Channel<Signer>) -> Result<(Option<msgs::FundingLocked>, Vec<(HTLCSource, PaymentHash)>), ClosureReason>>
(&self, height_opt: Option<u32>, f: FN) {
// Note that we MUST NOT end up calling methods on self.chain_monitor here - we're called
// during initialization prior to the chain_monitor being fully configured in some cases.
}
short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
}
- } else if let Err(e) = res {
+ } else if let Err(reason) = res {
if let Some(short_id) = channel.get_short_channel_id() {
short_to_id.remove(&short_id);
}
msg: update
});
}
- self.issue_channel_close_events(channel, ClosureReason::CommitmentTxConfirmed);
+ let reason_message = format!("{}", reason);
+ self.issue_channel_close_events(channel, reason);
pending_msg_events.push(events::MessageSendEvent::HandleError {
node_id: channel.get_counterparty_node_id(),
- action: msgs::ErrorAction::SendErrorMessage { msg: e },
+ action: msgs::ErrorAction::SendErrorMessage { msg: msgs::ErrorMessage {
+ channel_id: channel.channel_id(),
+ data: reason_message,
+ } },
});
return false;
}
let mut short_to_id = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
let mut channel_closures = Vec::new();
for _ in 0..channel_count {
- let mut channel: Channel<Signer> = Channel::read(reader, &args.keys_manager)?;
+ let mut channel: Channel<Signer> = Channel::read(reader, (&args.keys_manager, best_block_height))?;
let funding_txo = channel.get_funding_txo().ok_or(DecodeError::InvalidValue)?;
funding_txo_set.insert(funding_txo.clone());
if let Some(ref mut monitor) = args.channel_monitors.get_mut(&funding_txo) {
use ln::msgs::{ChannelMessageHandler, Init};
use routing::network_graph::NetworkGraph;
use routing::router::{Payee, get_route};
- use routing::scorer::Scorer;
+ use routing::scoring::Scorer;
use util::test_utils;
use util::config::UserConfig;
use util::events::{Event, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose};
macro_rules! send_payment {
($node_a: expr, $node_b: expr) => {
let usable_channels = $node_a.list_usable_channels();
- let payee = Payee::new($node_b.get_our_node_id())
+ let payee = Payee::from_node_id($node_b.get_our_node_id())
.with_features(InvoiceFeatures::known());
let scorer = Scorer::with_fixed_penalty(0);
let route = get_route(&$node_a.get_our_node_id(), &payee, &dummy_graph,