Skip to content

Commit 8d6ae08

Browse files
Aditya SharmaAditya Sharma
authored andcommitted
lightning: Add struct for building OurPeerStorage, it gets updated everytime a LatestCounterpartyCommitmentTxn update is sent. It would be encrypted and sent to our peers.
1 parent c0c9606 commit 8d6ae08

File tree

3 files changed

+270
-3
lines changed

3 files changed

+270
-3
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,191 @@ impl Readable for IrrevocablyResolvedHTLC {
764764
}
765765
}
766766

767+
/// [StubChannel] is the smallest unit of [OurPeerStorage], it contains
768+
/// information about a single channel using which we can recover on-chain funds.
769+
#[derive(Clone, PartialEq, Eq)]
770+
pub struct StubChannel {
771+
pub channel_id: ChannelId,
772+
pub funding_outpoint: OutPoint,
773+
pub channel_value_stoshis: u64,
774+
pub channel_keys_id: [u8;32],
775+
pub commitment_secrets: CounterpartyCommitmentSecrets,
776+
pub counterparty_node_id: PublicKey,
777+
pub counterparty_delayed_payment_base_key: DelayedPaymentBasepoint,
778+
pub counterparty_htlc_base_key: HtlcBasepoint,
779+
pub on_counterparty_tx_csv: u16,
780+
pub obscure_factor: u64,
781+
pub(crate) latest_state: HashMap<Txid, Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>>,
782+
pub their_cur_per_commitment_points: Option<(u64, PublicKey, Option<PublicKey>)>,
783+
pub features: ChannelTypeFeatures,
784+
}
785+
786+
impl StubChannel {
787+
pub(crate) fn new(channel_id: ChannelId, funding_outpoint: OutPoint, channel_value_stoshis: u64, channel_keys_id: [u8; 32],
788+
commitment_secrets: CounterpartyCommitmentSecrets, counterparty_node_id: PublicKey, counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, counterparty_htlc_base_key: HtlcBasepoint, on_counterparty_tx_csv: u16,
789+
obscure_factor: u64, latest_state: HashMap<Txid, Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>>, their_cur_per_commitment_points: Option<(u64, PublicKey, Option<PublicKey>)>,
790+
features: ChannelTypeFeatures) -> Self {
791+
StubChannel {
792+
channel_id,
793+
funding_outpoint,
794+
channel_value_stoshis,
795+
channel_keys_id,
796+
commitment_secrets,
797+
counterparty_node_id,
798+
counterparty_delayed_payment_base_key,
799+
counterparty_htlc_base_key,
800+
on_counterparty_tx_csv,
801+
obscure_factor,
802+
latest_state,
803+
their_cur_per_commitment_points,
804+
features,
805+
}
806+
}
807+
}
808+
809+
impl_writeable_tlv_based!(StubChannel, {
810+
(0, channel_id, required),
811+
(2, channel_keys_id, required),
812+
(4, channel_value_stoshis, required),
813+
(6, funding_outpoint, required),
814+
(8, commitment_secrets, required),
815+
(10, counterparty_node_id, required),
816+
(12, counterparty_delayed_payment_base_key, required),
817+
(14, counterparty_htlc_base_key, required),
818+
(16, on_counterparty_tx_csv, required),
819+
(18, obscure_factor, required),
820+
(20, latest_state, required),
821+
(22, their_cur_per_commitment_points, option),
822+
(24, features, required),
823+
});
824+
825+
/// [OurPeerStorage] is used to store our channels using which we
826+
/// can create our PeerStorage Backup.
827+
/// This includes timestamp to compare between two given
828+
/// [OurPeerStorage] and version defines the structure.
829+
#[derive(Clone, PartialEq, Eq)]
830+
pub struct OurPeerStorage {
831+
pub version: u32,
832+
pub timestamp: u32,
833+
pub channels: Vec<StubChannel>,
834+
}
835+
836+
impl OurPeerStorage {
837+
pub fn new() -> Self {
838+
let duration_since_epoch = std::time::SystemTime::now()
839+
.duration_since(std::time::SystemTime::UNIX_EPOCH)
840+
.expect("Time must be > 1970");
841+
842+
Self {
843+
version: 1,
844+
timestamp: duration_since_epoch.as_secs() as u32,
845+
channels: Vec::new(),
846+
}
847+
}
848+
849+
pub fn stub_channel(&mut self, chan: StubChannel) {
850+
self.channels.push(chan);
851+
}
852+
853+
pub(crate) fn update_latest_state(&mut self, cid: ChannelId, txid: Txid, htlc_data: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>, their_cur_per_commitment_points: Option<(u64, PublicKey, Option<PublicKey>)>) {
854+
for stub_channel in &mut self.channels {
855+
if stub_channel.channel_id == cid {
856+
let mut latest_state = HashMap::new();
857+
latest_state.insert(txid, htlc_data);
858+
stub_channel.latest_state = latest_state;
859+
stub_channel.their_cur_per_commitment_points = their_cur_per_commitment_points;
860+
return;
861+
}
862+
}
863+
}
864+
865+
pub(crate) fn provide_secret(&mut self, cid: ChannelId, idx:u64, secret: [u8; 32]) -> Result<(), ()> {
866+
for stub_channel in &mut self.channels {
867+
if stub_channel.channel_id == cid {
868+
return stub_channel.commitment_secrets.provide_secret(idx, secret);
869+
}
870+
}
871+
return Err(());
872+
}
873+
874+
pub(crate) fn update_state_from_monitor_update(&mut self, cid: ChannelId, monitor_update: ChannelMonitorUpdate) -> Result<(),()> {
875+
for update in monitor_update.updates.iter() {
876+
match update {
877+
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid, htlc_outputs, commitment_number,
878+
their_per_commitment_point, .. } => {
879+
let stub_channels = &self.channels;
880+
let mut cur_per_commitment_points = None;
881+
for stub_channel in stub_channels {
882+
if stub_channel.channel_id == cid {
883+
match stub_channel.their_cur_per_commitment_points {
884+
Some(old_points) => {
885+
if old_points.0 == commitment_number + 1 {
886+
cur_per_commitment_points = Some((old_points.0, old_points.1, Some(*their_per_commitment_point)));
887+
} else if old_points.0 == commitment_number + 2 {
888+
if let Some(old_second_point) = old_points.2 {
889+
cur_per_commitment_points = Some((old_points.0 - 1, old_second_point, Some(*their_per_commitment_point)));
890+
} else {
891+
cur_per_commitment_points = Some((*commitment_number, *their_per_commitment_point, None));
892+
}
893+
} else {
894+
cur_per_commitment_points = Some((*commitment_number, *their_per_commitment_point, None));
895+
}
896+
},
897+
None => {
898+
cur_per_commitment_points = Some((*commitment_number, *their_per_commitment_point, None));
899+
}
900+
}
901+
}
902+
}
903+
let mut htlc_data = htlc_outputs.clone();
904+
for htlc in &mut htlc_data {
905+
htlc.1 = None;
906+
}
907+
self.update_latest_state(cid, *commitment_txid, htlc_data, cur_per_commitment_points);
908+
return Ok(());
909+
}
910+
_ => {}
911+
}
912+
}
913+
Err(())
914+
}
915+
916+
pub fn encrypt_our_peer_storage(&self, key: [u8; 32]) -> Vec<u8> {
917+
let n = 0u64;
918+
let mut peer_storage = VecWriter(Vec::new());
919+
self.write(&mut peer_storage).unwrap();
920+
let mut res = vec![0;peer_storage.0.len() + 16];
921+
922+
let plaintext = &peer_storage.0[..];
923+
let mut nonce = [0; 12];
924+
nonce[4..].copy_from_slice(&n.to_le_bytes()[..]);
925+
926+
let mut chacha = ChaCha20Poly1305RFC::new(&key, &nonce, b"");
927+
let mut tag = [0; 16];
928+
chacha.encrypt(plaintext, &mut res[0..plaintext.len()], &mut tag);
929+
res[plaintext.len()..].copy_from_slice(&tag);
930+
res
931+
}
932+
933+
pub fn decrypt_our_peer_storage(&self, res: &mut[u8], cyphertext: &[u8], key: [u8; 32]) -> Result<(), ()> {
934+
let n = 0u64;
935+
let mut nonce = [0; 12];
936+
nonce[4..].copy_from_slice(&n.to_le_bytes()[..]);
937+
938+
let mut chacha = ChaCha20Poly1305RFC::new(&key, &nonce, b"");
939+
if chacha.variable_time_decrypt(&cyphertext[0..cyphertext.len() - 16], res, &cyphertext[cyphertext.len() - 16..]).is_err() {
940+
return Err(());
941+
}
942+
Ok(())
943+
}
944+
}
945+
946+
impl_writeable_tlv_based!(OurPeerStorage, {
947+
(0, version, (default_value, 1)),
948+
(2, timestamp, required),
949+
(4, channels, optional_vec),
950+
});
951+
767952
/// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates
768953
/// on-chain transactions to ensure no loss of funds occurs.
769954
///
@@ -1439,6 +1624,19 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
14391624
self.inner.lock().unwrap().get_latest_update_id()
14401625
}
14411626

