Skip to content

Commit 0336495

Browse files
committed
Attributable failures
1 parent c35192b commit 0336495

File tree

3 files changed

+420
-69
lines changed

3 files changed

+420
-69
lines changed

lightning/src/ln/functional_tests.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::chain::chaininterface::LowerBoundedFeeEstimator;
1717
use crate::chain::channelmonitor;
1818
use crate::chain::channelmonitor::{Balance, ChannelMonitorUpdateStep, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE};
1919
use crate::chain::transaction::OutPoint;
20+
use crate::ln::onion_utils::ATTRIBUTION_DATA_LEN;
2021
use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, OutputSpender, SignerProvider};
2122
use crate::events::bump_transaction::WalletSource;
2223
use crate::events::{Event, FundingInfo, PathFailure, PaymentPurpose, ClosureReason, HTLCDestination, PaymentFailureReason};
@@ -7060,7 +7061,7 @@ pub fn test_update_fulfill_htlc_bolt2_update_fail_htlc_before_commitment() {
70607061
channel_id: chan.2,
70617062
htlc_id: 0,
70627063
reason: Vec::new(),
7063-
attribution_data: None,
7064+
attribution_data: Some([0; ATTRIBUTION_DATA_LEN])
70647065
};
70657066

70667067
nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_msg);

lightning/src/ln/onion_route_tests.rs

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ use crate::ln::functional_test_utils::*;
5050
use crate::ln::onion_utils::{construct_trampoline_onion_keys, construct_trampoline_onion_packet};
5151

5252
use super::msgs::OnionErrorPacket;
53+
use super::onion_utils::{add_hmacs, ATTRIBUTION_DATA_LEN};
5354

5455
fn run_onion_failure_test<F1,F2>(_name: &str, test_case: u8, nodes: &Vec<Node>, route: &Route, payment_hash: &PaymentHash, payment_secret: &PaymentSecret, callback_msg: F1, callback_node: F2, expected_retryable: bool, expected_error_code: Option<u16>, expected_channel_update: Option<NetworkUpdate>, expected_short_channel_id: Option<u64>, expected_htlc_destination: Option<HTLCDestination>)
5556
where F1: for <'a> FnMut(&'a mut msgs::UpdateAddHTLC),
@@ -411,17 +412,19 @@ fn test_onion_failure() {
411412
// and tamper returning error message
412413
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
413414
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
414-
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), NODE|2, &[0;0]);
415+
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), NODE|2, &[0;0], 0);
415416
msg.reason = failure.data;
417+
msg.attribution_data = failure.attribution_data;
416418
}, ||{}, true, Some(NODE|2), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[0].pubkey, is_permanent: false}), Some(route.paths[0].hops[0].short_channel_id), Some(next_hop_failure.clone()));
417419

418420
// final node failure
419421
run_onion_failure_test_with_fail_intercept("temporary_node_failure", 200, &nodes, &route, &payment_hash, &payment_secret, |_msg| {}, |msg| {
420422
// and tamper returning error message
421423
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
422424
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
423-
let failure = onion_utils::build_failure_packet(onion_keys[1].shared_secret.as_ref(), NODE|2, &[0;0]);
425+
let failure = onion_utils::build_failure_packet(onion_keys[1].shared_secret.as_ref(), NODE|2, &[0;0], 0);
424426
msg.reason = failure.data;
427+
msg.attribution_data = failure.attribution_data;
425428
}, ||{
426429
nodes[2].node.fail_htlc_backwards(&payment_hash);
427430
}, true, Some(NODE|2), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[1].pubkey, is_permanent: false}), Some(route.paths[0].hops[1].short_channel_id), None);
@@ -433,16 +436,18 @@ fn test_onion_failure() {
433436
}, |msg| {
434437
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
435438
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
436-
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), PERM|NODE|2, &[0;0]);
439+
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), PERM|NODE|2, &[0;0], 0);
437440
msg.reason = failure.data;
441+
msg.attribution_data = failure.attribution_data;
438442
}, ||{}, true, Some(PERM|NODE|2), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[0].pubkey, is_permanent: true}), Some(route.paths[0].hops[0].short_channel_id), Some(next_hop_failure.clone()));
439443

