Skip to content

Commit c94a64d

Browse files
Aditya SharmaAditya Sharma
authored andcommitted
channelmonitor: Create StubChannelMonitor so that channels can be stubbed to recover from PeerStorage.
1 parent df9c632 commit c94a64d

File tree

2 files changed

+111
-4
lines changed

2 files changed

+111
-4
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 110 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,21 @@ 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::our_peer_storage::StubChannelMonitor;
4241
use crate::ln::features::ChannelTypeFeatures;
42+
use crate::ln::our_peer_storage::StubChannelMonitor;
4343
use crate::chain;
4444
use crate::chain::{BestBlock, WatchedOutput};
4545
use crate::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator};
4646
use crate::chain::transaction::{OutPoint, TransactionData};
47+
use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC;
4748
use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, ecdsa::EcdsaChannelSigner, SignerProvider, EntropySource};
4849
use crate::chain::onchaintx::{ClaimEvent, FeerateStrategy, OnchainTxHandler};
4950
use crate::chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageSolvingData, PackageTemplate, RevokedOutput, RevokedHTLCOutput};
5051
use crate::chain::Filter;
5152
use crate::util::logger::{Logger, Record};
52-
use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, MaybeReadable, UpgradableRequired, Writer, Writeable, U48};
53+
use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, MaybeReadable, UpgradableRequired, Writer, Writeable, U48, VecWriter};
5354
use crate::util::byte_utils;
5455
use crate::events::{ClosureReason, Event, EventHandler, ReplayEvent};
5556
use crate::events::bump_transaction::{AnchorDescriptor, BumpTransactionEvent};
@@ -115,6 +116,11 @@ pub struct ChannelMonitorUpdate {
115116
/// No other [`ChannelMonitorUpdate`]s are allowed after force-close.
116117
pub const CLOSED_CHANNEL_UPDATE_ID: u64 = core::u64::MAX;
117118

119+
/// This update ID is used inside [`ChannelMonitorImpl`] to recognise
120+
/// that we're dealing with a [`StubChannelMonitor`]. Since we require some
121+
/// exceptions while dealing with it.
122+
pub const STUB_CHANNEL_UPDATE_IDENTIFIER: u64 = core::u64::MAX - 1;
123+
118124
impl Writeable for ChannelMonitorUpdate {
119125
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
120126
write_ver_prefix!(w, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
@@ -1434,6 +1440,100 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
14341440
})
14351441
}
14361442

