match source {
HTLCSource::OutboundRoute { .. } => {
mem::drop(channel_state);
-
- let mut pending_events = self.pending_events.lock().unwrap();
- pending_events.push(events::Event::PaymentFailed {
- payment_hash: payment_hash.clone()
- });
+ if let &HTLCFailReason::ErrorPacket { ref err } = &onion_error {
+ let (channel_update, payment_retryable) = self.process_onion_failure(&source, err.data.clone());
+ let mut pending_events = self.pending_events.lock().unwrap();
+ if let Some(channel_update) = channel_update {
+ pending_events.push(events::Event::PaymentFailureNetworkUpdate {
+ update: channel_update,
+ });
+ }
+ pending_events.push(events::Event::PaymentFailed {
+ payment_hash: payment_hash.clone(),
+ rejected_by_dest: !payment_retryable,
+ });
+ } else {
+ panic!("should have onion error packet here");
+ }
},
HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id, htlc_id, incoming_packet_shared_secret }) => {
let err_packet = match onion_error {
} else { ((None, true)) }
}
- fn internal_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result<Option<msgs::HTLCFailChannelUpdate>, MsgHandleErrInternal> {
+ fn internal_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result<(), MsgHandleErrInternal> {
let mut channel_state = self.channel_state.lock().unwrap();
- let htlc_source = match channel_state.by_id.get_mut(&msg.channel_id) {
+ match channel_state.by_id.get_mut(&msg.channel_id) {
Some(chan) => {
if chan.get_their_node_id() != *their_node_id {
//TODO: here and below MsgHandleErrInternal, #153 case
},
None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
}?;
-
- // we are the origin node and update route information
- // also determine if the payment is retryable
- if let &HTLCSource::OutboundRoute { .. } = htlc_source {
- let (channel_update, _payment_retry) = self.process_onion_failure(htlc_source, msg.reason.data.clone());
- Ok(channel_update)
- // TODO: include pyament_retry info in PaymentFailed event that will be
- // fired when receiving revoke_and_ack
- } else {
- Ok(None)
- }
+ Ok(())
}
fn internal_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailMalformedHTLC) -> Result<(), MsgHandleErrInternal> {
handle_error!(self, self.internal_update_fulfill_htlc(their_node_id, msg), their_node_id)
}
- fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result<Option<msgs::HTLCFailChannelUpdate>, HandleError> {
+ fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result<(), HandleError> {
handle_error!(self, self.internal_update_fail_htlc(their_node_id, msg), their_node_id)
}
let events = origin_node.node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events[0] {
- Event::PaymentFailed { payment_hash } => {
+ Event::PaymentFailed { payment_hash, rejected_by_dest } => {
assert_eq!(payment_hash, our_payment_hash);
+ assert!(rejected_by_dest);
},
_ => panic!("Unexpected event"),
}
_ => panic!("Unexpected event"),
}
match events[1] {
- Event::PaymentFailed { payment_hash } => {
+ Event::PaymentFailed { payment_hash, rejected_by_dest } => {
assert_eq!(payment_hash, payment_hash_5);
+ assert!(rejected_by_dest);
},
_ => panic!("Unexpected event"),
}
/// Handle an incoming update_fulfill_htlc message from the given peer.
fn handle_update_fulfill_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFulfillHTLC) -> Result<(), HandleError>;
/// Handle an incoming update_fail_htlc message from the given peer.
- fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailHTLC) -> Result<Option<HTLCFailChannelUpdate>, HandleError>;
+ fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailHTLC) -> Result<(), HandleError>;
/// Handle an incoming update_fail_malformed_htlc message from the given peer.
fn handle_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailMalformedHTLC) -> Result<(), HandleError>;
/// Handle an incoming commitment_signed message from the given peer.
PaymentFailed {
/// The hash which was given to ChannelManager::send_payment.
payment_hash: [u8; 32],
+ /// Indicates the payment was rejected for some reason by the recipient. This implies that
+ /// the payment has failed, not just the route in question. If this is not set, you may
+ /// retry the payment via a different route.
+ rejected_by_dest: bool,
},
/// Used to indicate that ChannelManager::process_pending_htlc_forwards should be called at a
/// time in the future.
node_id: PublicKey,
/// The action which should be taken.
action: Option<msgs::ErrorAction>
+ },
+ /// When a payment fails we may receive updates back from the hop where it failed. In such
+ /// cases this event is generated so that we can inform the router of this information.
+ ///
+ /// This event is handled by PeerManager::process_events if you are using a PeerManager.
+ PaymentFailureNetworkUpdate {
+ /// The channel/node update which should be sent to router
+ update: msgs::HTLCFailChannelUpdate,
}
}