440444
// final node failure
441445
run_onion_failure_test_with_fail_intercept("permanent_node_failure", 200, &nodes, &route, &payment_hash, &payment_secret, |_msg| {}, |msg| {
442446
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
443447
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
444-
let failure = onion_utils::build_failure_packet(onion_keys[1].shared_secret.as_ref(), PERM|NODE|2, &[0;0]);
448+
let failure = onion_utils::build_failure_packet(onion_keys[1].shared_secret.as_ref(), PERM|NODE|2, &[0;0], 0);
445449
msg.reason = failure.data;
450+
msg.attribution_data = failure.attribution_data;
446451
}, ||{
447452
nodes[2].node.fail_htlc_backwards(&payment_hash);
448453
}, false, Some(PERM|NODE|2), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[1].pubkey, is_permanent: true}), Some(route.paths[0].hops[1].short_channel_id), None);
@@ -454,8 +459,9 @@ fn test_onion_failure() {
454459
}, |msg| {
455460
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
456461
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
457-
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), PERM|NODE|3, &[0;0]);
462+
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), PERM|NODE|3, &[0;0], 0);
458463
msg.reason = failure.data;
464+
msg.attribution_data = failure.attribution_data;
459465
}, ||{
460466
nodes[2].node.fail_htlc_backwards(&payment_hash);
461467
}, true, Some(PERM|NODE|3), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[0].pubkey, is_permanent: true}), Some(route.paths[0].hops[0].short_channel_id), Some(next_hop_failure.clone()));
@@ -464,8 +470,9 @@ fn test_onion_failure() {
464470
run_onion_failure_test_with_fail_intercept("required_node_feature_missing", 200, &nodes, &route, &payment_hash, &payment_secret, |_msg| {}, |msg| {
465471
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
466472
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
467-
let failure = onion_utils::build_failure_packet(onion_keys[1].shared_secret.as_ref(), PERM|NODE|3, &[0;0]);
473+
let failure = onion_utils::build_failure_packet(onion_keys[1].shared_secret.as_ref(), PERM|NODE|3, &[0;0], 0);
468474
msg.reason = failure.data;
475+
msg.attribution_data = failure.attribution_data;
469476
}, ||{
470477
nodes[2].node.fail_htlc_backwards(&payment_hash);
471478
}, false, Some(PERM|NODE|3), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[1].pubkey, is_permanent: true}), Some(route.paths[0].hops[1].short_channel_id), None);
@@ -495,8 +502,9 @@ fn test_onion_failure() {
495502
}, |msg| {
496503
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
497504
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
498-
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), UPDATE|7, &err_data);
505+
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), UPDATE|7, &err_data, 0);
499506
msg.reason = failure.data;
507+
msg.attribution_data = failure.attribution_data;
500508
}, ||{}, true, Some(UPDATE|7),
501509
Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }),
502510
Some(short_channel_id), Some(next_hop_failure.clone()));
@@ -508,8 +516,9 @@ fn test_onion_failure() {
508516
}, |msg| {
509517
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
510518
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
511-
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), UPDATE|7, &err_data_without_type);
519+
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), UPDATE|7, &err_data_without_type, 0);
512520
msg.reason = failure.data;
521+
msg.attribution_data = failure.attribution_data;
513522
}, ||{}, true, Some(UPDATE|7),
514523
Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }),
515524
Some(short_channel_id), Some(next_hop_failure.clone()));
@@ -520,8 +529,9 @@ fn test_onion_failure() {
520529
}, |msg| {
521530
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
522531
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
523-
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), PERM|8, &[0;0]);
532+
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), PERM|8, &[0;0], 0);
524533
msg.reason = failure.data;
534+
msg.attribution_data = failure.attribution_data;
525535
// short_channel_id from the processing node
526536
}, ||{}, true, Some(PERM|8), Some(NetworkUpdate::ChannelFailure{short_channel_id, is_permanent: true}), Some(short_channel_id), Some(next_hop_failure.clone()));
527537