1627+
/// Gets the latest claiming info from the ChannelMonitor to update our PeerStorageBackup.
1628+
pub(crate) fn get_latest_commitment_txn_and_its_claiming_info(&self) -> Option<(Txid, Vec<(HTLCOutputInCommitment, Option<std::boxed::Box<HTLCSource>>)>, Option<(u64, PublicKey, Option<PublicKey>)>)> {
1629+
let lock = self.inner.lock().unwrap();
1630+
if let Some(latest_txid) = lock.current_counterparty_commitment_txid {
1631+
return Some((
1632+
latest_txid, lock.counterparty_claimable_outpoints.get(&latest_txid).unwrap().clone(),
1633+
lock.their_cur_per_commitment_points
1634+
))
1635+
}
1636+
1637+
None
1638+
}
1639+
14421640
/// Gets the funding transaction outpoint of the channel this ChannelMonitor is monitoring for.
14431641
pub fn get_funding_txo(&self) -> (OutPoint, ScriptBuf) {
14441642
self.inner.lock().unwrap().get_funding_txo().clone()

lightning/src/ln/channel.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2000,6 +2000,18 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
20002000
self.update_time_counter
20012001
}
20022002

2003+
pub fn get_commitment_secret(&self) -> CounterpartyCommitmentSecrets {
2004+
self.commitment_secrets.clone()
2005+
}
2006+
2007+
pub fn get_channel_keys_id(&self) -> [u8;32] {
2008+
self.channel_keys_id
2009+
}
2010+
2011+
pub fn get_commitment_txn_number_obscure_factor(&self) -> u64 {
2012+
get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound())
2013+
}
2014+
20032015
pub fn get_latest_monitor_update_id(&self) -> u64 {
20042016
self.latest_monitor_update_id
20052017
}
@@ -2298,7 +2310,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
22982310
height.checked_sub(self.funding_tx_confirmation_height).map_or(0, |c| c + 1)
22992311
}
23002312

