Skip to content

Commit

Permalink
fix issue 499 disable channel
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyukang committed Jan 26, 2025
1 parent 2f12f40 commit 4c55eac
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 92 deletions.
4 changes: 2 additions & 2 deletions migrate/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 8 additions & 4 deletions src/fiber/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,9 @@ where
TlcErrorCode::PermanentChannelFailure
}
ChannelState::ChannelReady() => {
if error.contains("channel is not public or disabled") {
eprintln!("debug now InvalidState error: {}", error);
if !state.local_tlc_info.enabled {
// channel is disabled
TlcErrorCode::TemporaryChannelFailure
} else {
// we expect `ChannelReady` will be both OK for tlc forwarding,
Expand Down Expand Up @@ -1012,7 +1014,7 @@ where
return Err(ProcessingChannelError::FinalIncorrectPaymentHash);
}
} else {
if state.is_public() && state.is_tlc_forwarding_enabled() {
if state.is_public() {
if add_tlc.expiry
< peeled_onion_packet.current.expiry + state.local_tlc_info.tlc_expiry_delta
{
Expand All @@ -1037,9 +1039,11 @@ where
} else {
// if we don't have public channel info, we can not forward the TLC
// this may happended some malicious sender build a invalid onion router
// here we don't need to check the next channel maybe disabled, because
// handle_add_tlc_command will check the channel state before forwarding
eprintln!("got here .........");
return Err(ProcessingChannelError::InvalidState(
"Received AddTlc message, but the channel is not public or disabled"
.to_string(),
"Received AddTlc message, but the channel is not public".to_string(),
));
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/fiber/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1530,6 +1530,8 @@ where
.write()
.await
.record_payment_fail(&payment_session, error_detail.clone());
eprintln!("yukang payment fail: {:?}", error_detail);
eprintln!("yukang need_to_retry: {:?}", need_to_retry);
if need_to_retry {
// If this is the first hop error, like the WaitingTlcAck error,
// we will just retry later, return Ok here for letting endpoint user
Expand Down Expand Up @@ -1783,6 +1785,7 @@ where
let hops_info = self
.build_payment_route(&mut payment_session, &payment_data)
.await?;

match self
.send_payment_onion_packet(state, &mut payment_session, &payment_data, hops_info)
.await
Expand Down
159 changes: 73 additions & 86 deletions src/fiber/tests/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3468,42 +3468,42 @@ async fn test_forward_payment_channel_disabled() {
true,
)
.await;
let [node_a, node_b, node_c] = nodes.try_into().expect("3 nodes");
let [mut node_a, mut node_b, mut node_c] = nodes.try_into().expect("3 nodes");
let [_channel_a_b, channel_b_c] = channels.try_into().expect("2 channels");

let node_c_pubkey = node_c.pubkey.clone();

tokio::time::sleep(tokio::time::Duration::from_millis(1000)).await;

let tlc_amount = 100;
let res = node_a
.send_payment_keysend(&node_c, 10_000_000, false)
.await;
assert!(res.is_ok(), "Send payment failed: {:?}", res);
let res = res.unwrap();
let payment_hash = res.payment_hash;
node_a.wait_until_success(payment_hash).await;

let message = |rpc_reply| -> NetworkActorMessage {
NetworkActorMessage::Command(NetworkActorCommand::SendPayment(
SendPaymentCommand {
target_pubkey: Some(node_c_pubkey),
amount: Some(tlc_amount),
payment_hash: None,
final_tlc_expiry_delta: None,
tlc_expiry_limit: None,
invoice: None,
timeout: None,
max_fee_amount: None,
max_parts: None,
keysend: Some(true),
udt_type_script: None,
allow_self_payment: false,
hop_hints: None,
dry_run: false,
},
rpc_reply,
))
};
let res = call!(node_a.network_actor, message)
.expect("node_a alive")
.unwrap();
// this is the payment_hash generated by keysend
assert_eq!(res.status, PaymentSessionStatus::Created);
tokio::time::sleep(tokio::time::Duration::from_millis(1000)).await;
let res = node_b
.send_payment_keysend(&node_c, 10_000_000, false)
.await;
assert!(res.is_ok(), "Send payment failed: {:?}", res);
let res = res.unwrap();
let payment_hash = res.payment_hash;
node_b.wait_until_success(payment_hash).await;

let res = node_c
.send_payment_keysend(&node_a, 10_000_000, false)
.await;
assert!(res.is_ok(), "Send payment failed: {:?}", res);
let res = res.unwrap();
let payment_hash = res.payment_hash;
node_c.wait_until_success(payment_hash).await;

let res = node_b
.send_payment_keysend(&node_a, 10_000_000, false)
.await;
assert!(res.is_ok(), "Send payment failed: {:?}", res);
let res = res.unwrap();
let payment_hash = res.payment_hash;
node_b.wait_until_success(payment_hash).await;

// update channel to disable it from node_b
let update_result = call!(node_b.network_actor, |rpc_reply| {
Expand All @@ -3526,29 +3526,31 @@ async fn test_forward_payment_channel_disabled() {
assert!(update_result.is_ok());
tokio::time::sleep(tokio::time::Duration::from_millis(1000)).await;

let message = |rpc_reply| -> NetworkActorMessage {
NetworkActorMessage::Command(NetworkActorCommand::SendPayment(
SendPaymentCommand {
target_pubkey: Some(node_c_pubkey),
amount: Some(tlc_amount),
payment_hash: None,
final_tlc_expiry_delta: None,
tlc_expiry_limit: None,
invoice: None,
timeout: None,
max_fee_amount: None,
max_parts: None,
keysend: Some(true),
udt_type_script: None,
allow_self_payment: false,
hop_hints: None,
dry_run: false,
},
rpc_reply,
))
};
let res = call!(node_a.network_actor, message).expect("node_a alive");
assert!(res.is_err());
let res = node_a
.send_payment_keysend(&node_c, 10_000_000, false)
.await;
assert!(res.is_err(), "Send payment should fail: {:?}", res);

let res = node_b
.send_payment_keysend(&node_c, 10_000_000, false)
.await;
assert!(res.is_err(), "Send payment should fail: {:?}", res);

let res = node_c
.send_payment_keysend(&node_b, 10_000_000, false)
.await;
assert!(res.is_ok(), "Send payment failed: {:?}", res);
let res = res.unwrap();
let payment_hash = res.payment_hash;
node_c.wait_until_success(payment_hash).await;

let res = node_c
.send_payment_keysend(&node_a, 80_000_000, false)
.await;
assert!(res.is_ok(), "Send payment failed: {:?}", res);
let res = res.unwrap();
let payment_hash = res.payment_hash;
node_c.wait_until_success(payment_hash).await;
}

#[tokio::test]
Expand Down Expand Up @@ -5146,49 +5148,34 @@ async fn test_send_payment_with_disable_channel() {
let amounts = vec![(100000000000, 100000000000); nodes_num - 1];
let (nodes, channels) =
create_n_nodes_with_established_channel(&amounts, nodes_num, true).await;
let [node_0, _node_1, mut node_2, node_3] = nodes.try_into().expect("4 nodes");
let source_node = &node_0;
let target_pubkey = node_3.pubkey.clone();

// sleep for a while
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
let [mut node_0, _node_1, mut node_2, mut node_3] = nodes.try_into().expect("4 nodes");

// begin to set channel disable, but do not notify the network
node_2.disable_channel_stealthy(channels[1]).await;
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;

let message = |rpc_reply| -> NetworkActorMessage {
NetworkActorMessage::Command(NetworkActorCommand::SendPayment(
SendPaymentCommand {
target_pubkey: Some(target_pubkey.clone()),
amount: Some(3000),
payment_hash: None,
final_tlc_expiry_delta: None,
tlc_expiry_limit: None,
invoice: None,
timeout: None,
max_fee_amount: None,
max_parts: None,
keysend: Some(true),
udt_type_script: None,
allow_self_payment: false,
hop_hints: None,
dry_run: false,
},
rpc_reply,
))
};

// expect send payment failed
let res = call!(source_node.network_actor, message).expect("source_node alive");
// expect send payment failed from node_3 to node_0
//let res = call!(source_node.network_actor, message).expect("source_node alive");
let res = node_3.send_payment_keysend(&node_0, 3000, false).await;
assert!(res.is_ok());
let payment_hash = res.unwrap().payment_hash;

source_node.wait_until_failed(payment_hash).await;
node_3.wait_until_failed(payment_hash).await;

// because there is only one path for the payment, the payment will fail in the second try
// this assertion make sure we didn't do meaningless retry
let payment_session = source_node.get_payment_session(payment_hash).unwrap();
let payment_session = node_3.get_payment_session(payment_hash).unwrap();
assert_eq!(payment_session.retried_times, 2);

// expect send payment successfully from node_0 to node_3
let res = node_0.send_payment_keysend(&node_3, 3000, false).await;
assert!(res.is_ok());
let payment_hash = res.unwrap().payment_hash;

node_0.wait_until_success(payment_hash).await;

let payment_session = node_0.get_payment_session(payment_hash).unwrap();
assert_eq!(payment_session.retried_times, 1);
}

#[tokio::test]
Expand Down
7 changes: 7 additions & 0 deletions src/fiber/tests/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,19 @@ async fn test_send_payment_over_private_channel() {
eprintln!("res: {:?}", res);
if is_payment_ok {
assert!(res.is_ok());
source_node
.wait_until_success(res.unwrap().payment_hash)
.await;
} else {
assert!(res.is_err());
source_node
.wait_until_failed(res.unwrap().payment_hash)
.await;
}
}

test(10000000000, true).await;
tokio::time::sleep(tokio::time::Duration::from_millis(2000)).await;
test(30000000000, false).await;
}

Expand Down

0 comments on commit 4c55eac

Please sign in to comment.