Skip to content

Commit 78ca873

Browse files
author
Antoine Riard
committed
Add preimages extraction in block_connected to claim funds
backward Add caching of PreviousHopData even in case of non-terminal peer to be able to route backward from on-chain resolution and prune them when htlc is updated by other node
1 parent 826233e commit 78ca873

File tree

2 files changed

+182
-26
lines changed

2 files changed

+182
-26
lines changed

src/ln/channel.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,7 +1508,7 @@ impl Channel {
15081508

15091509
/// Removes an outbound HTLC which has been commitment_signed by the remote end
15101510
#[inline]
1511-
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<[u8; 32]>, fail_reason: Option<HTLCFailReason>) -> Result<&HTLCSource, ChannelError> {
1511+
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<[u8; 32]>, fail_reason: Option<HTLCFailReason>) -> Result<(&HTLCSource, [u8;32]), ChannelError> {
15121512
for htlc in self.pending_outbound_htlcs.iter_mut() {
15131513
if htlc.htlc_id == htlc_id {
15141514
match check_preimage {
@@ -1528,13 +1528,13 @@ impl Channel {
15281528
OutboundHTLCState::AwaitingRemoteRevokeToRemove | OutboundHTLCState::AwaitingRemovedRemoteRevoke | OutboundHTLCState::RemoteRemoved =>
15291529
return Err(ChannelError::Close("Remote tried to fulfill HTLC that they'd already fulfilled")),
15301530
}
1531-
return Ok(&htlc.source);
1531+
return Ok((&htlc.source, htlc.payment_hash));
15321532
}
15331533
}
15341534
Err(ChannelError::Close("Remote tried to fulfill/fail an HTLC we couldn't find"))
15351535
}
15361536

1537-
pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<&HTLCSource, ChannelError> {
1537+
pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<(&HTLCSource, [u8;32]), ChannelError> {
15381538
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
15391539
return Err(ChannelError::Close("Got fulfill HTLC message when channel was not in an operational state"));
15401540
}
@@ -1550,7 +1550,7 @@ impl Channel {
15501550
self.mark_outbound_htlc_removed(msg.htlc_id, Some(payment_hash), None)
15511551
}
15521552

1553-
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<&HTLCSource, ChannelError> {
1553+
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<(&HTLCSource, [u8;32]), ChannelError> {
15541554
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
15551555
return Err(ChannelError::Close("Got fail HTLC message when channel was not in an operational state"));
15561556
}
@@ -1561,7 +1561,7 @@ impl Channel {
15611561
self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason))
15621562
}
15631563

1564-
pub fn update_fail_malformed_htlc<'a>(&mut self, msg: &msgs::UpdateFailMalformedHTLC, fail_reason: HTLCFailReason) -> Result<&HTLCSource, ChannelError> {
1564+
pub fn update_fail_malformed_htlc<'a>(&mut self, msg: &msgs::UpdateFailMalformedHTLC, fail_reason: HTLCFailReason) -> Result<(&HTLCSource, [u8;32]), ChannelError> {
15651565
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
15661566
return Err(ChannelError::Close("Got fail malformed HTLC message when channel was not in an operational state"));
15671567
}

src/ln/channelmanager.rs

Lines changed: 177 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use crypto::mac::{Mac,MacResult};
3939
use crypto::hmac::Hmac;
4040
use crypto::digest::Digest;
4141
use crypto::symmetriccipher::SynchronousStreamCipher;
42+
use crypto::ripemd160::Ripemd160;
4243

4344
use std::{ptr, mem};
4445
use std::collections::HashMap;
@@ -518,13 +519,7 @@ impl ChannelManager {
518519
for tx in local_txn {
519520
self.tx_broadcaster.broadcast_transaction(&tx);
520521
}
521-
//TODO: We need to have a way where outbound HTLC claims can result in us claiming the
522-
//now-on-chain HTLC output for ourselves (and, thereafter, passing the HTLC backwards).
523-
//TODO: We need to handle monitoring of pending offered HTLCs which just hit the chain and
524-
//may be claimed, resulting in us claiming the inbound HTLCs (and back-failing after
525-
//timeouts are hit and our claims confirm).
526-
//TODO: In any case, we need to make sure we remove any pending htlc tracking (via
527-
//fail_backwards or claim_funds) eventually for all HTLCs that were in the channel
522+
528523
}
529524

