Skip to content
91 changes: 91 additions & 0 deletions lightning/src/ln/accountable_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use crate::ln::channelmanager::{
HTLCForwardInfo, PaymentId, PendingAddHTLCInfo, PendingHTLCInfo, RecipientOnionFields, Retry,
};
use crate::ln::functional_test_utils::*;
use crate::ln::msgs::ChannelMessageHandler;
use crate::routing::router::{PaymentParameters, RouteParameters};

fn test_accountable_forwarding_with_override(
override_accountable: Option<bool>, expected_forwarded: bool,
) {
let chanmon_cfgs = create_chanmon_cfgs(3);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);

let _chan_ab = create_announced_chan_between_nodes(&nodes, 0, 1);
let _chan_bc = create_announced_chan_between_nodes(&nodes, 1, 2);

let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]);
let route_params = RouteParameters::from_payment_params_and_value(
PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV),
100_000,
);
let onion_fields = RecipientOnionFields::secret_only(payment_secret);
let payment_id = PaymentId(payment_hash.0);
nodes[0]
.node
.send_payment(payment_hash, onion_fields, payment_id, route_params, Retry::Attempts(0))
.unwrap();
check_added_monitors(&nodes[0], 1);

let updates_ab = get_htlc_update_msgs(&nodes[0], &nodes[1].node.get_our_node_id());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this test does not cover the serialization logic of UpdateAddHTLC with the new accountable field - we pass the struct itself from node to node. Would be cool have a separate test where UpdateAddHTLC is serialized to the wire format, and transmits the accountable signal that way.

assert_eq!(updates_ab.update_add_htlcs.len(), 1);
let mut htlc_ab = updates_ab.update_add_htlcs[0].clone();
assert_eq!(htlc_ab.accountable, Some(false));

// Override accountable value if requested
if let Some(override_value) = override_accountable {
htlc_ab.accountable = Some(override_value);
}

nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &htlc_ab);
do_commitment_signed_dance(&nodes[1], &nodes[0], &updates_ab.commitment_signed, false, false);
expect_and_process_pending_htlcs(&nodes[1], false);
check_added_monitors(&nodes[1], 1);

let updates_bc = get_htlc_update_msgs(&nodes[1], &nodes[2].node.get_our_node_id());
assert_eq!(updates_bc.update_add_htlcs.len(), 1);
let htlc_bc = &updates_bc.update_add_htlcs[0];
assert_eq!(
htlc_bc.accountable,
Some(expected_forwarded),
"B -> C should have accountable = {:?}",
expected_forwarded
);

nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), htlc_bc);
do_commitment_signed_dance(&nodes[2], &nodes[1], &updates_bc.commitment_signed, false, false);

// Accountable signal is not surfaced in PaymentClaimable, so we do our next-best and check
// that the received htlcs that will be processed has the signal set as we expect. We manually
// process pending update adds so that we can access the htlc in forward_htlcs.
nodes[2].node.test_process_pending_update_add_htlcs();
{
let fwds_lock = nodes[2].node.forward_htlcs.lock().unwrap();
let recvs = fwds_lock.get(&0).unwrap();
assert_eq!(recvs.len(), 1);
match recvs[0] {
HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo {
forward_info: PendingHTLCInfo { incoming_accountable, .. },
..
}) => {
assert_eq!(incoming_accountable, expected_forwarded)
},
_ => panic!("Unexpected forward"),
}
}

expect_and_process_pending_htlcs(&nodes[2], false);
check_added_monitors(&nodes[2], 0);
expect_payment_claimable!(nodes[2], payment_hash, payment_secret, 100_000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't give it a shot mysef, could dig into the PendingHTLCInfo of node 2 here to cover the create_recv_pending_htlc_info case ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do - should be possible to grab it out of the recipient's forward_htlcs and check it there.

claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
}

#[test]
fn test_accountable_signal() {
// Tests forwarding of accountable signal for various incoming signal values.
test_accountable_forwarding_with_override(None, false);
test_accountable_forwarding_with_override(Some(true), true);
test_accountable_forwarding_with_override(Some(false), false);
}
1 change: 1 addition & 0 deletions lightning/src/ln/blinded_payment_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1526,6 +1526,7 @@ fn update_add_msg(
skimmed_fee_msat: None,
blinding_point,
hold_htlc: None,
accountable: None,
}
}

Expand Down
Loading