2301-
fn get_holder_selected_contest_delay(&self) -> u16 {
2313+
pub fn get_holder_selected_contest_delay(&self) -> u16 {
23022314
self.channel_transaction_parameters.holder_selected_contest_delay
23032315
}
23042316

lightning/src/ln/channelmanager.rs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, Paym
3737
use crate::chain;
3838
use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock};
3939
use crate::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator};
40-
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};
40+
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, StubChannelMonitor, StubChannel, OurPeerStorage, WithChannelMonitor, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, MonitorEvent, CLOSED_CHANNEL_UPDATE_ID};
4141
use crate::chain::transaction::{OutPoint, TransactionData};
4242
use crate::events;
4343
use crate::events::{Event, EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination, PaymentFailureReason};
@@ -2122,6 +2122,7 @@ where
21222122
entropy_source: ES,
21232123
node_signer: NS,
21242124
signer_provider: SP,
2125+
our_peer_storage: FairRwLock<OurPeerStorage>,
21252126
peer_storage: Mutex<HashMap<PublicKey, Vec<u8>>>,
21262127
logger: L,
21272128
}
@@ -2901,6 +2902,7 @@ where
29012902
entropy_source,
29022903
node_signer,
29032904
signer_provider,
2905+
our_peer_storage: FairRwLock::new(OurPeerStorage::new()),
29042906
peer_storage: Mutex::new(new_hash_map()),
29052907
logger,
29062908
}
@@ -6286,6 +6288,8 @@ where
62866288
chan_id, action);
62876289
peer_state.monitor_update_blocked_actions.entry(chan_id).or_insert(Vec::new()).push(action);
62886290
}
6291+
6292+
let _ = self.our_peer_storage.write().unwrap().update_state_from_monitor_update(chan.context.channel_id(), monitor_update.clone());
62896293
if !during_init {
62906294
handle_new_monitor_update!(self, prev_hop.outpoint, monitor_update, peer_state_lock,
62916295
peer_state, per_peer_state, chan);
@@ -7294,7 +7298,17 @@ where
72947298
let mut pending_events = self.pending_events.lock().unwrap();
72957299
emit_channel_ready_event!(pending_events, chan);
72967300
}
7297-
7301+
// Update Peer Storage.
7302+
let counterparty_channel_parameters = chan.context.channel_transaction_parameters.counterparty_parameters.as_ref().unwrap();
7303+
let counterparty_delayed_payment_base_key = counterparty_channel_parameters.pubkeys.delayed_payment_basepoint;
7304+
let counterparty_htlc_base_key = counterparty_channel_parameters.pubkeys.htlc_basepoint;
7305+
let stub_chan = StubChannel::new(chan.context.channel_id(), chan.context.get_funding_txo().unwrap(), chan.context.get_value_satoshis(),
7306+
chan.context.get_channel_keys_id(), chan.context.get_commitment_secret(),
7307+
chan.context.get_counterparty_node_id(), counterparty_delayed_payment_base_key, counterparty_htlc_base_key,
7308+
chan.context.get_holder_selected_contest_delay(),
7309+
chan.context.get_commitment_txn_number_obscure_factor(), new_hash_map(),
7310+
None, chan.context.channel_transaction_parameters.channel_type_features.clone());
7311+
self.our_peer_storage.write().unwrap().stub_channel(stub_chan);
72987312
Ok(())
72997313
} else {
73007314
try_chan_phase_entry!(self, Err(ChannelError::close(
@@ -7641,6 +7655,7 @@ where
76417655
let funding_txo = chan.context.get_funding_txo();
76427656
let monitor_update_opt = try_chan_phase_entry!(self, chan.commitment_signed(&msg, &&logger), chan_phase_entry);
76437657
if let Some(monitor_update) = monitor_update_opt {
7658+
let _ = self.our_peer_storage.write().unwrap().update_state_from_monitor_update(chan.context.channel_id(), monitor_update.clone());
76447659
handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock,
76457660
peer_state, per_peer_state, chan);
76467661
}
@@ -7834,9 +7849,15 @@ where
78347849
} else { false };
78357850
let (htlcs_to_fail, monitor_update_opt) = try_chan_phase_entry!(self,
78367851
chan.revoke_and_ack(&msg, &self.fee_estimator, &&logger, mon_update_blocked), chan_phase_entry);
7852+
7853+
let mut our_peer_storage = self.our_peer_storage.write().unwrap();
7854+
let _ = our_peer_storage.provide_secret(chan.context.channel_id(), chan.get_cur_counterparty_commitment_transaction_number() + 1, msg.per_commitment_secret);
78377855
if let Some(monitor_update) = monitor_update_opt {
78387856
let funding_txo = funding_txo_opt
78397857
.expect("Funding outpoint must have been set for RAA handling to succeed");
7858+
7859+
let _ = our_peer_storage.update_state_from_monitor_update(chan.context.channel_id(), monitor_update.clone());
7860+
78407861
handle_new_monitor_update!(self, funding_txo, monitor_update,
78417862
peer_state_lock, peer_state, per_peer_state, chan);
78427863
}
@@ -8180,6 +8201,7 @@ where
81808201
}
81818202
if let Some(monitor_update) = monitor_opt {
81828203
has_monitor_update = true;
8204+
let _ = self.our_peer_storage.write().unwrap().update_state_from_monitor_update(chan.context.channel_id(), monitor_update.clone());
81838205

81848206
handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update,
81858207
peer_state_lock, peer_state, per_peer_state, chan);
@@ -11363,6 +11385,8 @@ where
1136311385
let mut channel_closures = VecDeque::new();
1136411386
let mut close_background_events = Vec::new();
1136511387
let mut funding_txo_to_channel_id = hash_map_with_capacity(channel_count as usize);
11388+
let mut our_peer_storage: OurPeerStorage = OurPeerStorage::new();
11389+
1136611390
for _ in 0..channel_count {
1136711391
let mut channel: Channel<SP> = Channel::read(reader, (
1136811392
&args.entropy_source, &args.signer_provider, best_block_height, &provided_channel_type_features(&args.default_config)
@@ -11371,7 +11395,39 @@ where
1137111395
let funding_txo = channel.context.get_funding_txo().ok_or(DecodeError::InvalidValue)?;
1137211396
funding_txo_to_channel_id.insert(funding_txo, channel.context.channel_id());
1137311397
funding_txo_set.insert(funding_txo.clone());
11398+
let counterparty_channel_parameters = channel.context.channel_transaction_parameters.counterparty_parameters.as_ref().unwrap();
11399+
let counterparty_delayed_payment_base_key = counterparty_channel_parameters.pubkeys.delayed_payment_basepoint;
11400+
let counterparty_htlc_base_key = counterparty_channel_parameters.pubkeys.htlc_basepoint;
11401+
11402+
let stub_chan = StubChannel::new(
11403+
channel.context.channel_id(),
11404+
funding_txo,
11405+
channel.context.get_value_satoshis(),
11406+
channel.context.get_channel_keys_id(),
11407+
channel.context.get_commitment_secret(),
11408+
channel.context.get_counterparty_node_id(),
11409+
counterparty_delayed_payment_base_key,
11410+
counterparty_htlc_base_key,
11411+
channel.context.get_holder_selected_contest_delay(),
11412+
channel.context.get_commitment_txn_number_obscure_factor(),
11413+
new_hash_map(),
11414+
None,
11415+
channel.context.channel_transaction_parameters.channel_type_features.clone(),
11416+
);
11417+
our_peer_storage.stub_channel(stub_chan);
1137411418
if let Some(ref mut monitor) = args.channel_monitors.get_mut(&funding_txo) {
11419+
if let Some(latest_commitment_txn_info) = monitor.get_latest_commitment_txn_and_its_claiming_info() {
11420+
11421+
let mut htlc_data = latest_commitment_txn_info.1;
11422+
11423+
// We do not need HTLCSource to be backed up.
11424+
for htlc in &mut htlc_data {
11425+
htlc.1 = None;
11426+
}
11427+
11428+
our_peer_storage.update_latest_state(monitor.channel_id(), latest_commitment_txn_info.0, htlc_data, latest_commitment_txn_info.2);
11429+
}
11430+
1137511431
if channel.get_cur_holder_commitment_transaction_number() > monitor.get_cur_holder_commitment_number() ||
1137611432
channel.get_revoked_counterparty_commitment_transaction_number() > monitor.get_min_seen_secret() ||
1137711433
channel.get_cur_counterparty_commitment_transaction_number() > monitor.get_cur_counterparty_commitment_number() ||
@@ -12215,6 +12271,7 @@ where
1221512271

1221612272
last_days_feerates: Mutex::new(VecDeque::new()),
1221712273

12274+
our_peer_storage: FairRwLock::new(our_peer_storage),
1221812275
peer_storage: Mutex::new(peer_storage),
1221912276
logger: args.logger,
1222012277
default_configuration: args.default_config,

0 commit comments

Comments
 (0)