530525
/// Force closes a channel, immediately broadcasting the latest local commitment transaction to
@@ -1207,11 +1202,16 @@ impl ChannelManager {
12071202

12081203
let mut add_htlc_msgs = Vec::new();
12091204
for HTLCForwardInfo { prev_short_channel_id, prev_htlc_id, forward_info } in pending_forwards.drain(..) {
1210-
let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData {
1205+
let prev_hop_data = HTLCPreviousHopData {
12111206
short_channel_id: prev_short_channel_id,
12121207
htlc_id: prev_htlc_id,
12131208
incoming_packet_shared_secret: forward_info.incoming_shared_secret,
1214-
});
1209+
};
1210+
match channel_state.claimable_htlcs.entry(forward_info.payment_hash) {
1211+
hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(prev_hop_data.clone()),
1212+
hash_map::Entry::Vacant(entry) => { entry.insert(vec![prev_hop_data.clone()]); },
1213+
};
1214+
let htlc_source = HTLCSource::PreviousHopData(prev_hop_data);
12151215
match forward_chan.send_htlc(forward_info.amt_to_forward, forward_info.payment_hash, forward_info.outgoing_cltv_value, htlc_source.clone(), forward_info.onion_packet.unwrap()) {
12161216
Err(_e) => {
12171217
let chan_update = self.get_channel_update(forward_chan).unwrap();
@@ -1731,34 +1731,47 @@ impl ChannelManager {
17311731

17321732
fn internal_update_fulfill_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC) -> Result<(), MsgHandleErrInternal> {
17331733
let mut channel_state = self.channel_state.lock().unwrap();
1734-
let htlc_source = match channel_state.by_id.get_mut(&msg.channel_id) {
1734+
let (htlc_source, payment_hash) = match channel_state.by_id.get_mut(&msg.channel_id) {
17351735
Some(chan) => {
17361736
if chan.get_their_node_id() != *their_node_id {
17371737
//TODO: here and below MsgHandleErrInternal, #153 case
17381738
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
17391739
}
1740-
chan.update_fulfill_htlc(&msg)
1741-
.map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?.clone()
1740+
let (htlc_source, payment_hash) = chan.update_fulfill_htlc(&msg)
1741+
.map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
1742+
(htlc_source.clone(), payment_hash)
17421743
},
17431744
None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
17441745
};
1746+
if let Some(sources) = channel_state.claimable_htlcs.get_mut(&payment_hash) {
1747+
if let HTLCSource::PreviousHopData(previous_hop_data) = htlc_source.clone() {
1748+
sources.retain(|ref source| !(source.short_channel_id == previous_hop_data.short_channel_id && source.htlc_id == previous_hop_data.htlc_id));
1749+
}
1750+
}
17451751
self.claim_funds_internal(channel_state, htlc_source, msg.payment_preimage.clone());
17461752
Ok(())
17471753
}
17481754

17491755
fn internal_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result<Option<msgs::HTLCFailChannelUpdate>, MsgHandleErrInternal> {
1750-
let mut channel_state = self.channel_state.lock().unwrap();
1751-
let htlc_source = match channel_state.by_id.get_mut(&msg.channel_id) {
1756+
let mut channel_state_lock = self.channel_state.lock().unwrap();
1757+
let channel_state = channel_state_lock.borrow_parts();
1758+
let (htlc_source, payment_hash) = match channel_state.by_id.get_mut(&msg.channel_id) {
17521759
Some(chan) => {
17531760
if chan.get_their_node_id() != *their_node_id {
17541761
//TODO: here and below MsgHandleErrInternal, #153 case
17551762
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
17561763
}
1757-
chan.update_fail_htlc(&msg, HTLCFailReason::ErrorPacket { err: msg.reason.clone() })
1758-
.map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))
1764+
let (htlc_source, payment_hash) = chan.update_fail_htlc(&msg, HTLCFailReason::ErrorPacket { err: msg.reason.clone() })
1765+
.map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
1766+
(htlc_source, payment_hash)
17591767
},
17601768
None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
1761-
}?;
1769+
};
1770+
if let Some(sources) = channel_state.claimable_htlcs.get_mut(&payment_hash) {
1771+
if let HTLCSource::PreviousHopData(previous_hop_data) = htlc_source.clone() {
1772+
sources.retain(|ref source| !(source.short_channel_id == previous_hop_data.short_channel_id && source.htlc_id == previous_hop_data.htlc_id));
1773+
}
1774+
}
17621775

17631776
match htlc_source {
17641777
&HTLCSource::OutboundRoute { ref route, ref session_priv, .. } => {
@@ -1821,7 +1834,7 @@ impl ChannelManager {
18211834

18221835
fn internal_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailMalformedHTLC) -> Result<(), MsgHandleErrInternal> {
18231836
let mut channel_state = self.channel_state.lock().unwrap();
1824-
match channel_state.by_id.get_mut(&msg.channel_id) {
1837+
let (htlc_source, payment_hash) = match channel_state.by_id.get_mut(&msg.channel_id) {
18251838
Some(chan) => {
18261839
if chan.get_their_node_id() != *their_node_id {
18271840
//TODO: here and below MsgHandleErrInternal, #153 case
@@ -1830,12 +1843,18 @@ impl ChannelManager {
18301843
if (msg.failure_code & 0x8000) != 0 {
18311844
return Err(MsgHandleErrInternal::send_err_msg_close_chan("Got update_fail_malformed_htlc with BADONION set", msg.channel_id));
18321845
}
1833-
chan.update_fail_malformed_htlc(&msg, HTLCFailReason::Reason { failure_code: msg.failure_code, data: Vec::new() })
1846+
let (htlc_source, payment_hash) = chan.update_fail_malformed_htlc(&msg, HTLCFailReason::Reason { failure_code: msg.failure_code, data: Vec::new() })
18341847
.map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
1835-
Ok(())
1848+
(htlc_source.clone(), payment_hash)
18361849
},
18371850
None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
1851+
};
1852+
if let Some(sources) = channel_state.claimable_htlcs.get_mut(&payment_hash) {
1853+
if let HTLCSource::PreviousHopData(previous_hop_data) = htlc_source {
1854+
sources.retain(|ref source| !(source.short_channel_id == previous_hop_data.short_channel_id && source.htlc_id == previous_hop_data.htlc_id));
1855+
}
18381856
}
1857+
Ok(())
18391858
}
18401859

18411860
fn internal_commitment_signed(&self, their_node_id: &PublicKey, msg: &msgs::CommitmentSigned) -> Result<(msgs::RevokeAndACK, Option<msgs::CommitmentSigned>), MsgHandleErrInternal> {
@@ -2040,6 +2059,7 @@ impl ChainListener for ChannelManager {
20402059
fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) {
20412060
let mut new_events = Vec::new();
20422061
let mut failed_channels = Vec::new();
2062+
let mut hash_to_remove = Vec::new();
20432063
{
20442064
let mut channel_lock = self.channel_state.lock().unwrap();
20452065
let channel_state = channel_lock.borrow_parts();
@@ -2102,10 +2122,47 @@ impl ChainListener for ChannelManager {
21022122
}
21032123
true
21042124
});
2125+
2126+
for tx in txn_matched {
2127+
for (htlc_with_hash, _) in channel_state.claimable_htlcs.iter() {
2128+
let mut ripemd = Ripemd160::new();
2129+
ripemd.input(htlc_with_hash);
2130+
let mut payment_hash160 = [0; 20];
2131+
ripemd.result(&mut payment_hash160);
2132+
2133+
if tx.input.len() > 0 && tx.input[0].witness.len() == 5 && tx.input[0].witness[4].len() == 138 && payment_hash160 == tx.input[0].witness[4][69..89] {
2134+
//TODO: macro?
2135+
let mut payment_preimage = [0; 32];
2136+
for (arr, vec) in payment_preimage.iter_mut().zip(tx.input[0].witness[3].iter()) {
2137+
*arr = *vec;
2138+
}
2139+
hash_to_remove.push((payment_preimage, htlc_with_hash.clone()));
2140+
} else if tx.input.len() > 0 && tx.input[0].witness.len() == 3 && tx.input[0].witness[2].len() == 133 && payment_hash160 == tx.input[0].witness[2][109..129] {
2141+
let mut payment_preimage = [0; 32];
2142+
for (arr, vec) in payment_preimage.iter_mut().zip(tx.input[0].witness[1].iter()) {
2143+
*arr = *vec;
2144+
}
2145+
hash_to_remove.push((payment_preimage, htlc_with_hash.clone()));
2146+
}
2147+
}
2148+
}
21052149
}
21062150
for failure in failed_channels.drain(..) {
21072151
self.finish_force_close_channel(failure);
21082152
}
2153+
2154+
{
2155+
let mut channel_state = Some(self.channel_state.lock().unwrap());
2156+
for (preimage, hash) in hash_to_remove {
2157+
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap());}
2158+
if let Some(mut sources) = channel_state.as_mut().unwrap().claimable_htlcs.remove(&hash) {
2159+
for source in sources.drain(..) {
2160+
self.claim_funds_internal(channel_state.take().unwrap(), HTLCSource::PreviousHopData(source), preimage);
2161+
}
2162+
}
2163+
}
2164+
}
2165+
21092166
let mut pending_events = self.pending_events.lock().unwrap();
21102167
for funding_locked in new_events.drain(..) {
21112168
pending_events.push(funding_locked);
@@ -3817,7 +3874,7 @@ mod tests {
38173874
}
38183875

38193876
/// Tests that the given node has broadcast a claim transaction against the provided revoked
3820-
/// HTLC transaction.
3877+
/// HTLC transaction issued from a revoked commitment tx
38213878
fn test_revoked_htlc_claim_txn_broadcast(node: &Node, revoked_tx: Transaction) {
38223879
let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap();
38233880
assert_eq!(node_txn.len(), 1);
@@ -4205,6 +4262,105 @@ mod tests {
42054262
assert_eq!(nodes[1].node.list_channels().len(), 0);
42064263
}
42074264

4265+
#[test]
4266+
fn test_htlc_on_chain_success() {
4267+
// Test that in case of an unilateral close onchain, we detect the state of output thanks to
4268+
// ChainWatchInterface and pass the preimage backward accordingly. So here we test that ChannelManager is
4269+
// broadcasting the right event to other nodes in payment path.
4270+
// A --------------------> B ----------------------> C (preimage)
4271+
// A's commitment tx C's commitment tx
4272+
// \ \
4273+
// B's preimage tx C's HTLC Success tx
4274+
4275+
let nodes = create_network(3);
4276+
4277+
// Create some initial channels
4278+
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
4279+
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
4280+
4281+
// Rebalance the network a bit by relaying one payment through all the channels...
4282+
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
4283+
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
4284+
4285+
let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000);
4286+
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
4287+
4288+
// Broadcast legit commitment tx from C on B's chain
4289+
// Broadcast HTLC Success transation by C on received output from C's commitment tx on B's chain
4290+
let commitment_tx = nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().last_local_commitment_txn.clone();
4291+
nodes[2].node.claim_funds(payment_preimage);
4292+
{
4293+
let mut added_monitors = nodes[2].chan_monitor.added_monitors.lock().unwrap();
4294+
assert_eq!(added_monitors.len(), 1);
4295+
added_monitors.clear();
4296+
}
4297+
let events = nodes[2].node.get_and_clear_pending_events();
4298+
assert_eq!(events.len(), 1);
4299+
match events[0] {
4300+
Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, .. } } => {
4301+
assert!(update_add_htlcs.is_empty());
4302+
assert!(update_fail_htlcs.is_empty());
4303+
assert!(!update_fulfill_htlcs.is_empty());
4304+
assert!(update_fail_malformed_htlcs.is_empty());
4305+
assert_eq!(nodes[1].node.get_our_node_id(), *node_id);
4306+
},
4307+
_ => panic!("Unexpected event"),
4308+
};
4309+
nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
4310+
let events = nodes[2].node.get_and_clear_pending_events();
4311+
assert_eq!(events.len(), 1);
4312+
match events[0] {
4313+
Event::BroadcastChannelUpdate { msg: msgs::ChannelUpdate { .. } } => {},
4314+
_ => panic!("Unexpected event"),
4315+
}
4316+
let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
4317+
4318+
// Verify that B's ChannelManager is able to extract preimage from HTLC Success tx and pass it backward
4319+
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: node_txn}, 1);
4320+
{
4321+
let mut added_monitors = nodes[1].chan_monitor.added_monitors.lock().unwrap();
4322+
assert_eq!(added_monitors.len(), 1);
4323+
added_monitors.clear();
4324+
}
4325+
let events = nodes[1].node.get_and_clear_pending_events();
4326+
assert_eq!(events.len(), 2);
4327+
match events[0] {
4328+
Event::BroadcastChannelUpdate { msg: msgs::ChannelUpdate { .. } } => {},
4329+
_ => panic!("Unexpected event"),
4330+
}
4331+
match events[1] {
4332+
Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, .. } } => {
4333+
assert!(update_add_htlcs.is_empty());
4334+
assert!(update_fail_htlcs.is_empty());
4335+
assert!(!update_fulfill_htlcs.is_empty());
4336+
assert!(update_fail_malformed_htlcs.is_empty());
4337+
assert_eq!(nodes[0].node.get_our_node_id(), *node_id);
4338+
},
4339+
_ => panic!("Unexpected event"),
4340+
};
4341+
4342+
// Broadcast legit commitment tx from A on B's chain
4343+
// Broadcast preimage tx by B on offered output from A commitment tx on A's chain
4344+
let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
4345+
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
4346+
let events = nodes[1].node.get_and_clear_pending_events();
4347+
assert_eq!(events.len(), 1);
4348+
match events[0] {
4349+
Event::BroadcastChannelUpdate { msg: msgs::ChannelUpdate { .. } } => {},
4350+
_ => panic!("Unexpected event"),
4351+
}
4352+
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
4353+
4354+
// Verify that A's ChannelManager is able to extract preimage from preimage tx and pass it backward
4355+
nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: node_txn }, 1);
4356+
let events = nodes[0].node.get_and_clear_pending_events();
4357+
assert_eq!(events.len(), 1);
4358+
match events[0] {
4359+
Event::BroadcastChannelUpdate { msg: msgs::ChannelUpdate { .. } } => {},
4360+
_ => panic!("Unexpected event"),
4361+
}
4362+
}
4363+
42084364
#[test]
42094365
fn test_htlc_ignore_latest_remote_commitment() {
42104366
// Test that HTLC transactions spending the latest remote commitment transaction are simply

0 commit comments

Comments
 (0)