Skip to content

Commit e56e900

Browse files
Aditya SharmaAditya Sharma
authored andcommitted
Handle YourPeerStorage in ChannelManager
Ensure ChannelManager properly handles cases where a stale or missing ChannelMonitor is detected. - Write internal_your_peer_storage to verify if a ChannelMonitor is stale or missing. - Update ChannelManager::read to panic if a stale ChannelMonitor is encountered during loading. - Add STUB_CHANNEL_UPDATE_IDENTIFIER to identify stub channel monitors constructed from peer storage. - Make some exceptions for StubChannelMonitors.
1 parent b4d0c88 commit e56e900

File tree

3 files changed

+112
-2
lines changed

3 files changed

+112
-2
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ pub struct ChannelMonitorUpdate {
114114
/// No other [`ChannelMonitorUpdate`]s are allowed after force-close.
115115
pub const CLOSED_CHANNEL_UPDATE_ID: u64 = core::u64::MAX;
116116

117+
/// This update ID is used inside [`ChannelMonitorImpl`] to recognise
118+
/// that we're dealing with a [`StubChannelMonitor`]. Since we require some
119+
/// exceptions while dealing with it.
120+
pub const STUB_CHANNEL_UPDATE_IDENTIFIER: u64 = core::u64::MAX - 1;
121+
117122
impl Writeable for ChannelMonitorUpdate {
118123
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
119124
write_ver_prefix!(w, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
@@ -851,6 +856,40 @@ pub struct ChannelMonitor<Signer: EcdsaChannelSigner> {
851856
pub(super) inner: Mutex<ChannelMonitorImpl<Signer>>,
852857
}
853858

859+
/// Data prepended to the serialised [`ChannelMonitor`] inside
860+
/// PeerStorage so that we can identify stale or missing channel
861+
/// monitor inside in [`FundRecoverer::handle_your_peer_storage`] &
862+
/// [`ChannelManager::handle_your_peer_storage`].
863+
pub struct StubChannelInfo {
864+
/// Minimum seen secret of the [`ChannelMonitor`] to identify stale channels.
865+
pub min_seen_secret: u64,
866+
/// Channel Id of the channel retrieved from Peer Storage.
867+
pub cid: ChannelId,
868+
/// Node Id of the counterparty.
869+
pub counterparty_node_id: PublicKey,
870+
/// Funding outpoint of the [`ChannelMonitor`].
871+
pub funding_outpoint: OutPoint,
872+
/// Channel Keys Id of the channel retrieved from the Peer Storage.
873+
pub channel_keys_id: [u8; 32],
874+
/// Channel value sats of the channel.
875+
pub channel_value_satoshi: u64
876+
}
877+
878+
impl_writeable_tlv_based!(StubChannelInfo, {
879+
(0, min_seen_secret, required),
880+
(2, cid, required),
881+
(4, counterparty_node_id, required),
882+
(6, funding_outpoint, required),
883+
(8, channel_keys_id, required),
884+
(10, channel_value_satoshi, required),
885+
});
886+
887+
/// Read [`StubChannelInfo`] from `chan_reader` of the [`ChannelMonitor`].
888+
pub fn get_stub_channel_info_from_ser_channel<R: io::Read>(chan_reader: &mut R) -> Result<StubChannelInfo, DecodeError> {
889+
let stub_info: StubChannelInfo = Readable::read(chan_reader)?;
890+
Ok(stub_info)
891+
}
892+
854893
impl<Signer: EcdsaChannelSigner> Clone for ChannelMonitor<Signer> where Signer: Clone {
855894
fn clone(&self) -> Self {
856895
let inner = self.inner.lock().unwrap().clone();
@@ -3514,6 +3553,10 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35143553
block_hash, per_commitment_claimable_data.iter().map(|(htlc, htlc_source)|
35153554
(htlc, htlc_source.as_ref().map(|htlc_source| htlc_source.as_ref()))
35163555
), logger);
3556+
} else if self.latest_update_id == STUB_CHANNEL_UPDATE_IDENTIFIER {
3557+
// Since we aren't storing per commitment option inside stub channels.
3558+
fail_unbroadcast_htlcs!(self, "revoked counterparty", commitment_txid, tx, height,
3559+
block_hash, [].iter().map(|reference| *reference), logger);
35173560
} else {
35183561
// Our fuzzers aren't constrained by pesky things like valid signatures, so can
35193562
// spend our funding output with a transaction which doesn't match our past
@@ -4274,6 +4317,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
42744317
if *idx == input.previous_output.vout {
42754318
#[cfg(test)]
42764319
{
4320+
if self.latest_update_id == STUB_CHANNEL_UPDATE_IDENTIFIER {
4321+
return true;
4322+
}
42774323
// If the expected script is a known type, check that the witness
42784324
// appears to be spending the correct type (ie that the match would
42794325
// actually succeed in BIP 158/159-style filters).

lightning/src/ln/channel.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2074,6 +2074,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
20742074
self.update_time_counter
20752075
}
20762076

2077+
pub fn get_commitment_secret(&self) -> CounterpartyCommitmentSecrets {
2078+
self.commitment_secrets.clone()
2079+
}
2080+
20772081
pub fn get_latest_monitor_update_id(&self) -> u64 {
20782082
self.latest_monitor_update_id
20792083
}

lightning/src/ln/channelmanager.rs

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,14 @@ use crate::blinded_path::payment::{BlindedPaymentPath, Bolt12OfferContext, Bolt1
4040
use crate::chain;
4141
use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock};
4242
use crate::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator};
43-
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, WithChannelMonitor, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, MonitorEvent, CLOSED_CHANNEL_UPDATE_ID};
43+
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, MonitorEvent, WithChannelMonitor, ANTI_REORG_DELAY, CLOSED_CHANNEL_UPDATE_ID, CLTV_CLAIM_BUFFER, HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, STUB_CHANNEL_UPDATE_IDENTIFIER};
4444
use crate::chain::transaction::{OutPoint, TransactionData};
4545
use crate::events;
4646
use crate::events::{Event, EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination, PaymentFailureReason, ReplayEvent};
4747
// Since this struct is returned in `list_channels` methods, expose it here in case users want to
4848
// construct one themselves.
4949
use crate::ln::inbound_payment;
50+
use crate::ln::our_peer_storage::OurPeerStorage;
5051
use crate::ln::types::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
5152
use crate::ln::channel::{self, Channel, ChannelPhase, ChannelContext, ChannelError, ChannelUpdateStatus, ShutdownResult, UnfundedChannelContext, UpdateFulfillCommitFetch, OutboundV1Channel, InboundV1Channel, WithChannelContext};
5253
use crate::ln::channel_state::ChannelDetails;
@@ -76,8 +77,8 @@ use crate::offers::static_invoice::StaticInvoice;
7677
use crate::onion_message::async_payments::{AsyncPaymentsMessage, HeldHtlcAvailable, ReleaseHeldHtlc, AsyncPaymentsMessageHandler};
7778
use crate::onion_message::messenger::{Destination, MessageRouter, Responder, ResponseInstruction, MessageSendInstructions};
7879
use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
79-
use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider};
8080
use crate::sign::ecdsa::EcdsaChannelSigner;
81+
use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider};
8182
use crate::util::config::{UserConfig, ChannelConfig, ChannelConfigUpdate};
8283
use crate::util::wakers::{Future, Notifier};
8384
use crate::util::scid_utils::fake_scid;
@@ -7913,6 +7914,61 @@ where
79137914
peer_state.peer_storage = msg.data.clone();
79147915
}
79157916

