Skip to content

Commit 5e9e199

Browse files
authored
Merge pull request #258 from TheBlueMatt/2018-11-close-locked
Simplify + document the ChannelManager Err flow, fix close-outside-lock race, finish ChannelError conversion
2 parents 6969fc9 + 466d0f6 commit 5e9e199

File tree

2 files changed

+340
-294
lines changed

2 files changed

+340
-294
lines changed

src/ln/channel.rs

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use secp256k1;
1313
use crypto::digest::Digest;
1414

1515
use ln::msgs;
16-
use ln::msgs::{DecodeError, ErrorAction, HandleError};
16+
use ln::msgs::DecodeError;
1717
use ln::channelmonitor::ChannelMonitor;
1818
use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingForwardHTLCInfo, RAACommitmentOrder};
1919
use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT};
@@ -373,15 +373,6 @@ pub(super) enum ChannelError {
373373
Close(&'static str),
374374
}
375375

376-
macro_rules! secp_call {
377-
( $res: expr, $err: expr, $chan_id: expr ) => {
378-
match $res {
379-
Ok(key) => key,
380-
Err(_) => return Err(HandleError {err: $err, action: Some(msgs::ErrorAction::SendErrorMessage {msg: msgs::ErrorMessage {channel_id: $chan_id, data: $err.to_string()}})})
381-
}
382-
};
383-
}
384-
385376
macro_rules! secp_check {
386377
($res: expr, $err: expr) => {
387378
match $res {
@@ -1013,6 +1004,7 @@ impl Channel {
10131004
#[inline]
10141005
/// Creates a set of keys for build_commitment_transaction to generate a transaction which we
10151006
/// will sign and send to our counterparty.
1007+
/// If an Err is returned, it is a ChannelError::Close (for get_outbound_funding_created)
10161008
fn build_remote_transaction_keys(&self) -> Result<TxCreationKeys, ChannelError> {
10171009
//TODO: Ensure that the payment_key derived here ends up in the library users' wallet as we
10181010
//may see payments to it!
@@ -1528,40 +1520,40 @@ impl Channel {
15281520
(self.pending_outbound_htlcs.len() as u32, htlc_outbound_value_msat)
15291521
}
15301522

1531-
pub fn update_add_htlc(&mut self, msg: &msgs::UpdateAddHTLC, pending_forward_state: PendingHTLCStatus) -> Result<(), HandleError> {
1523+
pub fn update_add_htlc(&mut self, msg: &msgs::UpdateAddHTLC, pending_forward_state: PendingHTLCStatus) -> Result<(), ChannelError> {
15321524
if (self.channel_state & (ChannelState::ChannelFunded as u32 | ChannelState::RemoteShutdownSent as u32)) != (ChannelState::ChannelFunded as u32) {
1533-
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None});
1525+
return Err(ChannelError::Close("Got add HTLC message when channel was not in an operational state"));
15341526
}
15351527
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1536-
return Err(HandleError{err: "Peer sent update_add_htlc when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent update_add_htlc when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
1528+
return Err(ChannelError::Close("Peer sent update_add_htlc when we needed a channel_reestablish"));
15371529
}
15381530
if msg.amount_msat > self.channel_value_satoshis * 1000 {
1539-
return Err(HandleError{err: "Remote side tried to send more than the total value of the channel", action: None});
1531+
return Err(ChannelError::Close("Remote side tried to send more than the total value of the channel"));
15401532
}
15411533
if msg.amount_msat < self.our_htlc_minimum_msat {
1542-
return Err(HandleError{err: "Remote side tried to send less than our minimum HTLC value", action: None});
1534+
return Err(ChannelError::Close("Remote side tried to send less than our minimum HTLC value"));
15431535
}
15441536

15451537
let (inbound_htlc_count, htlc_inbound_value_msat) = self.get_inbound_pending_htlc_stats();
15461538
if inbound_htlc_count + 1 > OUR_MAX_HTLCS as u32 {
1547-
return Err(HandleError{err: "Remote tried to push more than our max accepted HTLCs", action: None});
1539+
return Err(ChannelError::Close("Remote tried to push more than our max accepted HTLCs"));
15481540
}
15491541
//TODO: Spec is unclear if this is per-direction or in total (I assume per direction):
15501542
// Check our_max_htlc_value_in_flight_msat
15511543
if htlc_inbound_value_msat + msg.amount_msat > Channel::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis) {
1552-
return Err(HandleError{err: "Remote HTLC add would put them over their max HTLC value in flight", action: None});
1544+
return Err(ChannelError::Close("Remote HTLC add would put them over their max HTLC value in flight"));
15531545
}
15541546
// Check our_channel_reserve_satoshis (we're getting paid, so they have to at least meet
15551547
// the reserve_satoshis we told them to always have as direct payment so that they lose
15561548
// something if we punish them for broadcasting an old state).
15571549
if htlc_inbound_value_msat + msg.amount_msat + self.value_to_self_msat > (self.channel_value_satoshis - Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis)) * 1000 {
1558-
return Err(HandleError{err: "Remote HTLC add would put them over their reserve value", action: None});
1550+
return Err(ChannelError::Close("Remote HTLC add would put them over their reserve value"));
15591551
}
15601552
if self.next_remote_htlc_id != msg.htlc_id {
1561-
return Err(HandleError{err: "Remote skipped HTLC ID", action: None});
1553+
return Err(ChannelError::Close("Remote skipped HTLC ID"));
15621554
}
15631555
if msg.cltv_expiry >= 500000000 {
1564-
return Err(HandleError{err: "Remote provided CLTV expiry in seconds instead of block height", action: None});
1556+
return Err(ChannelError::Close("Remote provided CLTV expiry in seconds instead of block height"));
15651557
}
15661558

15671559
//TODO: Check msg.cltv_expiry further? Do this in channel manager?
@@ -1613,7 +1605,7 @@ impl Channel {
16131605
Err(ChannelError::Close("Remote tried to fulfill/fail an HTLC we couldn't find"))
16141606
}
16151607

1616-
pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<&HTLCSource, ChannelError> {
1608+
pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<HTLCSource, ChannelError> {
16171609
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
16181610
return Err(ChannelError::Close("Got fulfill HTLC message when channel was not in an operational state"));
16191611
}
@@ -1626,29 +1618,31 @@ impl Channel {
16261618
let mut payment_hash = [0; 32];
16271619
sha.result(&mut payment_hash);
16281620

1629-
self.mark_outbound_htlc_removed(msg.htlc_id, Some(payment_hash), None)
1621+
self.mark_outbound_htlc_removed(msg.htlc_id, Some(payment_hash), None).map(|source| source.clone())
16301622
}
16311623

1632-
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<&HTLCSource, ChannelError> {
1624+
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<(), ChannelError> {
16331625
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
16341626
return Err(ChannelError::Close("Got fail HTLC message when channel was not in an operational state"));
16351627
}
16361628
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
16371629
return Err(ChannelError::Close("Peer sent update_fail_htlc when we needed a channel_reestablish"));
16381630
}
16391631

1640-
self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason))
1632+
self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason))?;
1633+
Ok(())
16411634
}
16421635

1643-
pub fn update_fail_malformed_htlc<'a>(&mut self, msg: &msgs::UpdateFailMalformedHTLC, fail_reason: HTLCFailReason) -> Result<&HTLCSource, ChannelError> {
1636+
pub fn update_fail_malformed_htlc<'a>(&mut self, msg: &msgs::UpdateFailMalformedHTLC, fail_reason: HTLCFailReason) -> Result<(), ChannelError> {
16441637
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
16451638
return Err(ChannelError::Close("Got fail malformed HTLC message when channel was not in an operational state"));
16461639
}
16471640
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
16481641
return Err(ChannelError::Close("Peer sent update_fail_malformed_htlc when we needed a channel_reestablish"));
16491642
}
16501643

