Skip to content

Commit ca8b93c

Browse files
Aditya SharmaAditya Sharma
Aditya Sharma
authored and
Aditya Sharma
committed
channelmonitor: Create StubChannelMonitor so that channels can be stubbed to recover from PeerStorage.
1 parent 8226da4 commit ca8b93c

File tree

3 files changed

+116
-3
lines changed

3 files changed

+116
-3
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,20 @@ use crate::ln::channel::INITIAL_COMMITMENT_NUMBER;
3636
use crate::ln::types::{PaymentHash, PaymentPreimage, ChannelId};
3737
use crate::ln::msgs::DecodeError;
3838
use crate::ln::channel_keys::{DelayedPaymentKey, DelayedPaymentBasepoint, HtlcBasepoint, HtlcKey, RevocationKey, RevocationBasepoint};
39-
use crate::ln::chan_utils::{self,CommitmentTransaction, CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCClaim, ChannelTransactionParameters, HolderCommitmentTransaction, TxCreationKeys};
39+
use crate::ln::chan_utils::{self, CommitmentTransaction, CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCClaim, ChannelTransactionParameters, HolderCommitmentTransaction, TxCreationKeys};
4040
use crate::ln::channelmanager::{HTLCSource, SentHTLCId};
41+
use crate::ln::features::ChannelTypeFeatures;
4142
use crate::chain;
4243
use crate::chain::{BestBlock, WatchedOutput};
4344
use crate::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator};
4445
use crate::chain::transaction::{OutPoint, TransactionData};
46+
use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC;
4547
use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, ecdsa::EcdsaChannelSigner, SignerProvider, EntropySource};
4648
use crate::chain::onchaintx::{ClaimEvent, FeerateStrategy, OnchainTxHandler};
4749
use crate::chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageSolvingData, PackageTemplate, RevokedOutput, RevokedHTLCOutput};
4850
use crate::chain::Filter;
4951
use crate::util::logger::{Logger, Record};
50-
use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, MaybeReadable, UpgradableRequired, Writer, Writeable, U48};
52+
use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, MaybeReadable, UpgradableRequired, Writer, Writeable, U48, VecWriter};
5153
use crate::util::byte_utils;
5254
use crate::events::{ClosureReason, Event, EventHandler, ReplayEvent};
5355
use crate::events::bump_transaction::{AnchorDescriptor, BumpTransactionEvent};
@@ -113,6 +115,11 @@ pub struct ChannelMonitorUpdate {
113115
/// No other [`ChannelMonitorUpdate`]s are allowed after force-close.
114116
pub const CLOSED_CHANNEL_UPDATE_ID: u64 = core::u64::MAX;
115117

118+
/// This update ID is used inside [`ChannelMonitorImpl`] to recognise
119+
/// that we're dealing with a [`StubChannelMonitor`]. Since we require some
120+
/// exceptions while dealing with it.
121+
pub const STUB_CHANNEL_UPDATE_IDENTIFIER: u64 = CLOSED_CHANNEL_UPDATE_ID - 1;
122+
116123
impl Writeable for ChannelMonitorUpdate {
117124
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
118125
write_ver_prefix!(w, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
@@ -1628,6 +1635,100 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
16281635
})
16291636
}
16301637

