AwaitingRemovedRemoteRevoke,
/// Removed by us and a new commitment_signed was sent (if we were AwaitingRemoteRevoke when we
/// created it we would have put it in the holding cell instead). When they next revoke_and_ack
- /// we'll promote to LocalRemovedAwaitingCommitment if we fulfilled, otherwise we'll drop at
- /// that point.
+ /// we'll drop it.
/// Note that we have to keep an eye on the HTLC until we've received a broadcastable
/// commitment transaction without it as otherwise we'll have to force-close the channel to
/// claim it before the timeout (obviously doesn't apply to revoked HTLCs that we can't claim
- /// anyway).
+ /// anyway). That said, ChannelMonitor does this for us (see
+ /// ChannelMonitor::would_broadcast_at_height) so we actually remove the HTLC from our own
+ /// local state before then, once we're sure that the next commitment_signed and
+ /// ChannelMonitor::provide_latest_local_commitment_tx_info will not include this HTLC.
/// Implies HTLCOutput::outbound: false
LocalRemoved,
- /// Removed by us, sent a new commitment_signed and got a revoke_and_ack. Just waiting on an
- /// updated local commitment transaction. Implies local_removed_fulfilled.
- /// Implies HTLCOutput::outbound: false
- LocalRemovedAwaitingCommitment,
}
struct HTLCOutput { //TODO: Refactor into Outbound/InboundHTLCOutput (will save memory and fewer panics)
HTLCState::AwaitingRemoteRevokeToRemove => generated_by_local,
HTLCState::AwaitingRemovedRemoteRevoke => false,
HTLCState::LocalRemoved => !generated_by_local,
- HTLCState::LocalRemovedAwaitingCommitment => false,
};
if include {
value_to_self_msat_offset += htlc.amount_msat as i64;
}
},
- HTLCState::LocalRemovedAwaitingCommitment => {
- assert!(htlc.local_removed_fulfilled);
- value_to_self_msat_offset += htlc.amount_msat as i64;
- },
_ => {},
}
}
let mut pending_idx = std::usize::MAX;
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 {
+ htlc.state != HTLCState::LocalRemoved {
if let Some(PendingHTLCStatus::Fail(_)) = htlc.pending_forward_state {
} else {
if pending_idx != std::usize::MAX {
// we'll fail this one as soon as remote commits to it.
continue;
}
- } else if htlc.state == HTLCState::LocalRemoved || htlc.state == HTLCState::LocalRemovedAwaitingCommitment {
+ } else if htlc.state == HTLCState::LocalRemoved {
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");
pub fn funding_created(&mut self, msg: &msgs::FundingCreated) -> Result<(msgs::FundingSigned, ChannelMonitor), HandleError> {
if self.channel_outbound {
- return Err(HandleError{err: "Received funding_created for an outbound channel?", action: None});
+ return Err(HandleError{err: "Received funding_created for an outbound channel?", action: Some(msgs::ErrorAction::SendErrorMessage {msg: msgs::ErrorMessage {channel_id: self.channel_id, data: "Received funding_created for an outbound channel?".to_string()}})});
}
if self.channel_state != (ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32) {
- return Err(HandleError{err: "Received funding_created after we got the channel!", action: None});
+ // BOLT 2 says that if we disconnect before we send funding_signed we SHOULD NOT
+ // remember the channel, so its safe to just send an error_message here and drop the
+ // channel.
+ return Err(HandleError{err: "Received funding_created after we got the channel!", action: Some(msgs::ErrorAction::SendErrorMessage {msg: msgs::ErrorMessage {channel_id: self.channel_id, data: "Received funding_created after we got the channel!".to_string()}})});
}
if self.channel_monitor.get_min_seen_secret() != (1 << 48) || self.cur_remote_commitment_transaction_number != (1 << 48) - 1 || self.cur_local_commitment_transaction_number != (1 << 48) - 1 {
panic!("Should not have advanced channel commitment tx numbers prior to funding_created");
HTLCState::AwaitingRemoteRevokeToRemove => { if for_remote_update_check { continue; } },
HTLCState::AwaitingRemovedRemoteRevoke => { if for_remote_update_check { continue; } },
HTLCState::LocalRemoved => {},
- HTLCState::LocalRemovedAwaitingCommitment => { if for_remote_update_check { continue; } },
}
if !htlc.outbound {
inbound_htlc_count += 1;
need_our_commitment = true;
}
}
- // Finally delete all the LocalRemovedAwaitingCommitment HTLCs
- // We really shouldnt have two passes here, but retain gives a non-mutable ref (Rust bug)
- let mut claimed_value_msat = 0;
- self.pending_htlcs.retain(|htlc| {
- if htlc.state == HTLCState::LocalRemovedAwaitingCommitment {
- claimed_value_msat += htlc.amount_msat;
- false
- } else { true }
- });
- self.value_to_self_msat += claimed_value_msat;
self.cur_local_commitment_transaction_number -= 1;
self.last_local_commitment_txn = new_local_commitment_txn;
// We really shouldnt have two passes here, but retain gives a non-mutable ref (Rust bug)
self.pending_htlcs.retain(|htlc| {
if htlc.state == HTLCState::LocalRemoved {
- if htlc.local_removed_fulfilled { true } else { false }
+ if htlc.local_removed_fulfilled {
+ value_to_self_msat_diff += htlc.amount_msat as i64;
+ }
+ false
} else if htlc.state == HTLCState::AwaitingRemovedRemoteRevoke {
if let Some(reason) = htlc.fail_reason.clone() { // We really want take() here, but, again, non-mut ref :(
revoked_htlcs.push((htlc.payment_hash, reason));
} else if htlc.state == HTLCState::AwaitingRemoteRevokeToRemove {
htlc.state = HTLCState::AwaitingRemovedRemoteRevoke;
require_commitment = true;
- } else if htlc.state == HTLCState::LocalRemoved {
- assert!(htlc.local_removed_fulfilled);
- htlc.state = HTLCState::LocalRemovedAwaitingCommitment;
}
}
self.value_to_self_msat = (self.value_to_self_msat as i64 + value_to_self_msat_diff) as u64;
/// This returns an option instead of a pure UpdateAddHTLC as we may be in a state where we are
/// waiting on the remote peer to send us a revoke_and_ack during which time we cannot add new
/// HTLCs on the wire or we wouldn't be able to determine what they actually ACK'ed.
+ /// You MUST call send_commitment prior to any other calls on this Channel
pub fn send_htlc(&mut self, amount_msat: u64, payment_hash: [u8; 32], cltv_expiry: u32, onion_routing_packet: msgs::OnionPacket) -> Result<Option<msgs::UpdateAddHTLC>, HandleError> {
if (self.channel_state & (ChannelState::ChannelFunded as u32 | BOTH_SIDES_SHUTDOWN_MASK)) != (ChannelState::ChannelFunded as u32) {
return Err(HandleError{err: "Cannot send HTLC until channel is fully established and we haven't started shutting down", action: None});
}
/// Creates a signed commitment transaction to send to the remote peer.
+ /// Always returns a Channel-failing HandleError::action if an immediately-preceding (read: the
+ /// last call to this Channel) send_htlc returned Ok(Some(_)) and there is an Err.
pub fn send_commitment(&mut self) -> Result<(msgs::CommitmentSigned, ChannelMonitor), HandleError> {
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
return Err(HandleError{err: "Cannot create commitment tx until channel is fully established", action: None});