Skip to content

Commit 853bcbb

Browse files
author
Antoine Riard
committed
Move htlc_updated_waiting_threshold_conf to an OnchainEvent model
We need also to track claim tx until their maturation to know when we may safely remove them from could-be-bumped-txn buffer
1 parent d310e89 commit 853bcbb

File tree

2 files changed

+162
-45
lines changed

2 files changed

+162
-45
lines changed

src/ln/channelmonitor.rs

Lines changed: 142 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,23 @@ enum InputDescriptors {
352352
RevokedOutput, // either a revoked to_local output on commitment tx, a revoked HTLC-Timeout output or a revoked HTLC-Success output
353353
}
354354

355+
/// Upon discovering of some classes of onchain tx by ChannelMonitor, we may have to take actions on it
356+
/// once they mature to enough confirmations (HTLC_FAIL_ANTI_REORG_DELAY)
357+
#[derive(Clone, PartialEq)]
358+
enum OnchainEvent {
359+
/// Outpoint under claim process by our own tx, once this one get enough confirmations, we remove it from
360+
/// bump-txn candidate buffer.
361+
Claim {
362+
outpoint: BitcoinOutPoint,
363+
},
364+
/// HTLC output getting solved by a timeout, at maturation we pass upstream payment source information to solve
365+
/// inbound HTLC in backward channel. Note, in case of preimage, we pass info to upstream without delay as we can
366+
/// only win from it, so it's never an OnchainEvent
367+
HTLCUpdate {
368+
htlc_update: (HTLCSource, PaymentHash),
369+
},
370+
}
371+
355372
const SERIALIZATION_VERSION: u8 = 1;
356373
const MIN_SERIALIZATION_VERSION: u8 = 1;
357374