1638+
/// Returns a [`ChannelMonitor`] using [`StubChannel`] and other
1639+
/// important information to sweep funds and create penalty transactions.
1640+
pub(crate) fn new_stub(secp_ctx: Secp256k1<secp256k1::All>, stub_channel: &StubChannel, best_block: BestBlock, keys: Signer, channel_parameters: ChannelTransactionParameters ,funding_info_scriptbuf: ScriptBuf, destination_script: ScriptBuf) -> ChannelMonitor<Signer> {
1641+
let mut outputs_to_watch = new_hash_map();
1642+
outputs_to_watch.insert(stub_channel.funding_outpoint.get_txid(), vec![(stub_channel.funding_outpoint.index as u32, funding_info_scriptbuf.clone())]);
1643+
let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
1644+
let dummy_sig = crate::crypto::utils::sign(&secp_ctx, &secp256k1::Message::from_digest_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap());
1645+
let counterparty_payment_script = chan_utils::get_counterparty_payment_script(
1646+
&stub_channel.features, &keys.pubkeys().payment_point
1647+
);
1648+
let holder_revocation_basepoint = keys.pubkeys().revocation_basepoint;
1649+
let holder_commitment_tx = HolderSignedTx {
1650+
txid: stub_channel.funding_outpoint.get_txid(),
1651+
revocation_key: RevocationKey(dummy_key),
1652+
a_htlc_key: HtlcKey(dummy_key),
1653+
b_htlc_key: HtlcKey(dummy_key),
1654+
delayed_payment_key: DelayedPaymentKey(dummy_key),
1655+
per_commitment_point: dummy_key,
1656+
htlc_outputs: Vec::new(), // There are never any HTLCs in the initial commitment transactions
1657+
to_self_value_sat: 0,
1658+
feerate_per_kw: 1,
1659+
};
1660+
1661+
let dummy_tx_creation_keys = TxCreationKeys {
1662+
per_commitment_point: dummy_key.clone(),
1663+
revocation_key: RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(dummy_key), &dummy_key),
1664+
broadcaster_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1665+
countersignatory_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1666+
broadcaster_delayed_payment_key: DelayedPaymentKey::from_basepoint(&secp_ctx, &DelayedPaymentBasepoint::from(dummy_key), &dummy_key),
1667+
};
1668+
let counterparty_htlc_sigs = Vec::new();
1669+
let mut nondust_htlcs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)> = Vec::new();
1670+
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, dummy_key.clone(), dummy_key.clone(), dummy_tx_creation_keys, 0, &mut nondust_htlcs, &channel_parameters.as_counterparty_broadcastable());
1671+
let holder_commitment = HolderCommitmentTransaction::new(inner, dummy_sig, counterparty_htlc_sigs, &dummy_key, &PublicKey::from_slice(&[2;33]).unwrap());
1672+
let onchain_tx_handler = OnchainTxHandler::new(
1673+
stub_channel.channel_value_stoshis, stub_channel.channel_keys_id, destination_script.clone(), keys,
1674+
channel_parameters, holder_commitment, secp_ctx
1675+
);
1676+
let counterparty_commitment_params = CounterpartyCommitmentParameters { counterparty_delayed_payment_base_key: stub_channel.counterparty_delayed_payment_base_key,
1677+
counterparty_htlc_base_key: stub_channel.counterparty_htlc_base_key, on_counterparty_tx_csv: stub_channel.on_counterparty_tx_csv };
1678+
let mut counterparty_claimable_outpoints = new_hash_map();
1679+
counterparty_claimable_outpoints.insert(stub_channel.latest_state.unwrap(), Vec::new());
1680+
1681+
Self::from_impl(ChannelMonitorImpl {
1682+
latest_update_id: STUB_CHANNEL_UPDATE_IDENTIFIER,
1683+
commitment_transaction_number_obscure_factor: stub_channel.obscure_factor,
1684+
destination_script: destination_script.clone(),
1685+
broadcasted_holder_revokable_script: None,
1686+
counterparty_payment_script,
1687+
shutdown_script: None,
1688+
channel_keys_id: stub_channel.channel_keys_id,
1689+
holder_revocation_basepoint,
1690+
channel_id: stub_channel.channel_id,
1691+
funding_info: (stub_channel.funding_outpoint, ScriptBuf::new()),
1692+
current_counterparty_commitment_txid: None,
1693+
prev_counterparty_commitment_txid: None,
1694+
counterparty_commitment_params,
1695+
funding_redeemscript: ScriptBuf::new(),
1696+
channel_value_satoshis: stub_channel.channel_value_stoshis,
1697+
their_cur_per_commitment_points: stub_channel.their_cur_per_commitment_points,
1698+
on_holder_tx_csv: 1,
1699+
commitment_secrets: stub_channel.commitment_secrets.clone(),
1700+
counterparty_claimable_outpoints,
1701+
1702+
holder_pays_commitment_tx_fee: None,
1703+
1704+
counterparty_hash_commitment_number: new_hash_map(),
1705+
counterparty_commitment_txn_on_chain: new_hash_map(),
1706+
counterparty_fulfilled_htlcs: new_hash_map(),
1707+
prev_holder_signed_commitment_tx: None,
1708+
current_holder_commitment_tx: holder_commitment_tx,
1709+
current_counterparty_commitment_number: 0,
1710+
current_holder_commitment_number: 1,
1711+
payment_preimages: new_hash_map(),
1712+
pending_monitor_events: Vec::new(),
1713+
pending_events: Vec::new(),
1714+
is_processing_pending_events: false,
1715+
onchain_events_awaiting_threshold_conf: Vec::new(),
1716+
outputs_to_watch,
1717+
onchain_tx_handler,
1718+
lockdown_from_offchain: true,
1719+
holder_tx_signed: true,
1720+
funding_spend_seen: false,
1721+
funding_spend_confirmed: None,
1722+
confirmed_commitment_tx_counterparty_output: None,
1723+
htlcs_resolved_on_chain: Vec::new(),
1724+
spendable_txids_confirmed: Vec::new(),
1725+
best_block,
1726+
counterparty_node_id: Some(stub_channel.counterparty_node_id),
1727+
initial_counterparty_commitment_info: None,
1728+
balances_empty_height: None
1729+
})
1730+
}
1731+
16311732
#[cfg(test)]
16321733
fn provide_secret(&self, idx: u64, secret: [u8; 32]) -> Result<(), &'static str> {
16331734
self.inner.lock().unwrap().provide_secret(idx, secret)
@@ -3702,6 +3803,10 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
37023803
block_hash, per_commitment_claimable_data.iter().map(|(htlc, htlc_source)|
37033804
(htlc, htlc_source.as_ref().map(|htlc_source| htlc_source.as_ref()))
37043805
), logger);
3806+
} else if self.latest_update_id == STUB_CHANNEL_UPDATE_IDENTIFIER {
3807+
// Since we aren't storing per commitment option inside stub channels.
3808+
fail_unbroadcast_htlcs!(self, "revoked counterparty", commitment_txid, tx, height,
3809+
block_hash, [].iter().map(|reference| *reference), logger);
37053810
} else {
37063811
// Our fuzzers aren't constrained by pesky things like valid signatures, so can
37073812
// spend our funding output with a transaction which doesn't match our past
@@ -4462,6 +4567,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
44624567
if *idx == input.previous_output.vout {
44634568
#[cfg(test)]
44644569
{
4570+
if self.latest_update_id == STUB_CHANNEL_UPDATE_IDENTIFIER {
4571+
return true;
4572+
}
44654573
// If the expected script is a known type, check that the witness
44664574
// appears to be spending the correct type (ie that the match would
44674575
// actually succeed in BIP 158/159-style filters).

lightning/src/chain/transaction.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ impl OutPoint {
6666
vout: self.index as u32,
6767
}
6868
}
69+
70+
/// Returns the [`Txid`] of the [`OutPoint`].
71+
pub fn get_txid(self) -> Txid {
72+
self.txid
73+
}
6974
}
7075

7176
impl core::fmt::Display for OutPoint {

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7898,7 +7898,7 @@ where
78987898
};
78997899
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
79007900
let peer_state = &mut *peer_state_lock;
7901-
let logger = WithContext::from(&self.logger, Some(*counterparty_node_id), None);
7901+
let logger = WithContext::from(&self.logger, Some(*counterparty_node_id), None, None);
79027902

79037903
// Check if we have any channels with the peer (Currently we only provide the servie to peers we have a channel with).
79047904
if !peer_state.channel_by_id.values().any(|phase| matches!(phase, ChannelPhase::Funded(_))) {

0 commit comments

Comments
 (0)