|
10 | 10 | //! Tests which test upgrading from previous versions of LDK or downgrading to previous versions of |
11 | 11 | //! LDK. |
12 | 12 |
|
| 13 | +use lightning_0_2::commitment_signed_dance as commitment_signed_dance_0_2; |
| 14 | +use lightning_0_2::events::Event as Event_0_2; |
| 15 | +use lightning_0_2::get_monitor as get_monitor_0_2; |
| 16 | +use lightning_0_2::ln::channelmanager::PaymentId as PaymentId_0_2; |
| 17 | +use lightning_0_2::ln::channelmanager::RecipientOnionFields as RecipientOnionFields_0_2; |
| 18 | +use lightning_0_2::ln::functional_test_utils as lightning_0_2_utils; |
| 19 | +use lightning_0_2::ln::msgs::ChannelMessageHandler as _; |
| 20 | +use lightning_0_2::routing::router as router_0_2; |
| 21 | +use lightning_0_2::util::ser::Writeable as _; |
| 22 | + |
13 | 23 | use lightning_0_1::commitment_signed_dance as commitment_signed_dance_0_1; |
14 | 24 | use lightning_0_1::events::ClosureReason as ClosureReason_0_1; |
15 | 25 | use lightning_0_1::expect_pending_htlcs_forwardable_ignore as expect_pending_htlcs_forwardable_ignore_0_1; |
@@ -498,3 +508,200 @@ fn test_0_1_htlc_forward_after_splice() { |
498 | 508 | do_test_0_1_htlc_forward_after_splice(true); |
499 | 509 | do_test_0_1_htlc_forward_after_splice(false); |
500 | 510 | } |
| 511 | + |
| 512 | +#[derive(PartialEq, Eq)] |
| 513 | +enum MidHtlcForwardCase { |
| 514 | + // Restart the upgraded node after locking an HTLC forward into the inbound edge, but before |
| 515 | + // decoding the onion. |
| 516 | + PreOnionDecode, |
| 517 | + // Restart the upgraded node after locking an HTLC forward into the inbound edge + decoding the |
| 518 | + // onion. |
| 519 | + PostOnionDecode, |
| 520 | + // Restart the upgraded node after the HTLC has been decoded and placed in the pending intercepted |
| 521 | + // HTLCs map. |
| 522 | + Intercept, |
| 523 | +} |
| 524 | + |
| 525 | +#[test] |
| 526 | +fn upgrade_pre_htlc_forward_onion_decode() { |
| 527 | + do_upgrade_mid_htlc_forward(MidHtlcForwardCase::PreOnionDecode); |
| 528 | +} |
| 529 | +#[test] |
| 530 | +fn upgrade_mid_htlc_forward() { |
| 531 | + do_upgrade_mid_htlc_forward(MidHtlcForwardCase::PostOnionDecode); |
| 532 | +} |
| 533 | +#[test] |
| 534 | +fn upgrade_mid_htlc_intercept_forward() { |
| 535 | + do_upgrade_mid_htlc_forward(MidHtlcForwardCase::Intercept); |
| 536 | +} |
| 537 | +fn do_upgrade_mid_htlc_forward(test: MidHtlcForwardCase) { |
| 538 | + // In 0.3, we started reconstructing the `ChannelManager`'s HTLC forwards maps from the HTLCs |
| 539 | + // contained in `Channel`s, as part of removing the requirement to regularly persist the |
| 540 | + // `ChannelManager`. However, HTLC forwards can only be reconstructed this way if they were |
| 541 | + // received on 0.3 or higher. Test that HTLC forwards that were serialized on <=0.2 will still |
| 542 | + // succeed when read on 0.3+. |
| 543 | + let (node_a_ser, node_b_ser, node_c_ser, mon_a_1_ser, mon_b_1_ser, mon_b_2_ser, mon_c_1_ser); |
| 544 | + let (node_a_id, node_b_id, node_c_id); |
| 545 | + let (payment_secret_bytes, payment_hash_bytes, payment_preimage_bytes); |
| 546 | + let (node_a_blocks, node_b_blocks, node_c_blocks); |
| 547 | + let chan_id_bytes_b_c; |
| 548 | + |
| 549 | + { |
| 550 | + let chanmon_cfgs = lightning_0_2_utils::create_chanmon_cfgs(3); |
| 551 | + let node_cfgs = lightning_0_2_utils::create_node_cfgs(3, &chanmon_cfgs); |
| 552 | + |
| 553 | + let mut intercept_cfg = lightning_0_2_utils::test_default_channel_config(); |
| 554 | + intercept_cfg.accept_intercept_htlcs = true; |
| 555 | + let cfgs = &[None, Some(intercept_cfg), None]; |
| 556 | + let node_chanmgrs = lightning_0_2_utils::create_node_chanmgrs(3, &node_cfgs, cfgs); |
| 557 | + let nodes = lightning_0_2_utils::create_network(3, &node_cfgs, &node_chanmgrs); |
| 558 | + |
| 559 | + node_a_id = nodes[0].node.get_our_node_id(); |
| 560 | + node_b_id = nodes[1].node.get_our_node_id(); |
| 561 | + node_c_id = nodes[2].node.get_our_node_id(); |
| 562 | + let chan_id_a = lightning_0_2_utils::create_announced_chan_between_nodes_with_value( |
| 563 | + &nodes, 0, 1, 10_000_000, 0, |
| 564 | + ) |
| 565 | + .2; |
| 566 | + |
| 567 | + let chan_id_b = lightning_0_2_utils::create_announced_chan_between_nodes_with_value( |
| 568 | + &nodes, 1, 2, 50_000, 0, |
| 569 | + ) |
| 570 | + .2; |
| 571 | + chan_id_bytes_b_c = chan_id_b.0; |
| 572 | + |
| 573 | + // Ensure all nodes are at the same initial height. |
| 574 | + let node_max_height = nodes.iter().map(|node| node.best_block_info().1).max().unwrap(); |
| 575 | + for node in &nodes { |
| 576 | + let blocks_to_mine = node_max_height - node.best_block_info().1; |
| 577 | + if blocks_to_mine > 0 { |
| 578 | + lightning_0_2_utils::connect_blocks(node, blocks_to_mine); |
| 579 | + } |
| 580 | + } |
| 581 | + |
| 582 | + // Initiate an HTLC to be sent over node_a -> node_b -> node_c |
| 583 | + let (preimage, hash, secret) = |
| 584 | + lightning_0_2_utils::get_payment_preimage_hash(&nodes[2], Some(1_000_000), None); |
| 585 | + payment_preimage_bytes = preimage.0; |
| 586 | + payment_hash_bytes = hash.0; |
| 587 | + payment_secret_bytes = secret.0; |
| 588 | + |
| 589 | + let pay_params = router_0_2::PaymentParameters::from_node_id( |
| 590 | + node_c_id, |
| 591 | + lightning_0_2_utils::TEST_FINAL_CLTV, |
| 592 | + ) |
| 593 | + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) |
| 594 | + .unwrap(); |
| 595 | + |
| 596 | + let route_params = |
| 597 | + router_0_2::RouteParameters::from_payment_params_and_value(pay_params, 1_000_000); |
| 598 | + let mut route = lightning_0_2_utils::get_route(&nodes[0], &route_params).unwrap(); |
| 599 | + |
| 600 | + if test == MidHtlcForwardCase::Intercept { |
| 601 | + route.paths[0].hops[1].short_channel_id = nodes[1].node.get_intercept_scid(); |
| 602 | + } |
| 603 | + |
| 604 | + let onion = RecipientOnionFields_0_2::secret_only(secret); |
| 605 | + let id = PaymentId_0_2(hash.0); |
| 606 | + nodes[0].node.send_payment_with_route(route, hash, onion, id).unwrap(); |
| 607 | + |
| 608 | + lightning_0_2_utils::check_added_monitors(&nodes[0], 1); |
| 609 | + let send_event = lightning_0_2_utils::SendEvent::from_node(&nodes[0]); |
| 610 | + |
| 611 | + // Lock in the HTLC on the inbound edge of node_b without initiating the outbound edge. |
| 612 | + nodes[1].node.handle_update_add_htlc(node_a_id, &send_event.msgs[0]); |
| 613 | + commitment_signed_dance_0_2!(nodes[1], nodes[0], send_event.commitment_msg, false); |
| 614 | + if test != MidHtlcForwardCase::PreOnionDecode { |
| 615 | + nodes[1].node.test_process_pending_update_add_htlcs(); |
| 616 | + } |
| 617 | + let events = nodes[1].node.get_and_clear_pending_events(); |
| 618 | + if test == MidHtlcForwardCase::Intercept { |
| 619 | + assert_eq!(events.len(), 1); |
| 620 | + assert!(matches!(events[0], Event_0_2::HTLCIntercepted { .. })); |
| 621 | + } else { |
| 622 | + assert!(events.is_empty()); |
| 623 | + } |
| 624 | + |
| 625 | + node_a_ser = nodes[0].node.encode(); |
| 626 | + node_b_ser = nodes[1].node.encode(); |
| 627 | + node_c_ser = nodes[2].node.encode(); |
| 628 | + mon_a_1_ser = get_monitor_0_2!(nodes[0], chan_id_a).encode(); |
| 629 | + mon_b_1_ser = get_monitor_0_2!(nodes[1], chan_id_a).encode(); |
| 630 | + mon_b_2_ser = get_monitor_0_2!(nodes[1], chan_id_b).encode(); |
| 631 | + mon_c_1_ser = get_monitor_0_2!(nodes[2], chan_id_b).encode(); |
| 632 | + |
| 633 | + node_a_blocks = Arc::clone(&nodes[0].blocks); |
| 634 | + node_b_blocks = Arc::clone(&nodes[1].blocks); |
| 635 | + node_c_blocks = Arc::clone(&nodes[2].blocks); |
| 636 | + } |
| 637 | + |
| 638 | + // Create a dummy node to reload over with the 0.2 state |
| 639 | + let mut chanmon_cfgs = create_chanmon_cfgs(3); |
| 640 | + |
| 641 | + // Our TestChannelSigner will fail as we're jumping ahead, so disable its state-based checks |
| 642 | + chanmon_cfgs[0].keys_manager.disable_all_state_policy_checks = true; |
| 643 | + chanmon_cfgs[1].keys_manager.disable_all_state_policy_checks = true; |
| 644 | + chanmon_cfgs[2].keys_manager.disable_all_state_policy_checks = true; |
| 645 | + |
| 646 | + chanmon_cfgs[0].tx_broadcaster.blocks = node_a_blocks; |
| 647 | + chanmon_cfgs[1].tx_broadcaster.blocks = node_b_blocks; |
| 648 | + chanmon_cfgs[2].tx_broadcaster.blocks = node_c_blocks; |
| 649 | + |
| 650 | + let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); |
| 651 | + let (persister_a, persister_b, persister_c, chain_mon_a, chain_mon_b, chain_mon_c); |
| 652 | + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); |
| 653 | + let (node_a, node_b, node_c); |
| 654 | + let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); |
| 655 | + |
| 656 | + let config = test_default_channel_config(); |
| 657 | + let a_mons = &[&mon_a_1_ser[..]]; |
| 658 | + reload_node!(nodes[0], config.clone(), &node_a_ser, a_mons, persister_a, chain_mon_a, node_a); |
| 659 | + let b_mons = &[&mon_b_1_ser[..], &mon_b_2_ser[..]]; |
| 660 | + reload_node!(nodes[1], config.clone(), &node_b_ser, b_mons, persister_b, chain_mon_b, node_b); |
| 661 | + let c_mons = &[&mon_c_1_ser[..]]; |
| 662 | + reload_node!(nodes[2], config, &node_c_ser, c_mons, persister_c, chain_mon_c, node_c); |
| 663 | + |
| 664 | + reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1])); |
| 665 | + let mut reconnect_b_c_args = ReconnectArgs::new(&nodes[1], &nodes[2]); |
| 666 | + reconnect_b_c_args.send_channel_ready = (true, true); |
| 667 | + reconnect_b_c_args.send_announcement_sigs = (true, true); |
| 668 | + reconnect_nodes(reconnect_b_c_args); |
| 669 | + |
| 670 | + // Now release the HTLC from node_b to node_c, to be claimed back to node_a |
| 671 | + nodes[1].node.process_pending_htlc_forwards(); |
| 672 | + |
| 673 | + if test == MidHtlcForwardCase::Intercept { |
| 674 | + let events = nodes[1].node.get_and_clear_pending_events(); |
| 675 | + assert_eq!(events.len(), 1); |
| 676 | + let (intercept_id, expected_outbound_amt_msat) = match events[0] { |
| 677 | + Event::HTLCIntercepted { intercept_id, expected_outbound_amount_msat, .. } => { |
| 678 | + (intercept_id, expected_outbound_amount_msat) |
| 679 | + }, |
| 680 | + _ => panic!(), |
| 681 | + }; |
| 682 | + nodes[1] |
| 683 | + .node |
| 684 | + .forward_intercepted_htlc( |
| 685 | + intercept_id, |
| 686 | + &ChannelId(chan_id_bytes_b_c), |
| 687 | + nodes[2].node.get_our_node_id(), |
| 688 | + expected_outbound_amt_msat, |
| 689 | + ) |
| 690 | + .unwrap(); |
| 691 | + nodes[1].node.process_pending_htlc_forwards(); |
| 692 | + } |
| 693 | + |
| 694 | + let pay_secret = PaymentSecret(payment_secret_bytes); |
| 695 | + let pay_hash = PaymentHash(payment_hash_bytes); |
| 696 | + let pay_preimage = PaymentPreimage(payment_preimage_bytes); |
| 697 | + |
| 698 | + check_added_monitors(&nodes[1], 1); |
| 699 | + let forward_event = SendEvent::from_node(&nodes[1]); |
| 700 | + nodes[2].node.handle_update_add_htlc(node_b_id, &forward_event.msgs[0]); |
| 701 | + let commitment = &forward_event.commitment_msg; |
| 702 | + do_commitment_signed_dance(&nodes[2], &nodes[1], commitment, false, false); |
| 703 | + |
| 704 | + expect_and_process_pending_htlcs(&nodes[2], false); |
| 705 | + expect_payment_claimable!(nodes[2], pay_hash, pay_secret, 1_000_000); |
| 706 | + claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], pay_preimage); |
| 707 | +} |
0 commit comments