@@ -402,7 +419,9 @@ pub struct ChannelMonitor {
402419

403420
destination_script: Script,
404421

405-
htlc_updated_waiting_threshold_conf: HashMap<u32, Vec<(HTLCSource, Option<PaymentPreimage>, PaymentHash)>>,
422+
// Used to track onchain events, i.e transactions parts of channels confirmed on chain, on which
423+
// we have to take actions once they reach enough confs. Actions depend on OnchainEvent type.
424+
onchain_events_waiting_threshold_conf: HashMap<u32, Vec<OnchainEvent>>,
406425

407426
// We simply modify last_block_hash in Channel's block_connected so that serialization is
408427
// consistent but hopefully the users' copy handles block_connected in a consistent way.
@@ -434,7 +453,7 @@ impl PartialEq for ChannelMonitor {
434453
self.current_local_signed_commitment_tx != other.current_local_signed_commitment_tx ||
435454
self.payment_preimages != other.payment_preimages ||
436455
self.destination_script != other.destination_script ||
437-
self.htlc_updated_waiting_threshold_conf != other.htlc_updated_waiting_threshold_conf
456+
self.onchain_events_waiting_threshold_conf != other.onchain_events_waiting_threshold_conf
438457
{
439458
false
440459
} else {
@@ -484,7 +503,7 @@ impl ChannelMonitor {
484503
payment_preimages: HashMap::new(),
485504
destination_script: destination_script,
486505

487-
htlc_updated_waiting_threshold_conf: HashMap::new(),
506+
onchain_events_waiting_threshold_conf: HashMap::new(),
488507

489508
last_block_hash: Default::default(),
490509
secp_ctx: Secp256k1::new(),
@@ -993,14 +1012,22 @@ impl ChannelMonitor {
9931012
self.last_block_hash.write(writer)?;
9941013
self.destination_script.write(writer)?;
9951014

996-
writer.write_all(&byte_utils::be64_to_array(self.htlc_updated_waiting_threshold_conf.len() as u64))?;
997-
for (ref target, ref updates) in self.htlc_updated_waiting_threshold_conf.iter() {
1015+
writer.write_all(&byte_utils::be64_to_array(self.onchain_events_waiting_threshold_conf.len() as u64))?;
1016+
for (ref target, ref events) in self.onchain_events_waiting_threshold_conf.iter() {
9981017
writer.write_all(&byte_utils::be32_to_array(**target))?;
999-
writer.write_all(&byte_utils::be64_to_array(updates.len() as u64))?;
1000-
for ref update in updates.iter() {
1001-
update.0.write(writer)?;
1002-
update.1.write(writer)?;
1003-
update.2.write(writer)?;
1018+
writer.write_all(&byte_utils::be64_to_array(events.len() as u64))?;
1019+
for ev in events.iter() {
1020+
match *ev {
1021+
OnchainEvent::Claim { ref outpoint } => {
1022+
writer.write_all(&[0; 1])?;
1023+
outpoint.write(writer)?;
1024+
},
1025+
OnchainEvent::HTLCUpdate { ref htlc_update } => {
1026+
writer.write_all(&[1; 1])?;
1027+
htlc_update.0.write(writer)?;
1028+
htlc_update.1.write(writer)?;
1029+
}
1030+
}
10041031
}
10051032
}
10061033

@@ -1238,14 +1265,21 @@ impl ChannelMonitor {
12381265
for &(ref htlc, ref source_option) in outpoints.iter() {
12391266
if let &Some(ref source) = source_option {
12401267
log_trace!(self, "Failing HTLC with payment_hash {} from {} remote commitment tx due to broadcast of revoked remote commitment transaction, waiting confirmation until {} height", log_bytes!(htlc.payment_hash.0), $commitment_tx, height + HTLC_FAIL_ANTI_REORG_DELAY - 1);
1241-
match self.htlc_updated_waiting_threshold_conf.entry(height + HTLC_FAIL_ANTI_REORG_DELAY - 1) {
1268+
match self.onchain_events_waiting_threshold_conf.entry(height + HTLC_FAIL_ANTI_REORG_DELAY - 1) {
12421269
hash_map::Entry::Occupied(mut entry) => {
12431270
let e = entry.get_mut();
1244-
e.retain(|ref update| update.0 != **source);
1245-
e.push(((**source).clone(), None, htlc.payment_hash.clone()));
1271+
e.retain(|ref event| {
1272+
match **event {
1273+
OnchainEvent::HTLCUpdate { ref htlc_update } => {
1274+
return htlc_update.0 != **source
1275+
},
1276+
_ => return true
1277+
}
1278+
});
1279+
e.push(OnchainEvent::HTLCUpdate { htlc_update: ((**source).clone(), htlc.payment_hash.clone())});
12461280
}
12471281
hash_map::Entry::Vacant(entry) => {
1248-
entry.insert(vec![((**source).clone(), None, htlc.payment_hash.clone())]);
1282+
entry.insert(vec![OnchainEvent::HTLCUpdate { htlc_update: ((**source).clone(), htlc.payment_hash.clone())}]);
12491283
}
12501284
}
12511285
}
@@ -1325,14 +1359,21 @@ impl ChannelMonitor {
13251359
}
13261360
}
13271361
log_trace!(self, "Failing HTLC with payment_hash {} from {} remote commitment tx due to broadcast of remote commitment transaction", log_bytes!(htlc.payment_hash.0), $commitment_tx);
1328-
match self.htlc_updated_waiting_threshold_conf.entry(height + HTLC_FAIL_ANTI_REORG_DELAY - 1) {
1362+
match self.onchain_events_waiting_threshold_conf.entry(height + HTLC_FAIL_ANTI_REORG_DELAY - 1) {
13291363
hash_map::Entry::Occupied(mut entry) => {
13301364
let e = entry.get_mut();
1331-
e.retain(|ref update| update.0 != **source);
1332-
e.push(((**source).clone(), None, htlc.payment_hash.clone()));
1365+
e.retain(|ref event| {
1366+
match **event {
1367+
OnchainEvent::HTLCUpdate { ref htlc_update } => {
1368+
return htlc_update.0 != **source
1369+
},
1370+
_ => return true
1371+
}
1372+
});
1373+
e.push(OnchainEvent::HTLCUpdate { htlc_update: ((**source).clone(), htlc.payment_hash.clone())});
13331374
}
13341375
hash_map::Entry::Vacant(entry) => {
1335-
entry.insert(vec![((**source).clone(), None, htlc.payment_hash.clone())]);
1376+
entry.insert(vec![OnchainEvent::HTLCUpdate { htlc_update: ((**source).clone(), htlc.payment_hash.clone())}]);
13361377
}
13371378
}
13381379
}
@@ -1704,16 +1745,23 @@ impl ChannelMonitor {
17041745
let mut watch_outputs = Vec::new();
17051746

17061747
macro_rules! wait_threshold_conf {
1707-
($height: expr, $source: expr, $update: expr, $commitment_tx: expr, $payment_hash: expr) => {
1748+
($height: expr, $source: expr, $commitment_tx: expr, $payment_hash: expr) => {
17081749
log_trace!(self, "Failing HTLC with payment_hash {} from {} local commitment tx due to broadcast of transaction, waiting confirmation until {} height", log_bytes!($payment_hash.0), $commitment_tx, height + HTLC_FAIL_ANTI_REORG_DELAY - 1);
1709-
match self.htlc_updated_waiting_threshold_conf.entry($height + HTLC_FAIL_ANTI_REORG_DELAY - 1) {
1750+
match self.onchain_events_waiting_threshold_conf.entry($height + HTLC_FAIL_ANTI_REORG_DELAY - 1) {
17101751
hash_map::Entry::Occupied(mut entry) => {
17111752
let e = entry.get_mut();
1712-
e.retain(|ref update| update.0 != $source);
1713-
e.push(($source, $update, $payment_hash));
1753+
e.retain(|ref event| {
1754+
match **event {
1755+
OnchainEvent::HTLCUpdate { ref htlc_update } => {
1756+
return htlc_update.0 != $source
1757+
},
1758+
_ => return true
1759+
}
1760+
});
1761+
e.push(OnchainEvent::HTLCUpdate { htlc_update: ($source, $payment_hash)});
17141762
}
17151763
hash_map::Entry::Vacant(entry) => {
1716-
entry.insert(vec![($source, $update, $payment_hash)]);
1764+
entry.insert(vec![OnchainEvent::HTLCUpdate { htlc_update: ($source, $payment_hash)}]);
17171765
}
17181766
}
17191767
}
@@ -1731,7 +1779,7 @@ impl ChannelMonitor {
17311779
for &(ref htlc, _, ref source) in &local_tx.htlc_outputs {
17321780
if htlc.transaction_output_index.is_none() {
17331781
if let &Some(ref source) = source {
1734-
wait_threshold_conf!(height, source.clone(), None, "lastest", htlc.payment_hash.clone());
1782+
wait_threshold_conf!(height, source.clone(), "lastest", htlc.payment_hash.clone());
17351783
}
17361784
}
17371785
}
@@ -1751,7 +1799,7 @@ impl ChannelMonitor {
17511799
for &(ref htlc, _, ref source) in &local_tx.htlc_outputs {
17521800
if htlc.transaction_output_index.is_none() {
17531801
if let &Some(ref source) = source {
1754-
wait_threshold_conf!(height, source.clone(), None, "previous", htlc.payment_hash.clone());
1802+
wait_threshold_conf!(height, source.clone(), "previous", htlc.payment_hash.clone());
17551803
}
17561804
}
17571805
}
@@ -1874,6 +1922,27 @@ impl ChannelMonitor {
18741922
if updated.len() > 0 {
18751923
htlc_updated.append(&mut updated);
18761924
}
1925+
for inp in &tx.input {
1926+
if self.our_claim_txn_waiting_first_conf.contains_key(&inp.previous_output) {
1927+
match self.onchain_events_waiting_threshold_conf.entry(height + HTLC_FAIL_ANTI_REORG_DELAY) {
1928+
hash_map::Entry::Occupied(mut entry) => {
1929+
let e = entry.get_mut();
1930+
e.retain(|ref event| {
1931+
match **event {
1932+
OnchainEvent::Claim { outpoint } => {
1933+
return outpoint != inp.previous_output
1934+
},
1935+
_ => return true
1936+
}
1937+
});
1938+
e.push(OnchainEvent::Claim { outpoint: inp.previous_output.clone()});
1939+
}
1940+
hash_map::Entry::Vacant(entry) => {
1941+
entry.insert(vec![OnchainEvent::Claim { outpoint: inp.previous_output.clone()}]);
1942+
}
1943+
}
1944+
}
1945+
}
18771946
}
18781947
if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx {
18791948
if self.would_broadcast_at_height(height) {
@@ -1902,19 +1971,27 @@ impl ChannelMonitor {
19021971
}
19031972
}
19041973
}
1905-
if let Some(updates) = self.htlc_updated_waiting_threshold_conf.remove(&height) {
1906-
for update in updates {
1907-
log_trace!(self, "HTLC {} failure update has get enough confirmation to be pass upstream", log_bytes!((update.2).0));
1908-
htlc_updated.push(update);
1974+
if let Some(events) = self.onchain_events_waiting_threshold_conf.remove(&height) {
1975+
for ev in events {
1976+
match ev {
1977+
OnchainEvent::Claim { outpoint } => {
1978+
},
1979+
OnchainEvent::HTLCUpdate { htlc_update } => {
1980+
log_trace!(self, "HTLC {} failure update has get enough confirmation to be pass upstream", log_bytes!((htlc_update.1).0));
1981+
htlc_updated.push((htlc_update.0, None, htlc_update.1));
1982+
},
1983+
}
19091984
}
19101985
}
19111986
self.last_block_hash = block_hash.clone();
19121987
(watch_outputs, spendable_outputs, htlc_updated)
19131988
}
19141989

19151990
fn block_disconnected(&mut self, height: u32, block_hash: &Sha256dHash) {
1916-
if let Some(_) = self.htlc_updated_waiting_threshold_conf.remove(&(height + HTLC_FAIL_ANTI_REORG_DELAY - 1)) {
1917-
//We discard htlc update there as failure-trigger tx (revoked commitment tx, non-revoked commitment tx, HTLC-timeout tx) has been disconnected
1991+
if let Some(_) = self.onchain_events_waiting_threshold_conf.remove(&(height + HTLC_FAIL_ANTI_REORG_DELAY - 1)) {
1992+
//We may discard:
1993+
//- htlc update there as failure-trigger tx (revoked commitment tx, non-revoked commitment tx, HTLC-timeout tx) has been disconnected
1994+
//- our claim tx on a commitment tx output
19181995
}
19191996
self.last_block_hash = block_hash.clone();
19201997
}
@@ -2096,14 +2173,21 @@ impl ChannelMonitor {
20962173
htlc_updated.push((source, Some(payment_preimage), payment_hash));
20972174
} else {
20982175
log_trace!(self, "Failing HTLC with payment_hash {} timeout by a spend tx, waiting confirmation until {} height", log_bytes!(payment_hash.0), height + HTLC_FAIL_ANTI_REORG_DELAY - 1);
2099-
match self.htlc_updated_waiting_threshold_conf.entry(height + HTLC_FAIL_ANTI_REORG_DELAY - 1) {
2176+
match self.onchain_events_waiting_threshold_conf.entry(height + HTLC_FAIL_ANTI_REORG_DELAY - 1) {
21002177
hash_map::Entry::Occupied(mut entry) => {
21012178
let e = entry.get_mut();
2102-
e.retain(|ref update| update.0 != source);
2103-
e.push((source, None, payment_hash.clone()));
2179+
e.retain(|ref event| {
2180+
match **event {
2181+
OnchainEvent::HTLCUpdate { ref htlc_update } => {
2182+
return htlc_update.0 != source
2183+
},
2184+
_ => return true
2185+
}
2186+
});
2187+
e.push(OnchainEvent::HTLCUpdate { htlc_update: (source, payment_hash)});
21042188
}
21052189
hash_map::Entry::Vacant(entry) => {
2106-
entry.insert(vec![(source, None, payment_hash)]);
2190+
entry.insert(vec![OnchainEvent::HTLCUpdate { htlc_update: (source, payment_hash)}]);
21072191
}
21082192
}
21092193
}
@@ -2326,18 +2410,31 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
23262410
let destination_script = Readable::read(reader)?;
23272411

23282412
let waiting_threshold_conf_len: u64 = Readable::read(reader)?;
2329-
let mut htlc_updated_waiting_threshold_conf = HashMap::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128));
2413+
let mut onchain_events_waiting_threshold_conf = HashMap::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128));
23302414
for _ in 0..waiting_threshold_conf_len {
23312415
let height_target = Readable::read(reader)?;
2332-
let updates_len: u64 = Readable::read(reader)?;
2333-
let mut updates = Vec::with_capacity(cmp::min(updates_len as usize, MAX_ALLOC_SIZE / 128));
2334-
for _ in 0..updates_len {
2335-
let htlc_source = Readable::read(reader)?;
2336-
let preimage = Readable::read(reader)?;
2337-
let hash = Readable::read(reader)?;
2338-
updates.push((htlc_source, preimage, hash));
2416+
let events_len: u64 = Readable::read(reader)?;
2417+
let mut events = Vec::with_capacity(cmp::min(events_len as usize, MAX_ALLOC_SIZE / 128));
2418+
for _ in 0..events_len {
2419+
let ev = match <u8 as Readable<R>>::read(reader)? {
2420+
0 => {
2421+
let outpoint = Readable::read(reader)?;
2422+
OnchainEvent::Claim {
2423+
outpoint
2424+
}
2425+
},
2426+
1 => {
2427+
let htlc_source = Readable::read(reader)?;
2428+
let hash = Readable::read(reader)?;
2429+
OnchainEvent::HTLCUpdate {
2430+
htlc_update: (htlc_source, hash)
2431+
}
2432+
},
2433+
_ => return Err(DecodeError::InvalidValue),
2434+
};
2435+
events.push(ev);
23392436
}
2340-
htlc_updated_waiting_threshold_conf.insert(height_target, updates);
2437+
onchain_events_waiting_threshold_conf.insert(height_target, events);
23412438
}
23422439

23432440
Ok((last_block_hash.clone(), ChannelMonitor {
@@ -2364,7 +2461,7 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
23642461

23652462
destination_script,
23662463

2367-
htlc_updated_waiting_threshold_conf,
2464+
onchain_events_waiting_threshold_conf,
23682465

23692466
last_block_hash,
23702467
secp_ctx,

src/util/ser.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::hash::Hash;
99
use secp256k1::Signature;
1010
use secp256k1::key::{PublicKey, SecretKey};
1111
use bitcoin::blockdata::script::Script;
12+
use bitcoin::blockdata::transaction::OutPoint;
1213
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
1314
use std::marker::Sized;
1415
use ln::msgs::DecodeError;
@@ -422,3 +423,22 @@ impl<R, T> Readable<R> for Option<T>
422423
}
423424
}
424425
}
426+
427+
impl Writeable for OutPoint {
428+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
429+
self.txid.write(w)?;
430+
self.vout.write(w)?;
431+
Ok(())
432+
}
433+
}
434+
435+
impl<R: Read> Readable<R> for OutPoint {
436+
fn read(r: &mut R) -> Result<Self, DecodeError> {
437+
let txid = Readable::read(r)?;
438+
let vout = Readable::read(r)?;
439+
Ok(OutPoint {
440+
txid,
441+
vout,
442+
})
443+
}
444+
}

0 commit comments

Comments
 (0)