1651-
self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason))
1644+
self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason))?;
1645+
Ok(())
16521646
}
16531647

16541648
pub fn commitment_signed(&mut self, msg: &msgs::CommitmentSigned, fee_estimator: &FeeEstimator) -> Result<(msgs::RevokeAndACK, Option<msgs::CommitmentSigned>, Option<msgs::ClosingSigned>, ChannelMonitor), ChannelError> {
@@ -2508,24 +2502,24 @@ impl Channel {
25082502
Ok((our_shutdown, self.maybe_propose_first_closing_signed(fee_estimator), dropped_outbound_htlcs))
25092503
}
25102504

2511-
pub fn closing_signed(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::ClosingSigned) -> Result<(Option<msgs::ClosingSigned>, Option<Transaction>), HandleError> {
2505+
pub fn closing_signed(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::ClosingSigned) -> Result<(Option<msgs::ClosingSigned>, Option<Transaction>), ChannelError> {
25122506
if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK != BOTH_SIDES_SHUTDOWN_MASK {
2513-
return Err(HandleError{err: "Remote end sent us a closing_signed before both sides provided a shutdown", action: None});
2507+
return Err(ChannelError::Close("Remote end sent us a closing_signed before both sides provided a shutdown"));
25142508
}
25152509
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
2516-
return Err(HandleError{err: "Peer sent closing_signed when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent closing_signed when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
2510+
return Err(ChannelError::Close("Peer sent closing_signed when we needed a channel_reestablish"));
25172511
}
25182512
if !self.pending_inbound_htlcs.is_empty() || !self.pending_outbound_htlcs.is_empty() {
2519-
return Err(HandleError{err: "Remote end sent us a closing_signed while there were still pending HTLCs", action: None});
2513+
return Err(ChannelError::Close("Remote end sent us a closing_signed while there were still pending HTLCs"));
25202514
}
25212515
if msg.fee_satoshis > 21000000 * 10000000 { //this is required to stop potential overflow in build_closing_transaction
2522-
return Err(HandleError{err: "Remote tried to send us a closing tx with > 21 million BTC fee", action: None});
2516+
return Err(ChannelError::Close("Remote tried to send us a closing tx with > 21 million BTC fee"));
25232517
}
25242518

25252519
let funding_redeemscript = self.get_funding_redeemscript();
25262520
let (mut closing_tx, used_total_fee) = self.build_closing_transaction(msg.fee_satoshis, false);
25272521
if used_total_fee != msg.fee_satoshis {
2528-
return Err(HandleError{err: "Remote sent us a closing_signed with a fee greater than the value they can claim", action: None});
2522+
return Err(ChannelError::Close("Remote sent us a closing_signed with a fee greater than the value they can claim"));
25292523
}
25302524
let mut sighash = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap();
25312525

@@ -2536,7 +2530,7 @@ impl Channel {
25362530
// limits, so check for that case by re-checking the signature here.
25372531
closing_tx = self.build_closing_transaction(msg.fee_satoshis, true).0;
25382532
sighash = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap();
2539-
secp_call!(self.secp_ctx.verify(&sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid closing tx signature from peer", self.channel_id());
2533+
secp_check!(self.secp_ctx.verify(&sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid closing tx signature from peer");
25402534
},
25412535
};
25422536

@@ -2570,7 +2564,7 @@ impl Channel {
25702564
if proposed_sat_per_kw > our_max_feerate {
25712565
if let Some((last_feerate, _)) = self.last_sent_closing_fee {
25722566
if our_max_feerate <= last_feerate {
2573-
return Err(HandleError{err: "Unable to come to consensus about closing feerate, remote wanted something higher than our Normal feerate", action: None});
2567+
return Err(ChannelError::Close("Unable to come to consensus about closing feerate, remote wanted something higher than our Normal feerate"));
25742568
}
25752569
}
25762570
propose_new_feerate!(our_max_feerate);
@@ -2580,7 +2574,7 @@ impl Channel {
25802574
if proposed_sat_per_kw < our_min_feerate {
25812575
if let Some((last_feerate, _)) = self.last_sent_closing_fee {
25822576
if our_min_feerate >= last_feerate {
2583-
return Err(HandleError{err: "Unable to come to consensus about closing feerate, remote wanted something lower than our Background feerate", action: None});
2577+
return Err(ChannelError::Close("Unable to come to consensus about closing feerate, remote wanted something lower than our Background feerate"));
25842578
}
25852579
}
25862580
propose_new_feerate!(our_min_feerate);
@@ -2780,7 +2774,7 @@ impl Channel {
27802774
/// In case of Err, the channel may have been closed, at which point the standard requirements
27812775
/// apply - no calls may be made except those explicitly stated to be allowed post-shutdown.
27822776
/// Only returns an ErrorAction of DisconnectPeer, if Err.
2783-
pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<Option<msgs::FundingLocked>, HandleError> {
2777+
pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<Option<msgs::FundingLocked>, msgs::ErrorMessage> {
27842778
let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS);
27852779
if header.bitcoin_hash() != self.last_block_connected {
27862780
self.last_block_connected = header.bitcoin_hash();
@@ -2840,7 +2834,10 @@ impl Channel {
28402834
}
28412835
self.channel_state = ChannelState::ShutdownComplete as u32;
28422836
self.channel_update_count += 1;
2843-
return Err(HandleError{err: "funding tx had wrong script/value", action: Some(ErrorAction::DisconnectPeer{msg: None})});
2837+
return Err(msgs::ErrorMessage {
2838+
channel_id: self.channel_id(),
2839+
data: "funding tx had wrong script/value".to_owned()
2840+
});
28442841
} else {
28452842
if self.channel_outbound {
28462843
for input in tx.input.iter() {
@@ -2953,6 +2950,7 @@ impl Channel {
29532950
}
29542951
}
29552952

2953+
/// If an Err is returned, it is a ChannelError::Close (for get_outbound_funding_created)
29562954
fn get_outbound_funding_created_signature(&mut self) -> Result<(Signature, Transaction), ChannelError> {
29572955
let funding_script = self.get_funding_redeemscript();
29582956

@@ -2970,6 +2968,7 @@ impl Channel {
29702968
/// or if called on an inbound channel.
29712969
/// Note that channel_id changes during this call!
29722970
/// Do NOT broadcast the funding transaction until after a successful funding_signed call!
2971+
/// If an Err is returned, it is a ChannelError::Close.
29732972
pub fn get_outbound_funding_created(&mut self, funding_txo: OutPoint) -> Result<(msgs::FundingCreated, ChannelMonitor), ChannelError> {
29742973
if !self.channel_outbound {
29752974
panic!("Tried to create outbound funding_created message on an inbound channel!");
@@ -3160,7 +3159,7 @@ impl Channel {
31603159
}
31613160

31623161
/// Creates a signed commitment transaction to send to the remote peer.
3163-
/// Always returns a Channel-failing HandleError::action if an immediately-preceding (read: the
3162+
/// Always returns a ChannelError::Close if an immediately-preceding (read: the
31643163
/// last call to this Channel) send_htlc returned Ok(Some(_)) and there is an Err.
31653164
/// May panic if called except immediately after a successful, Ok(Some(_))-returning send_htlc.
31663165
pub fn send_commitment(&mut self) -> Result<(msgs::CommitmentSigned, ChannelMonitor), ChannelError> {

0 commit comments

Comments
 (0)