use ln::msgs;
use ln::msgs::{ErrorAction, HandleError, MsgEncodable};
use ln::channelmonitor::ChannelMonitor;
-use ln::channelmanager::{PendingHTLCStatus, PendingForwardHTLCInfo, HTLCFailReason};
+use ln::channelmanager::{PendingHTLCStatus, PendingForwardHTLCInfo, HTLCFailReason, HTLCFailureMsg};
use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT};
use ln::chan_utils;
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
for (idx, htlc) in self.pending_htlcs.iter().enumerate() {
if !htlc.outbound && htlc.payment_hash == payment_hash_calc &&
htlc.state != HTLCState::LocalRemoved && htlc.state != HTLCState::LocalRemovedAwaitingCommitment {
- if pending_idx != std::usize::MAX {
- panic!("Duplicate HTLC payment_hash, ChannelManager should have prevented this!");
+ if let Some(PendingHTLCStatus::Fail(_)) = htlc.pending_forward_state {
+ } else {
+ if pending_idx != std::usize::MAX {
+ panic!("Duplicate HTLC payment_hash, ChannelManager should have prevented this!");
+ }
+ pending_idx = idx;
}
- pending_idx = idx;
}
}
if pending_idx == std::usize::MAX {
if htlc_id != 0 {
panic!("Duplicate HTLC payment_hash, you probably re-used payment preimages, NEVER DO THIS!");
}
- htlc_id = htlc.htlc_id;
- htlc_amount_msat += htlc.amount_msat;
if htlc.state == HTLCState::Committed {
htlc.state = HTLCState::LocalRemoved;
} else if htlc.state == HTLCState::RemoteAnnounced {
- panic!("Somehow forwarded HTLC prior to remote revocation!");
+ if let Some(PendingHTLCStatus::Forward(_)) = htlc.pending_forward_state {
+ panic!("Somehow forwarded HTLC prior to remote revocation!");
+ } else {
+ // We have to pretend this isn't here - we're probably a duplicate with the
+ // same payment_hash as some other HTLC, and the other is getting failed,
+ // we'll fail this one as soon as remote commits to it.
+ continue;
+ }
} else if htlc.state == HTLCState::LocalRemoved || htlc.state == HTLCState::LocalRemovedAwaitingCommitment {
return Err(HandleError{err: "Unable to find a pending HTLC which matched the given payment preimage", action: None});
} else {
panic!("Have an inbound HTLC when not awaiting remote revoke that had a garbage state");
}
+ htlc_id = htlc.htlc_id;
+ htlc_amount_msat += htlc.amount_msat;
}
}
if htlc_amount_msat == 0 {
update_add_htlcs,
update_fulfill_htlcs,
update_fail_htlcs,
+ update_fail_malformed_htlcs: Vec::new(),
commitment_signed,
}, monitor_update)))
},
let mut to_forward_infos = Vec::new();
let mut revoked_htlcs = Vec::new();
- let mut failed_htlcs = Vec::new();
+ let mut update_fail_htlcs = Vec::new();
+ let mut update_fail_malformed_htlcs = Vec::new();
let mut require_commitment = false;
let mut value_to_self_msat_diff: i64 = 0;
// We really shouldnt have two passes here, but retain gives a non-mutable ref (Rust bug)
PendingHTLCStatus::Fail(fail_msg) => {
htlc.state = HTLCState::LocalRemoved;
require_commitment = true;
- failed_htlcs.push(fail_msg);
+ match fail_msg {
+ HTLCFailureMsg::Relay(msg) => update_fail_htlcs.push(msg),
+ HTLCFailureMsg::Malformed(msg) => update_fail_malformed_htlcs.push(msg),
+ }
},
PendingHTLCStatus::Forward(forward_info) => {
to_forward_infos.push(forward_info);
match self.free_holding_cell_htlcs()? {
Some(mut commitment_update) => {
- commitment_update.0.update_fail_htlcs.reserve(failed_htlcs.len());
- for fail_msg in failed_htlcs.drain(..) {
+ commitment_update.0.update_fail_htlcs.reserve(update_fail_htlcs.len());
+ for fail_msg in update_fail_htlcs.drain(..) {
commitment_update.0.update_fail_htlcs.push(fail_msg);
}
+ commitment_update.0.update_fail_malformed_htlcs.reserve(update_fail_malformed_htlcs.len());
+ for fail_msg in update_fail_malformed_htlcs.drain(..) {
+ commitment_update.0.update_fail_malformed_htlcs.push(fail_msg);
+ }
Ok((Some(commitment_update.0), to_forward_infos, revoked_htlcs, commitment_update.1))
},
None => {
Ok((Some(msgs::CommitmentUpdate {
update_add_htlcs: Vec::new(),
update_fulfill_htlcs: Vec::new(),
- update_fail_htlcs: failed_htlcs,
+ update_fail_htlcs,
+ update_fail_malformed_htlcs,
commitment_signed
}), to_forward_infos, revoked_htlcs, monitor_update))
} else {