Skip to content

Handle invalid funding tx in channelmanager #98

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crypto::digest::Digest;
use crypto::hkdf::{hkdf_extract,hkdf_expand};

use ln::msgs;
use ln::msgs::{HandleError, MsgEncodable};
use ln::msgs::{ErrorAction, HandleError, MsgEncodable};
use ln::channelmonitor::ChannelMonitor;
use ln::channelmanager::{PendingForwardHTLCInfo, HTLCFailReason};
use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT};
Expand Down Expand Up @@ -1916,7 +1916,10 @@ impl Channel {
/// Called by channelmanager based on chain blocks being connected.
/// Note that we only need to use this to detect funding_signed, anything else is handled by
/// the channel_monitor.
pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Option<msgs::FundingLocked> {
/// In case of Err, the channel may have been closed, at which point the standard requirements
/// apply - no calls may be made except those explicitly stated to be allowed post-shutdown.
/// Only returns an ErrorAction of DisconnectPeer, if Err.
pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<Option<msgs::FundingLocked>, HandleError> {
let non_shutdown_state = self.channel_state & (!BOTH_SIDES_SHUTDOWN_MASK);
if self.funding_tx_confirmations > 0 {
if header.bitcoin_hash() != self.last_block_connected {
Expand All @@ -1940,10 +1943,10 @@ impl Channel {
//a protocol oversight, but I assume I'm just missing something.
let next_per_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number);
let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret).unwrap();
return Some(msgs::FundingLocked {
return Ok(Some(msgs::FundingLocked {
channel_id: self.channel_id,
next_per_commitment_point: next_per_commitment_point,
});
}));
}
}
}
Expand All @@ -1955,6 +1958,7 @@ impl Channel {
tx.output[txo_idx].value != self.channel_value_satoshis {
self.channel_state = ChannelState::ShutdownComplete as u32;
self.channel_update_count += 1;
return Err(HandleError{err: "funding tx had wrong script/value", action: Some(ErrorAction::DisconnectPeer{msg: None})});
} else {
self.funding_tx_confirmations = 1;
self.short_channel_id = Some(((height as u64) << (5*8)) |
Expand All @@ -1964,7 +1968,7 @@ impl Channel {
}
}
}
None
Ok(None)
}

/// Called by channelmanager based on chain blocks being disconnected.
Expand Down
13 changes: 12 additions & 1 deletion src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1141,7 +1141,8 @@ impl ChainListener for ChannelManager {
let channel_state = channel_lock.borrow_parts();
let short_to_id = channel_state.short_to_id;
channel_state.by_id.retain(|_, channel| {
if let Some(funding_locked) = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched) {
let chan_res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched);
if let Ok(Some(funding_locked)) = chan_res {
let announcement_sigs = match self.get_announcement_sigs(channel) {
Ok(res) => res,
Err(_e) => {
Expand All @@ -1155,6 +1156,16 @@ impl ChainListener for ChannelManager {
announcement_sigs: announcement_sigs
});
short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
} else if let Err(e) = chan_res {
if let Some(msgs::ErrorAction::DisconnectPeer { msg }) = e.action {
new_events.push(events::Event::DisconnectPeer {
node_id: channel.get_their_node_id(),
msg: msg
});
} else { unreachable!(); }
if channel.is_shutdown() {
return false;
}
}
if let Some(funding_txo) = channel.get_funding_txo() {
for tx in txn_matched {
Expand Down