7917+
fn internal_your_peer_storage(&self, counterparty_node_id: &PublicKey, msg: &msgs::YourPeerStorageMessage) {
7918+
let logger = WithContext::from(&self.logger, Some(*counterparty_node_id), None, None);
7919+
if msg.data.len() < 16 {
7920+
log_debug!(logger, "Invalid YourPeerStorage received from {}", log_pubkey!(counterparty_node_id));
7921+
return;
7922+
}
7923+
7924+
let mut res = vec![0; msg.data.len() - 16];
7925+
let our_peerstorage_encryption_key = self.node_signer.get_peer_storage_key();
7926+
let mut cyphertext_with_key = Vec::with_capacity(msg.data.len() + our_peerstorage_encryption_key.len());
7927+
cyphertext_with_key.extend(msg.data.clone());
7928+
cyphertext_with_key.extend_from_slice(&our_peerstorage_encryption_key);
7929+
7930+
match OurPeerStorage::decrypt_our_peer_storage(&mut res, cyphertext_with_key.as_slice()) {
7931+
Ok(()) => {
7932+
// Decryption successful, the plaintext is now stored in `res`.
7933+
log_debug!(logger, "Received a peer storage from peer {}", log_pubkey!(counterparty_node_id));
7934+
}
7935+
Err(_) => {
7936+
log_debug!(logger, "Invalid YourPeerStorage received from {}", log_pubkey!(counterparty_node_id));
7937+
return;
7938+
}
7939+
}
7940+
7941+
let our_peer_storage = <OurPeerStorage as Readable>::read(&mut ::bitcoin::io::Cursor::new(res)).unwrap();
7942+
let per_peer_state = self.per_peer_state.read().unwrap();
7943+
7944+
for ((node_id, channel_id), min_seen_secret) in our_peer_storage.get_cid_and_min_seen_secret().unwrap() {
7945+
let peer_state_mutex = match per_peer_state.get(&node_id) {
7946+
Some(mutex) => mutex,
7947+
None => {
7948+
log_debug!(logger, "Not able to find peer_state for the counterparty {}, channelId {}", log_pubkey!(node_id), channel_id);
7949+
continue;
7950+
}
7951+
};
7952+
7953+
let peer_state_lock = peer_state_mutex.lock().unwrap();
7954+
let peer_state = &*peer_state_lock;
7955+
7956+
match peer_state.channel_by_id.get(&channel_id) {
7957+
Some(ChannelPhase::Funded(chan)) => {
7958+
if chan.context.get_commitment_secret().get_min_seen_secret() > min_seen_secret {
7959+
panic!("Lost channel state for channel {}.
7960+
Received peer storage with a more recent state than what our node had.
7961+
Use the FundRecoverer to initiate a force close and sweep the funds.", channel_id);
7962+
}
7963+
},
7964+
Some(_) => {}
7965+
None => {
7966+
continue;
7967+
}
7968+
}
7969+
}
7970+
}
7971+
79167972
fn internal_funding_signed(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingSigned) -> Result<(), MsgHandleErrInternal> {
79177973
let best_block = *self.best_block.read().unwrap();
79187974
let per_peer_state = self.per_peer_state.read().unwrap();
@@ -12339,6 +12395,10 @@ where
1233912395
funding_txo_to_channel_id.insert(funding_txo, channel.context.channel_id());
1234012396
funding_txo_set.insert(funding_txo.clone());
1234112397
if let Some(ref mut monitor) = args.channel_monitors.get_mut(&funding_txo) {
12398+
if monitor.get_latest_update_id() == STUB_CHANNEL_UPDATE_IDENTIFIER {
12399+
panic!("ChannelMonitor for {} is stale and recovered from Peer Storage, it is not safe to run the node in normal mode.", monitor.channel_id());
12400+
}
12401+
1234212402
if channel.get_cur_holder_commitment_transaction_number() > monitor.get_cur_holder_commitment_number() ||
1234312403
channel.get_revoked_counterparty_commitment_transaction_number() > monitor.get_min_seen_secret() ||
1234412404
channel.get_cur_counterparty_commitment_transaction_number() > monitor.get_cur_counterparty_commitment_number() ||

0 commit comments

Comments
 (0)