1443+
/// Returns a [`ChannelMonitor`] using [`StubChannelMonitor`] and other
1444+
/// important information to sweep funds and create penalty transactions.
1445+
pub(crate) fn new_stub(secp_ctx: Secp256k1<secp256k1::All>, stub_channel: &StubChannelMonitor, keys: Signer, channel_parameters: ChannelTransactionParameters ,funding_info_scriptbuf: ScriptBuf, destination_script: ScriptBuf) -> ChannelMonitor<Signer> {
1446+
let mut outputs_to_watch = new_hash_map();
1447+
outputs_to_watch.insert(stub_channel.funding_outpoint.txid, vec![(stub_channel.funding_outpoint.index as u32, funding_info_scriptbuf.clone())]);
1448+
let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
1449+
let dummy_sig = crate::crypto::utils::sign(&secp_ctx, &secp256k1::Message::from_digest_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap());
1450+
let counterparty_payment_script = chan_utils::get_counterparty_payment_script(
1451+
&stub_channel.features, &keys.pubkeys().payment_point
1452+
);
1453+
let holder_revocation_basepoint = keys.pubkeys().revocation_basepoint;
1454+
let holder_commitment_tx = HolderSignedTx {
1455+
txid: stub_channel.funding_outpoint.txid,
1456+
revocation_key: RevocationKey(dummy_key),
1457+
a_htlc_key: HtlcKey(dummy_key),
1458+
b_htlc_key: HtlcKey(dummy_key),
1459+
delayed_payment_key: DelayedPaymentKey(dummy_key),
1460+
per_commitment_point: dummy_key,
1461+
htlc_outputs: Vec::new(), // There are never any HTLCs in the initial commitment transactions
1462+
to_self_value_sat: 0,
1463+
feerate_per_kw: 1,
1464+
};
1465+
1466+
let dummy_tx_creation_keys = TxCreationKeys {
1467+
per_commitment_point: dummy_key.clone(),
1468+
revocation_key: RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(dummy_key), &dummy_key),
1469+
broadcaster_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1470+
countersignatory_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1471+
broadcaster_delayed_payment_key: DelayedPaymentKey::from_basepoint(&secp_ctx, &DelayedPaymentBasepoint::from(dummy_key), &dummy_key),
1472+
};
1473+
let counterparty_htlc_sigs = Vec::new();
1474+
let mut nondust_htlcs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)> = Vec::new();
1475+
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());
1476+
let holder_commitment = HolderCommitmentTransaction::new(inner, dummy_sig, counterparty_htlc_sigs, &dummy_key, &PublicKey::from_slice(&[2;33]).unwrap());
1477+
let onchain_tx_handler = OnchainTxHandler::new(
1478+
stub_channel.channel_value_stoshis, stub_channel.channel_keys_id, destination_script.clone(), keys,
1479+
channel_parameters, holder_commitment, secp_ctx
1480+
);
1481+
let counterparty_commitment_params = CounterpartyCommitmentParameters { counterparty_delayed_payment_base_key: stub_channel.counterparty_delayed_payment_base_key,
1482+
counterparty_htlc_base_key: stub_channel.counterparty_htlc_base_key, on_counterparty_tx_csv: stub_channel.on_counterparty_tx_csv };
1483+
let mut counterparty_claimable_outpoints = new_hash_map();
1484+
counterparty_claimable_outpoints.insert(stub_channel.latest_state.unwrap(), Vec::new());
1485+
1486+
Self::from_impl(ChannelMonitorImpl {
1487+
latest_update_id: STUB_CHANNEL_UPDATE_IDENTIFIER,
1488+
commitment_transaction_number_obscure_factor: stub_channel.obscure_factor,
1489+
destination_script: destination_script.clone(),
1490+
broadcasted_holder_revokable_script: None,
1491+
counterparty_payment_script,
1492+
shutdown_script: None,
1493+
channel_keys_id: stub_channel.channel_keys_id,
1494+
holder_revocation_basepoint,
1495+
channel_id: stub_channel.channel_id,
1496+
funding_info: (stub_channel.funding_outpoint, ScriptBuf::new()),
1497+
current_counterparty_commitment_txid: None,
1498+
prev_counterparty_commitment_txid: None,
1499+
counterparty_commitment_params,
1500+
funding_redeemscript: ScriptBuf::new(),
1501+
channel_value_satoshis: stub_channel.channel_value_stoshis,
1502+
their_cur_per_commitment_points: stub_channel.their_cur_per_commitment_points,
1503+
on_holder_tx_csv: 1,
1504+
commitment_secrets: stub_channel.commitment_secrets.clone(),
1505+
counterparty_claimable_outpoints,
1506+
1507+
holder_pays_commitment_tx_fee: None,
1508+
1509+
counterparty_hash_commitment_number: new_hash_map(),
1510+
counterparty_commitment_txn_on_chain: new_hash_map(),
1511+
counterparty_fulfilled_htlcs: new_hash_map(),
1512+
prev_holder_signed_commitment_tx: None,
1513+
current_holder_commitment_tx: holder_commitment_tx,
1514+
current_counterparty_commitment_number: 0,
1515+
current_holder_commitment_number: 1,
1516+
payment_preimages: new_hash_map(),
1517+
pending_monitor_events: Vec::new(),
1518+
pending_events: Vec::new(),
1519+
is_processing_pending_events: false,
1520+
onchain_events_awaiting_threshold_conf: Vec::new(),
1521+
outputs_to_watch,
1522+
onchain_tx_handler,
1523+
lockdown_from_offchain: true,
1524+
holder_tx_signed: true,
1525+
funding_spend_seen: false,
1526+
funding_spend_confirmed: None,
1527+
confirmed_commitment_tx_counterparty_output: None,
1528+
htlcs_resolved_on_chain: Vec::new(),
1529+
spendable_txids_confirmed: Vec::new(),
1530+
best_block: stub_channel.best_block,
1531+
counterparty_node_id: Some(stub_channel.counterparty_node_id),
1532+
initial_counterparty_commitment_info: None,
1533+
balances_empty_height: None
1534+
})
1535+
}
1536+
14371537
#[cfg(test)]
14381538
fn provide_secret(&self, idx: u64, secret: [u8; 32]) -> Result<(), &'static str> {
14391539
self.inner.lock().unwrap().provide_secret(idx, secret)
@@ -3508,6 +3608,10 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35083608
block_hash, per_commitment_claimable_data.iter().map(|(htlc, htlc_source)|
35093609
(htlc, htlc_source.as_ref().map(|htlc_source| htlc_source.as_ref()))
35103610
), logger);
3611+
} else if self.latest_update_id == STUB_CHANNEL_UPDATE_IDENTIFIER {
3612+
// Since we aren't storing per commitment option inside stub channels.
3613+
fail_unbroadcast_htlcs!(self, "revoked counterparty", commitment_txid, tx, height,
3614+
block_hash, [].iter().map(|reference| *reference), logger);
35113615
} else {
35123616
// Our fuzzers aren't constrained by pesky things like valid signatures, so can
35133617
// spend our funding output with a transaction which doesn't match our past
@@ -4268,6 +4372,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
42684372
if *idx == input.previous_output.vout {
42694373
#[cfg(test)]
42704374
{
4375+
if self.latest_update_id == STUB_CHANNEL_UPDATE_IDENTIFIER {
4376+
return true;
4377+
}
42714378
// If the expected script is a known type, check that the witness
42724379
// appears to be spending the correct type (ie that the match would
42734380
// actually succeed in BIP 158/159-style filters).

lightning/src/ln/channelmanager.rs

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

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

0 commit comments

Comments
 (0)