+ /// Indicates that the preimage for payment_hash is unknown after a PaymentReceived event.
+ pub fn fail_htlc_backwards(&self, payment_hash: &[u8; 32]) -> bool {
+ self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), payment_hash, HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: &[0;0] })
+ }
+
+ fn fail_htlc_backwards_internal(&self, mut channel_state: MutexGuard<ChannelHolder>, payment_hash: &[u8; 32], onion_error: HTLCFailReason) -> bool {
+ let mut pending_htlc = {
+ match channel_state.claimable_htlcs.remove(payment_hash) {
+ Some(pending_htlc) => pending_htlc,
+ None => return false,
+ }
+ };
+
+ match pending_htlc {
+ PendingOutboundHTLC::CycledRoute { source_short_channel_id, incoming_packet_shared_secret, .. } => {
+ pending_htlc = PendingOutboundHTLC::IntermediaryHopData { source_short_channel_id, incoming_packet_shared_secret };
+ },
+ _ => {}
+ }
+
+ match pending_htlc {
+ PendingOutboundHTLC::CycledRoute { .. } => { panic!("WAT"); },
+ PendingOutboundHTLC::OutboundRoute { .. } => {
+ //TODO: DECRYPT route from 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()
+ });
+ false
+ },
+ PendingOutboundHTLC::IntermediaryHopData { source_short_channel_id, incoming_packet_shared_secret } => {
+ let err_packet = match onion_error {
+ HTLCFailReason::Reason { failure_code, data } => {
+ let packet = ChannelManager::build_failure_packet(&incoming_packet_shared_secret, failure_code, data).encode();
+ ChannelManager::encrypt_failure_packet(&incoming_packet_shared_secret, &packet)
+ },
+ HTLCFailReason::ErrorPacket { err } => {
+ ChannelManager::encrypt_failure_packet(&incoming_packet_shared_secret, &err.data)
+ }
+ };
+
+ let (node_id, fail_msg) = {
+ let chan_id = match channel_state.short_to_id.get(&source_short_channel_id) {
+ Some(chan_id) => chan_id.clone(),
+ None => return false
+ };
+
+ let chan = channel_state.by_id.get_mut(&chan_id).unwrap();
+ match chan.get_update_fail_htlc(payment_hash, err_packet) {
+ Ok(msg) => (chan.get_their_node_id(), msg),
+ Err(_e) => {
+ //TODO: Do something with e?
+ return false;
+ },
+ }
+ };
+
+ mem::drop(channel_state);
+ let mut pending_events = self.pending_events.lock().unwrap();
+ pending_events.push(events::Event::SendFailHTLC {
+ node_id,
+ msg: fail_msg
+ });
+
+ true
+ },
+ }
+ }
+