Skip to content

Commit

Permalink
Introduce test for padding
Browse files Browse the repository at this point in the history
1. Add test to verify blinded message and payment path padding.
  • Loading branch information
shaavan committed Sep 2, 2024
1 parent d3a06e8 commit 23888a2
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
8 changes: 8 additions & 0 deletions lightning/src/blinded_path/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,11 @@ impl Writeable for Padding {
Ok(())
}
}

#[cfg(test)]
/// Checks if all the packets in the blinded path are properly padded, ensuring they are of equal size.
pub fn is_properly_padded(hops: &[BlindedHop]) -> bool {
let first_hop = hops.first().expect("BlindedPath must have at least one hop");
let first_payload_size = first_hop.encrypted_payload.len();
hops.iter().all(|hop| hop.encrypted_payload.len() == first_payload_size)
}
37 changes: 37 additions & 0 deletions lightning/src/ln/blinded_payment_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

use bitcoin::hashes::hex::FromHex;
use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, schnorr};
use crate::blinded_path::utils::is_properly_padded;
use bitcoin::secp256k1::ecdh::SharedSecret;
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
use crate::blinded_path;
Expand Down Expand Up @@ -1348,6 +1349,42 @@ fn custom_tlvs_to_blinded_path() {
);
}

#[test]
fn blinded_payment_path_padding() {
// Make sure that for a blinded payment path, all encrypted payloads are padded to equal lengths.
let chanmon_cfgs = create_chanmon_cfgs(5);
let node_cfgs = create_node_cfgs(5, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &[None, None, None, None, None]);
let mut nodes = create_network(5, &node_cfgs, &node_chanmgrs);
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0);
let chan_upd_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents;
let chan_upd_3_4 = create_announced_chan_between_nodes_with_value(&nodes, 3, 4, 1_000_000, 0).0.contents;

// Get all our nodes onto the same height so payments don't fail for CLTV violations.
connect_blocks(&nodes[0], nodes[4].best_block_info().1 - nodes[0].best_block_info().1);
connect_blocks(&nodes[1], nodes[4].best_block_info().1 - nodes[1].best_block_info().1);
connect_blocks(&nodes[2], nodes[4].best_block_info().1 - nodes[2].best_block_info().1);
assert_eq!(nodes[4].best_block_info().1, nodes[3].best_block_info().1);

let amt_msat = 5000;
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[4], Some(amt_msat), None);

let blinded_path = blinded_payment_path(payment_secret, 1, 1_0000_0000,
nodes.iter().skip(2).map(|n| n.node.get_our_node_id()).collect(), &[&chan_upd_2_3, &chan_upd_3_4],
&chanmon_cfgs[4].keys_manager
);

assert!(is_properly_padded(&blinded_path.blinded_hops()));

let route_params = RouteParameters::from_payment_params_and_value(PaymentParameters::blinded(vec![blinded_path]), amt_msat);

nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]], amt_msat, payment_hash, payment_secret);
claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3], &nodes[4]], payment_preimage);
}

fn secret_from_hex(hex: &str) -> SecretKey {
SecretKey::from_slice(&<Vec<u8>>::from_hex(hex).unwrap()).unwrap()
}
Expand Down
27 changes: 27 additions & 0 deletions lightning/src/onion_message/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use crate::blinded_path::EmptyNodeIdLookUp;
use crate::blinded_path::message::{BlindedMessagePath, MessageForwardNode, MessageContext, OffersContext};
use crate::blinded_path::utils::is_properly_padded;
use crate::events::{Event, EventsProvider};
use crate::ln::features::{ChannelFeatures, InitFeatures};
use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
Expand Down Expand Up @@ -546,6 +547,32 @@ fn too_big_packet_error() {
assert_eq!(err, SendError::TooBigPacket);
}

#[test]
fn blinded_path_padding() {
// Make sure that for a blinded path, all encrypted payloads are padded to equal lengths.
let nodes = create_nodes(4);
let test_msg = TestCustomMessage::Pong;

let secp_ctx = Secp256k1::new();
let intermediate_nodes = [
MessageForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
MessageForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
];
// Update the context to create a larger final receive TLVs, ensuring that
// the hop sizes vary before padding.
let context = MessageContext::Custom(vec![0u8; 42]);
let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[3].node_id, context, &*nodes[3].entropy_source, &secp_ctx).unwrap();

assert!(is_properly_padded(&blinded_path.blinded_hops()));

let destination = Destination::BlindedPath(blinded_path);
let instructions = MessageSendInstructions::WithoutReplyPath { destination };

nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap();
nodes[3].custom_message_handler.expect_message(TestCustomMessage::Pong);
pass_along_path(&nodes);
}

#[test]
fn we_are_intro_node() {
// If we are sending straight to a blinded path and we are the introduction node, we need to
Expand Down

0 comments on commit 23888a2

Please sign in to comment.