@@ -531,8 +541,9 @@ fn test_onion_failure() {
531541
}, |msg| {
532542
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
533543
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
534-
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), PERM|9, &[0;0]);
544+
let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), PERM|9, &[0;0], 0);
535545
msg.reason = failure.data;
546+
msg.attribution_data = failure.attribution_data;
536547
// short_channel_id from the processing node
537548
}, ||{}, true, Some(PERM|9), Some(NetworkUpdate::ChannelFailure{short_channel_id, is_permanent: true}), Some(short_channel_id), Some(next_hop_failure.clone()));
538549

@@ -664,8 +675,9 @@ fn test_onion_failure() {
664675
// Tamper returning error message
665676
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
666677
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
667-
let failure = onion_utils::build_failure_packet(onion_keys[1].shared_secret.as_ref(), 23, &[0;0]);
678+
let failure = onion_utils::build_failure_packet(onion_keys[1].shared_secret.as_ref(), 23, &[0;0], 0);
668679
msg.reason = failure.data;
680+
msg.attribution_data = failure.attribution_data;
669681
}, ||{
670682
nodes[2].node.fail_htlc_backwards(&payment_hash);
671683
}, true, Some(23), None, None, None);
@@ -685,11 +697,13 @@ fn test_onion_failure() {
685697
decoded_err_packet.hmac = Hmac::from_engine(hmac).to_byte_array();
686698
let mut onion_error = OnionErrorPacket {
687699
data: decoded_err_packet.encode(),
688-
attribution_data: None,
700+
attribution_data: Some([0; ATTRIBUTION_DATA_LEN]),
689701
};
702+
add_hmacs(&onion_keys[1].shared_secret.as_ref(), &onion_error.data, onion_error.attribution_data.as_mut().unwrap());
690703
onion_utils::test_crypt_failure_packet(
691704
&onion_keys[1].shared_secret.as_ref(), &mut onion_error);
692705
msg.reason = onion_error.data;
706+
msg.attribution_data = onion_error.attribution_data;
693707
}, || nodes[2].node.fail_htlc_backwards(&payment_hash), false, None,
694708
Some(NetworkUpdate::NodeFailure { node_id: route.paths[0].hops[1].pubkey, is_permanent: true }),
695709
Some(channels[1].0.contents.short_channel_id), None);
@@ -713,11 +727,13 @@ fn test_onion_failure() {
713727
decoded_err_packet.hmac = Hmac::from_engine(hmac).to_byte_array();
714728
let mut onion_error = OnionErrorPacket{
715729
data: decoded_err_packet.encode(),
716-
attribution_data: None,
730+
attribution_data: Some([0; ATTRIBUTION_DATA_LEN]),
717731
};
732+
add_hmacs(&onion_keys[0].shared_secret.as_ref(), &onion_error.data, onion_error.attribution_data.as_mut().unwrap());
718733
onion_utils::test_crypt_failure_packet(
719734
&onion_keys[0].shared_secret.as_ref(), &mut onion_error);
720735
msg.reason = onion_error.data;
736+
msg.attribution_data = onion_error.attribution_data;
721737
}, || {}, true, Some(0x1000|7),
722738
Some(NetworkUpdate::ChannelFailure {
723739
short_channel_id: channels[1].0.contents.short_channel_id,
@@ -742,11 +758,13 @@ fn test_onion_failure() {
742758
decoded_err_packet.hmac = Hmac::from_engine(hmac).to_byte_array();
743759
let mut onion_error = OnionErrorPacket{
744760
data: decoded_err_packet.encode(),
745-
attribution_data: None,
761+
attribution_data: Some([0; ATTRIBUTION_DATA_LEN]),
746762
};
763+
add_hmacs(&onion_keys[1].shared_secret.as_ref(), &onion_error.data, onion_error.attribution_data.as_mut().unwrap());
747764
onion_utils::test_crypt_failure_packet(
748765
&onion_keys[1].shared_secret.as_ref(), &mut onion_error);
749766
msg.reason = onion_error.data;
767+
msg.attribution_data = onion_error.attribution_data;
750768
}, || nodes[2].node.fail_htlc_backwards(&payment_hash), true, Some(0x1000|7),
751769
Some(NetworkUpdate::ChannelFailure {
752770
short_channel_id: channels[1].0.contents.short_channel_id,

0 commit comments

Comments
 (0)