X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fln%2Fchannelmanager.rs;h=8875f9c9eea7cb3e8d61fc140b4cc08c242c2506;hb=8bfe18cf86b343acdc3cdecbd7e472b390605fbe;hp=4f226d76c84c9e1055bb7893edbed60af3463ed3;hpb=3833cc3736c40188852220d8d53d08c2e5c20111;p=rust-lightning diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index 4f226d76c..8875f9c9e 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -3212,6 +3212,109 @@ mod tests { // We can't continue, sadly, because our (1) now has a bogus signature } + #[test] + fn test_multi_flight_update_fee() { + let nodes = create_network(2); + let chan = create_announced_chan_between_nodes(&nodes, 0, 1); + let channel_id = chan.2; + + macro_rules! get_feerate { + ($node: expr) => {{ + let chan_lock = $node.node.channel_state.lock().unwrap(); + let chan = chan_lock.by_id.get(&channel_id).unwrap(); + chan.get_feerate() + }} + } + + // A B + // update_fee/commitment_signed -> + // .- send (1) RAA and (2) commitment_signed + // update_fee (never committed) -> + // (3) update_fee -> + // We have to manually generate the above update_fee, it is allowed by the protocol but we + // don't track which updates correspond to which revoke_and_ack responses so we're in + // AwaitingRAA mode and will not generate the update_fee yet. + // <- (1) RAA delivered + // (3) is generated and send (4) CS -. + // Note that A cannot generate (4) prior to (1) being delivered as it otherwise doesn't + // know the per_commitment_point to use for it. + // <- (2) commitment_signed delivered + // revoke_and_ack -> + // B should send no response here + // (4) commitment_signed delivered -> + // <- RAA/commitment_signed delivered + // revoke_and_ack -> + + // First nodes[0] generates an update_fee + let initial_feerate = get_feerate!(nodes[0]); + nodes[0].node.update_fee(channel_id, initial_feerate + 20).unwrap(); + check_added_monitors!(nodes[0], 1); + + let events_0 = nodes[0].node.get_and_clear_pending_events(); + assert_eq!(events_0.len(), 1); + let (update_msg_1, commitment_signed_1) = match events_0[0] { // (1) + Event::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, .. } => { + (update_fee.as_ref().unwrap(), commitment_signed) + }, + _ => panic!("Unexpected event"), + }; + + // Deliver first update_fee/commitment_signed pair, generating (1) and (2): + nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), update_msg_1).unwrap(); + let (bs_revoke_msg, bs_commitment_signed) = nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), commitment_signed_1).unwrap(); + check_added_monitors!(nodes[1], 1); + + // nodes[0] is awaiting a revoke from nodes[1] before it will create a new commitment + // transaction: + nodes[0].node.update_fee(channel_id, initial_feerate + 40).unwrap(); + assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); + + // Create the (3) update_fee message that nodes[0] will generate before it does... + let mut update_msg_2 = msgs::UpdateFee { + channel_id: update_msg_1.channel_id.clone(), + feerate_per_kw: (initial_feerate + 30) as u32, + }; + + nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), &update_msg_2).unwrap(); + + update_msg_2.feerate_per_kw = (initial_feerate + 40) as u32; + // Deliver (3) + nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), &update_msg_2).unwrap(); + + // Deliver (1), generating (3) and (4) + let as_second_update = nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_revoke_msg).unwrap(); + check_added_monitors!(nodes[0], 1); + assert!(as_second_update.as_ref().unwrap().update_add_htlcs.is_empty()); + assert!(as_second_update.as_ref().unwrap().update_fulfill_htlcs.is_empty()); + assert!(as_second_update.as_ref().unwrap().update_fail_htlcs.is_empty()); + assert!(as_second_update.as_ref().unwrap().update_fail_malformed_htlcs.is_empty()); + // Check that the update_fee newly generated matches what we delivered: + assert_eq!(as_second_update.as_ref().unwrap().update_fee.as_ref().unwrap().channel_id, update_msg_2.channel_id); + assert_eq!(as_second_update.as_ref().unwrap().update_fee.as_ref().unwrap().feerate_per_kw, update_msg_2.feerate_per_kw); + + // Deliver (2) commitment_signed + let (as_revoke_msg, as_commitment_signed) = nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), bs_commitment_signed.as_ref().unwrap()).unwrap(); + check_added_monitors!(nodes[0], 1); + assert!(as_commitment_signed.is_none()); + + assert!(nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_revoke_msg).unwrap().is_none()); + check_added_monitors!(nodes[1], 1); + + // Delever (4) + let (bs_second_revoke, bs_second_commitment) = nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_second_update.unwrap().commitment_signed).unwrap(); + check_added_monitors!(nodes[1], 1); + + assert!(nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_revoke).unwrap().is_none()); + check_added_monitors!(nodes[0], 1); + + let (as_second_revoke, as_second_commitment) = nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_second_commitment.unwrap()).unwrap(); + assert!(as_second_commitment.is_none()); + check_added_monitors!(nodes[0], 1); + + assert!(nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_second_revoke).unwrap().is_none()); + check_added_monitors!(nodes[1], 1); + } + #[test] fn test_update_fee_vanilla() { let nodes = create_network(2); @@ -3376,6 +3479,21 @@ mod tests { }} } + // A B + // (1) update_fee/commitment_signed -> + // <- (2) revoke_and_ack + // .- send (3) commitment_signed + // (4) update_fee/commitment_signed -> + // .- send (5) revoke_and_ack (no CS as we're awaiting a revoke) + // <- (3) commitment_signed delivered + // send (6) revoke_and_ack -. + // <- (5) deliver revoke_and_ack + // (6) deliver revoke_and_ack -> + // .- send (7) commitment_signed in response to (4) + // <- (7) deliver commitment_signed + // revoke_and_ack -> + + // Create and deliver (1)... let feerate = get_feerate!(nodes[0]); nodes[0].node.update_fee(channel_id, feerate+20).unwrap(); @@ -3389,15 +3507,18 @@ mod tests { }; nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), update_msg.unwrap()).unwrap(); + // Generate (2) and (3): let (revoke_msg, commitment_signed) = nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), commitment_signed).unwrap(); let commitment_signed_0 = commitment_signed.unwrap(); check_added_monitors!(nodes[0], 1); check_added_monitors!(nodes[1], 1); + // Deliver (2): let resp_option = nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &revoke_msg).unwrap(); assert!(resp_option.is_none()); check_added_monitors!(nodes[0], 1); + // Create and deliver (4)... nodes[0].node.update_fee(channel_id, feerate+30).unwrap(); let events_0 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_0.len(), 1); @@ -3410,21 +3531,27 @@ mod tests { nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), update_msg.unwrap()).unwrap(); let (revoke_msg, commitment_signed) = nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), commitment_signed).unwrap(); + // ... creating (5) assert!(commitment_signed.is_none()); check_added_monitors!(nodes[0], 1); check_added_monitors!(nodes[1], 1); + + // Handle (3), creating (6): let (revoke_msg_0, commitment_signed) = nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &commitment_signed_0).unwrap(); assert!(commitment_signed.is_none()); check_added_monitors!(nodes[0], 1); + // Deliver (5): let resp_option = nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &revoke_msg).unwrap(); assert!(resp_option.is_none()); check_added_monitors!(nodes[0], 1); + // Deliver (6), creating (7): let resp_option = nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &revoke_msg_0).unwrap(); let commitment_signed = resp_option.unwrap().commitment_signed; check_added_monitors!(nodes[1], 1); + // Deliver (7) let (revoke_msg, commitment_signed) = nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &commitment_signed).unwrap(); assert!(commitment_signed.is_none()); check_added_monitors!(nodes[0], 1);