Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix a bug in direct channel #411

Merged
merged 1 commit into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/fiber/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -900,12 +900,17 @@ where
}

// if this is a direct channel, try to load the channel actor state for balance
if from == self.source {
if from == self.source || to == self.source {
if let Some(state) = self
.store
.get_channel_state_by_outpoint(&channel_info.out_point())
{
if amount_to_send > state.to_local_amount {
let balance = if from == self.source {
state.to_local_amount
} else {
state.to_remote_amount
};
if amount_to_send > balance {
continue;
}
}
Expand Down
74 changes: 35 additions & 39 deletions src/fiber/tests/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ use crate::fiber::channel::{
use crate::fiber::config::MAX_PAYMENT_TLC_EXPIRY_LIMIT;
use crate::fiber::graph::PaymentSessionStatus;
use crate::fiber::network::{DebugEvent, SendPaymentCommand};
use crate::fiber::tests::test_utils::create_n_nodes_with_index_and_amounts_with_established_channel;
use crate::fiber::tests::test_utils::{
create_3_nodes_with_established_channel, create_n_nodes_with_established_channel,
create_nodes_with_established_channel, NetworkNodeConfigBuilder,
};
use crate::fiber::tests::test_utils::*;
use crate::fiber::types::{
Hash256, PaymentHopData, PeeledOnionPacket, TlcErrorCode, NO_SHARED_SECRET,
};
Expand Down Expand Up @@ -1134,8 +1130,8 @@ async fn test_network_send_payment_amount_is_too_large() {
init_tracing();

let _span = tracing::info_span!("node", node = "test").entered();
let node_a_funding_amount = 100000000000 + 4200000000;
let node_b_funding_amount = 4200000000 + 2;
let node_a_funding_amount = 100000000000 + MIN_RESERVED_CKB;
let node_b_funding_amount = MIN_RESERVED_CKB + 2;

let (node_a, node_b, _new_channel_id) =
create_nodes_with_established_channel(node_a_funding_amount, node_b_funding_amount, true)
Expand Down Expand Up @@ -4189,8 +4185,8 @@ async fn test_send_payment_with_multiple_edges_in_middle_hops() {
let (nodes, _channels) = create_n_nodes_with_index_and_amounts_with_established_channel(
&[
((0, 1), (100000000000, 100000000000)),
((1, 2), (4200000000 + 900, 5200000000)),
((1, 2), (4200000000 + 1000, 5200000000)),
((1, 2), (MIN_RESERVED_CKB + 900, 5200000000)),
((1, 2), (MIN_RESERVED_CKB + 1000, 5200000000)),
((2, 3), (100000000000, 100000000000)),
],
4,
Expand Down Expand Up @@ -4256,8 +4252,8 @@ async fn test_send_payment_with_all_failed_middle_hops() {
let (nodes, _channels) = create_n_nodes_with_index_and_amounts_with_established_channel(
&[
((0, 1), (100000000000, 100000000000)),
((1, 2), (4200000000 + 900, 4200000000 + 1000)),
((1, 2), (4200000000 + 910, 4200000000 + 1000)),
((1, 2), (MIN_RESERVED_CKB + 900, MIN_RESERVED_CKB + 1000)),
((1, 2), (MIN_RESERVED_CKB + 910, MIN_RESERVED_CKB + 1000)),
((2, 3), (100000000000, 100000000000)),
],
4,
Expand Down Expand Up @@ -4323,8 +4319,8 @@ async fn test_send_payment_with_multiple_edges_can_succeed_in_retry() {
let (nodes, _channels) = create_n_nodes_with_index_and_amounts_with_established_channel(
&[
((0, 1), (100000000000, 100000000000)),
((1, 2), (4200000000 + 1000, 5200000000)),
((1, 2), (4200000000 + 900, 6200000000)),
((1, 2), (MIN_RESERVED_CKB + 1000, 5200000000)),
((1, 2), (MIN_RESERVED_CKB + 900, 6200000000)),
((2, 3), (100000000000, 100000000000)),
],
4,
Expand Down Expand Up @@ -4391,8 +4387,8 @@ async fn test_send_payment_with_final_hop_multiple_edges_in_middle_hops() {
&[
((0, 1), (100000000000, 100000000000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (4200000000 + 900, 5200000000)),
((2, 3), (4200000000 + 1000, 5200000000)),
((2, 3), (MIN_RESERVED_CKB + 900, 5200000000)),
((2, 3), (MIN_RESERVED_CKB + 1000, 5200000000)),
],
4,
true,
Expand Down Expand Up @@ -4458,8 +4454,8 @@ async fn test_send_payment_with_final_all_failed_middle_hops() {
&[
((0, 1), (100000000000, 100000000000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (4200000000 + 900, 4200000000 + 1000)),
((2, 3), (4200000000 + 910, 4200000000 + 1000)),
((2, 3), (MIN_RESERVED_CKB + 900, MIN_RESERVED_CKB + 1000)),
((2, 3), (MIN_RESERVED_CKB + 910, MIN_RESERVED_CKB + 1000)),
],
4,
true,
Expand Down Expand Up @@ -4516,8 +4512,8 @@ async fn test_send_payment_with_final_multiple_edges_can_succeed_in_retry() {
&[
((0, 1), (100000000000, 100000000000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (4200000000 + 1000, 5200000000)),
((2, 3), (4200000000 + 900, 6200000000)),
((2, 3), (MIN_RESERVED_CKB + 1000, 5200000000)),
((2, 3), (MIN_RESERVED_CKB + 900, 6200000000)),
],
4,
true,
Expand Down Expand Up @@ -4571,7 +4567,7 @@ async fn test_send_payment_with_first_hop_failed_with_fee() {
// even 1000 > 999, but it's not enough for fee, and this is the direct channel
// so we can check the actual balance of channel
// the payment will fail
((0, 1), (4200000000 + 1000, 5200000000)),
((0, 1), (MIN_RESERVED_CKB + 1000, 5200000000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (100000000000, 100000000000)),
],
Expand Down Expand Up @@ -4622,8 +4618,8 @@ async fn test_send_payment_succeed_with_multiple_edges_in_first_hop() {
// the send payment should be succeed
let (nodes, _channels) = create_n_nodes_with_index_and_amounts_with_established_channel(
&[
((0, 1), (4200000000 + 900, 5200000000)),
((0, 1), (4200000000 + 1001, 5200000000)),
((0, 1), (MIN_RESERVED_CKB + 900, 5200000000)),
((0, 1), (MIN_RESERVED_CKB + 1001, 5200000000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (100000000000, 100000000000)),
],
Expand Down Expand Up @@ -4679,8 +4675,8 @@ async fn test_send_payment_with_first_hop_all_failed() {
// path finding will fail in the first time of send payment
let (nodes, _channels) = create_n_nodes_with_index_and_amounts_with_established_channel(
&[
((0, 1), (4200000000 + 900, 4200000000 + 1000)),
((0, 1), (4200000000 + 910, 4200000000 + 1000)),
((0, 1), (MIN_RESERVED_CKB + 900, MIN_RESERVED_CKB + 1000)),
((0, 1), (MIN_RESERVED_CKB + 910, MIN_RESERVED_CKB + 1000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (100000000000, 100000000000)),
],
Expand Down Expand Up @@ -4733,8 +4729,8 @@ async fn test_send_payment_will_succeed_with_direct_channel_info_first_hop() {
// so it will try the channel with smaller capacity and the payment will succeed
let (nodes, channels) = create_n_nodes_with_index_and_amounts_with_established_channel(
&[
((0, 1), (4200000000 + 2000, 4200000000 + 1000)),
((0, 1), (4200000000 + 1005, 4200000000 + 1000)),
((0, 1), (MIN_RESERVED_CKB + 2000, MIN_RESERVED_CKB + 1000)),
((0, 1), (MIN_RESERVED_CKB + 1005, MIN_RESERVED_CKB + 1000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (100000000000, 100000000000)),
],
Expand Down Expand Up @@ -4801,8 +4797,8 @@ async fn test_send_payment_will_succeed_with_retry_in_middle_hops() {
&[
((0, 1), (100000000000, 100000000000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (4200000000 + 2000, 4200000000 + 1000)),
((2, 3), (4200000000 + 1005, 4200000000 + 1000)),
((2, 3), (MIN_RESERVED_CKB + 2000, MIN_RESERVED_CKB + 1000)),
((2, 3), (MIN_RESERVED_CKB + 1005, MIN_RESERVED_CKB + 1000)),
],
4,
true,
Expand Down Expand Up @@ -4865,8 +4861,8 @@ async fn test_send_payment_will_fail_with_last_hop_info_in_add_tlc_peer() {
&[
((0, 1), (100000000000, 100000000000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (4200000000 + 2000, 4200000000 + 1000)),
((2, 3), (4200000000 + 1005, 4200000000 + 1000)),
((2, 3), (MIN_RESERVED_CKB + 2000, MIN_RESERVED_CKB + 1000)),
((2, 3), (MIN_RESERVED_CKB + 1005, MIN_RESERVED_CKB + 1000)),
],
4,
true,
Expand Down Expand Up @@ -4933,8 +4929,8 @@ async fn test_send_payment_will_fail_with_invoice_not_generated_by_target() {
&[
((0, 1), (100000000000, 100000000000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (4200000000 + 2000, 4200000000 + 1000)),
((2, 3), (4200000000 + 1005, 4200000000 + 1000)),
((2, 3), (MIN_RESERVED_CKB + 2000, MIN_RESERVED_CKB + 1000)),
((2, 3), (MIN_RESERVED_CKB + 1005, MIN_RESERVED_CKB + 1000)),
],
4,
true,
Expand Down Expand Up @@ -4994,8 +4990,8 @@ async fn test_send_payment_will_succeed_with_valid_invoice() {
&[
((0, 1), (100000000000, 100000000000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (4200000000 + 2000, 4200000000 + 1000)),
((2, 3), (4200000000 + 1005, 4200000000 + 1000)),
((2, 3), (MIN_RESERVED_CKB + 2000, MIN_RESERVED_CKB + 1000)),
((2, 3), (MIN_RESERVED_CKB + 1005, MIN_RESERVED_CKB + 1000)),
],
4,
true,
Expand Down Expand Up @@ -5064,8 +5060,8 @@ async fn test_send_payment_will_fail_with_no_invoice_preimage() {
&[
((0, 1), (100000000000, 100000000000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (4200000000 + 2000, 4200000000 + 1000)),
((2, 3), (4200000000 + 1005, 4200000000 + 1000)),
((2, 3), (MIN_RESERVED_CKB + 2000, MIN_RESERVED_CKB + 1000)),
((2, 3), (MIN_RESERVED_CKB + 1005, MIN_RESERVED_CKB + 1000)),
],
4,
true,
Expand Down Expand Up @@ -5136,8 +5132,8 @@ async fn test_send_payment_will_fail_with_cancelled_invoice() {
&[
((0, 1), (100000000000, 100000000000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (4200000000 + 2000, 4200000000 + 1000)),
((2, 3), (4200000000 + 1005, 4200000000 + 1000)),
((2, 3), (MIN_RESERVED_CKB + 2000, MIN_RESERVED_CKB + 1000)),
((2, 3), (MIN_RESERVED_CKB + 1005, MIN_RESERVED_CKB + 1000)),
],
4,
true,
Expand Down Expand Up @@ -5207,7 +5203,7 @@ async fn test_send_payment_will_succeed_with_large_tlc_expiry_limit() {

let (nodes, _channels) = create_n_nodes_with_index_and_amounts_with_established_channel(
&[
((0, 1), (4200000000 + 2000, 4200000000 + 1000)),
((0, 1), (MIN_RESERVED_CKB + 2000, MIN_RESERVED_CKB + 1000)),
((1, 2), (100000000000, 100000000000)),
((2, 3), (100000000000, 100000000000)),
],
Expand Down
131 changes: 129 additions & 2 deletions src/fiber/tests/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ async fn test_send_payment_for_direct_channel_and_dry_run() {

let (nodes, channels) = create_n_nodes_with_index_and_amounts_with_established_channel(
&[
((0, 1), (4200000000 + 10000000000, 4200000000)),
((0, 1), (4200000000, 4200000000 + 10000000000)),
((0, 1), (MIN_RESERVED_CKB + 10000000000, MIN_RESERVED_CKB)),
((0, 1), (MIN_RESERVED_CKB, MIN_RESERVED_CKB + 10000000000)),
],
2,
true,
Expand Down Expand Up @@ -115,3 +115,130 @@ async fn test_send_payment_for_direct_channel_and_dry_run() {
assert_eq!(node_0_balance, 10000000000);
assert_eq!(node_1_balance, 0);
}

#[tokio::test]
async fn test_send_payment_for_pay_self() {
init_tracing();
let _span = tracing::info_span!("node", node = "test").entered();
// from https://github.com/nervosnetwork/fiber/issues/362

let (nodes, channels) = create_n_nodes_with_index_and_amounts_with_established_channel(
&[
((0, 1), (MIN_RESERVED_CKB + 10000000000, MIN_RESERVED_CKB)),
((1, 2), (MIN_RESERVED_CKB + 10000000000, MIN_RESERVED_CKB)),
((2, 0), (MIN_RESERVED_CKB + 10000000000, MIN_RESERVED_CKB)),
],
3,
true,
)
.await;
let [mut node_0, node_1, node_2] = nodes.try_into().expect("3 nodes");

let node_1_channel0_balance = node_1.get_local_balance_from_channel(channels[0]);
let node_1_channel1_balance = node_1.get_local_balance_from_channel(channels[1]);
let node_2_channel1_balance = node_2.get_local_balance_from_channel(channels[1]);
let node_2_channel2_balance = node_2.get_local_balance_from_channel(channels[2]);

// sleep for a while
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;

// now node_0 -> node_2 will be ok only with node_1, so the fee is larger than 0
let res = node_0
.send_payment(SendPaymentCommand {
target_pubkey: Some(node_2.pubkey.clone()),
amount: Some(60000000),
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,
dry_run: true,
})
.await;

assert!(res.unwrap().fee > 0);

// node_0 -> node_0 will be ok for dry_run if `allow_self_payment` is true
let res = node_0
.send_payment(SendPaymentCommand {
target_pubkey: Some(node_0.pubkey.clone()),
amount: Some(60000000),
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: true,
dry_run: false,
})
.await;

eprintln!("res: {:?}", res);
assert!(res.is_ok());

// sleep for a while
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
let res = res.unwrap();
let payment_hash = res.payment_hash;
node_0
.assert_payment_status(payment_hash, PaymentSessionStatus::Success, Some(1))
.await;

let node_0_balance1 = node_0.get_local_balance_from_channel(channels[0]);
let node_0_balance2 = node_0.get_local_balance_from_channel(channels[2]);

assert_eq!(node_0_balance1, 10000000000 - 60000000 - res.fee);
assert_eq!(node_0_balance2, 60000000);

eprintln!(
"node1 left: {:?}, right: {:?}",
node_1.get_local_balance_from_channel(channels[0]),
node_1.get_local_balance_from_channel(channels[1])
);

let node_1_new_channel0_balance = node_1.get_local_balance_from_channel(channels[0]);
let node_1_new_channel1_balance = node_1.get_local_balance_from_channel(channels[1]);
let node_2_new_channel1_balance = node_2.get_local_balance_from_channel(channels[1]);
let node_2_new_channel2_balance = node_2.get_local_balance_from_channel(channels[2]);

let node1_fee = (node_1_new_channel0_balance - node_1_channel0_balance)
- (node_1_channel1_balance - node_1_new_channel1_balance);
assert!(node1_fee > 0);

let node2_fee = (node_2_new_channel1_balance - node_2_channel1_balance)
- (node_2_channel2_balance - node_2_new_channel2_balance);
assert!(node2_fee > 0);
assert_eq!(node1_fee + node2_fee, res.fee);

// node_0 -> node_2 will be ok with direct channel2,
// since after payself this channel now have enough balance, so the fee is 0
let res = node_0
.send_payment(SendPaymentCommand {
target_pubkey: Some(node_2.pubkey.clone()),
amount: Some(60000000),
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,
dry_run: true,
})
.await;

eprintln!("res: {:?}", res);
assert_eq!(res.unwrap().fee, 0);
}
1 change: 1 addition & 0 deletions src/fiber/tests/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ use crate::{
};

static RETAIN_VAR: &str = "TEST_TEMP_RETAIN";
pub(crate) const MIN_RESERVED_CKB: u128 = 4200000000;

#[derive(Debug)]
pub struct TempDir(ManuallyDrop<OldTempDir>);
Expand Down
Loading