Skip to content

Commit 3a10bdb

Browse files
author
Antoine Riard
committed
Implement fail backward in case of detection of revoked tx
Refactor block_connected to ease output resolution Add test_commitment_revoked_fail_backward Close lightningdevkit#137
1 parent 1993d67 commit 3a10bdb

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

src/ln/channelmanager.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6286,6 +6286,54 @@ mod tests {
62866286
assert_eq!(node_txn[2].clone().input[0].witness.last().unwrap().len(), 133);
62876287
}
62886288

6289+
#[test]
6290+
fn test_commitment_revoked_fail_backward() {
6291+
// Test that in case of a revoked commitment tx, we detect the resolution of output by justice tx
6292+
// and fail backward accordingly.
6293+
6294+
let nodes = create_network(3);
6295+
6296+
// Create some initial channels
6297+
create_announced_chan_between_nodes(&nodes, 0, 1);
6298+
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
6299+
6300+
// Rebalance the network a bit by relaying one payment through all the channels...
6301+
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
6302+
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
6303+
6304+
let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 3000000);
6305+
// Get the will-be-revoked local txn from nodes[2]
6306+
let revoked_local_txn = nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().last_local_commitment_txn.clone();
6307+
// Revoke the old state
6308+
claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], payment_preimage);
6309+
6310+
route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 3000000);
6311+
6312+
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
6313+
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
6314+
{
6315+
let mut added_monitors = nodes[1].chan_monitor.added_monitors.lock().unwrap();
6316+
assert_eq!(added_monitors.len(), 1);
6317+
added_monitors.clear();
6318+
}
6319+
let events = nodes[1].node.get_and_clear_pending_msg_events();
6320+
assert_eq!(events.len(), 2);
6321+
match events[0] {
6322+
MessageSendEvent::BroadcastChannelUpdate { msg: msgs::ChannelUpdate { .. } } => {},
6323+
_ => panic!("Unexpected event"),
6324+
}
6325+
match events[1] {
6326+
MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, .. } } => {
6327+
assert!(update_add_htlcs.is_empty());
6328+
assert!(!update_fail_htlcs.is_empty());
6329+
assert!(update_fulfill_htlcs.is_empty());
6330+
assert!(update_fail_malformed_htlcs.is_empty());
6331+
assert_eq!(nodes[0].node.get_our_node_id(), *node_id);
6332+
},
6333+
_ => panic!("Unexpected event"),
6334+
}
6335+
}
6336+
62896337
#[test]
62906338
fn test_htlc_ignore_latest_remote_commitment() {
62916339
// Test that HTLC transactions spending the latest remote commitment transaction are simply

src/ln/channelmonitor.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static> SimpleManyChannelMonitor<Key>
239239
monitors.insert(key, monitor);
240240
Ok(())
241241
}
242+
242243
}
243244

244245
impl ManyChannelMonitor for SimpleManyChannelMonitor<OutPoint> {
@@ -1664,6 +1665,16 @@ impl ChannelMonitor {
16641665
pub(crate) fn is_resolving_output(&self, tx: &Transaction) -> Option<Vec<(Option<[u8;32]>, [u8;32])>> {
16651666
let mut hash_to_remove = Vec::new();
16661667
if tx.input.len() > 0 {
1668+
let commitment_number = 0xffffffffffff - ((((tx.input[0].sequence as u64 & 0xffffff) << 3*8) | (tx.lock_time as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor);
1669+
if commitment_number >= self.get_min_seen_secret() {
1670+
if let Some(ref local_commitment_tx) = self.current_local_signed_commitment_tx {
1671+
for &(ref htlc_output, _, _) in &local_commitment_tx.htlc_outputs {
1672+
if htlc_output.offered {
1673+
hash_to_remove.push((None, htlc_output.payment_hash.clone()));
1674+
}
1675+
}
1676+
}
1677+
}
16671678
for input in &tx.input {
16681679
let mut payment_data = (None, None);
16691680
if let Some(ref current_local_signed_commitment_tx) = self.current_local_signed_commitment_tx {
@@ -1714,6 +1725,7 @@ impl ChannelMonitor {
17141725
}
17151726
None
17161727
}
1728+
17171729
}
17181730

17191731
const MAX_ALLOC_SIZE: usize = 64*1024;

0 commit comments

Comments
 (0)