From: Antoine Riard Date: Tue, 9 Oct 2018 00:33:59 +0000 (+0000) Subject: Implement fail backward in case of detection of revoked tx X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=aabc31cafb329c45f9e1bb070713ae51c89ef8af;p=rust-lightning Implement fail backward in case of detection of revoked tx Refactor block_connected to ease output resolution Add test_commitment_revoked_fail_backward Close #137 --- diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index c1e284a0..ca85f6fc 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -6342,6 +6342,54 @@ mod tests { assert_eq!(node_txn[2].clone().input[0].witness.last().unwrap().len(), 133); } + #[test] + fn test_commitment_revoked_fail_backward() { + // Test that in case of a revoked commitment tx, we detect the resolution of output by justice tx + // and fail backward accordingly. + + let nodes = create_network(3); + + // Create some initial channels + create_announced_chan_between_nodes(&nodes, 0, 1); + let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); + + // Rebalance the network a bit by relaying one payment through all the channels... + send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000); + send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000); + + let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 3000000); + // Get the will-be-revoked local txn from nodes[2] + let revoked_local_txn = nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().last_local_commitment_txn.clone(); + // Revoke the old state + claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], payment_preimage); + + route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 3000000); + + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42}; + nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + { + let mut added_monitors = nodes[1].chan_monitor.added_monitors.lock().unwrap(); + assert_eq!(added_monitors.len(), 1); + added_monitors.clear(); + } + let events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 2); + match events[0] { + MessageSendEvent::BroadcastChannelUpdate { msg: msgs::ChannelUpdate { .. } } => {}, + _ => panic!("Unexpected event"), + } + match events[1] { + 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, .. } } => { + assert!(update_add_htlcs.is_empty()); + assert!(!update_fail_htlcs.is_empty()); + assert!(update_fulfill_htlcs.is_empty()); + assert!(update_fail_malformed_htlcs.is_empty()); + assert_eq!(nodes[0].node.get_our_node_id(), *node_id); + }, + _ => panic!("Unexpected event"), + } + } + #[test] fn test_htlc_ignore_latest_remote_commitment() { // Test that HTLC transactions spending the latest remote commitment transaction are simply diff --git a/src/ln/channelmonitor.rs b/src/ln/channelmonitor.rs index ff58fdd1..f782b68b 100644 --- a/src/ln/channelmonitor.rs +++ b/src/ln/channelmonitor.rs @@ -274,6 +274,7 @@ impl SimpleManyChannelMonitor monitors.insert(key, monitor); Ok(()) } + } impl ManyChannelMonitor for SimpleManyChannelMonitor { @@ -1931,6 +1932,7 @@ impl ChannelMonitor { } htlc_updated } + } const MAX_ALLOC_SIZE: usize = 64*1024;