Skip to content

Commit

Permalink
fix router fee rate issue
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyukang committed Nov 19, 2024
1 parent b9d0afc commit 90f0992
Show file tree
Hide file tree
Showing 13 changed files with 367 additions and 72 deletions.
67 changes: 44 additions & 23 deletions src/ckb/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use once_cell::sync::OnceCell;
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, vec};
use thiserror::Error;
use tracing::info;

use crate::fiber::config::FiberScript;
Expand Down Expand Up @@ -34,27 +35,42 @@ pub struct ContractsContext {
pub contracts: ContractsInfo,
}

#[derive(Debug, Error)]
pub enum ContractsContextError {
#[error("Context already initialized")]
ContextAlreadyInitialized,

#[error("Genesis block transaction #{0} should exist")]
GenesisBlockTransactionNotFound(usize),

#[error("Genesis block transaction #0 output #{0} should exist")]
GenesisBlockTransaction0OutputNotFound(usize),

#[error("Genesis block secp256k1 binary cell type script should exist")]
GenesisBlockSecp256k1BinaryCellTypeScriptNotFound,
}

impl ContractsContext {
pub fn new(
pub fn try_new(
genesis_block: BlockView,
fiber_scripts: Vec<FiberScript>,
udt_whitelist: UdtCfgInfos,
) -> Self {
) -> Result<Self, ContractsContextError> {
let mut contract_default_scripts: HashMap<Contract, Script> = HashMap::new();
let mut script_cell_deps: HashMap<Contract, Vec<CellDep>> = HashMap::new();

let genesis_tx = genesis_block
.transaction(0)
.expect("genesis block transaction #0 should exist");
.ok_or(ContractsContextError::GenesisBlockTransactionNotFound(0))?;

// setup secp256k1
let secp256k1_binary_cell = genesis_tx
.output(1)
.expect("genesis block transaction #0 output #1 should exist");
.ok_or(ContractsContextError::GenesisBlockTransaction0OutputNotFound(1))?;
let secp256k1_binary_cell_type_script = secp256k1_binary_cell
.type_()
.to_opt()
.expect("secp256k1 binary type script should exist");
.ok_or(ContractsContextError::GenesisBlockSecp256k1BinaryCellTypeScriptNotFound)?;
contract_default_scripts.insert(
Contract::Secp256k1Lock,
Script::new_builder()
Expand All @@ -65,7 +81,7 @@ impl ContractsContext {

let secp256k1_dep_group_tx_hash = genesis_block
.transaction(1)
.expect("genesis block transaction #1 should exist")
.ok_or(ContractsContextError::GenesisBlockTransactionNotFound(1))?
.hash();
let secp256k1_dep_group_out_point = OutPoint::new_builder()
.tx_hash(secp256k1_dep_group_tx_hash)
Expand Down Expand Up @@ -119,7 +135,11 @@ impl ContractsContext {
let output_data = genesis_tx
.outputs_data()
.get(index as usize)
.expect("contract output data should exist in the genesis tx")
.ok_or(
ContractsContextError::GenesisBlockTransaction0OutputNotFound(
index as usize,
),
)?
.raw_data();
let cell_deps =
if matches!(contract, Contract::FundingLock | Contract::CommitmentLock) {
Expand Down Expand Up @@ -150,13 +170,13 @@ impl ContractsContext {
script_cell_deps.insert(name, cell_deps.into_iter().map(CellDep::from).collect());
}

Self {
Ok(Self {
contracts: ContractsInfo {
contract_default_scripts,
script_cell_deps,
udt_whitelist,
},
}
})
}

fn get_contracts_map(&self) -> &HashMap<Contract, Script> {
Expand All @@ -180,7 +200,7 @@ impl ContractsContext {
pub(crate) fn get_script(&self, contract: Contract, args: &[u8]) -> Script {
self.get_contracts_map()
.get(&contract)
.unwrap_or_else(|| panic!("Contract {:?} exists", contract))
.unwrap_or_else(|| panic!("Contract {:?} should exist", contract))
.clone()
.as_builder()
.args(args.pack())
Expand All @@ -189,14 +209,15 @@ impl ContractsContext {

pub(crate) fn get_udt_info(&self, udt_script: &Script) -> Option<&UdtArgInfo> {
for udt in &self.get_udt_whitelist().0 {
let _type: ScriptHashType = udt_script.hash_type().try_into().expect("valid hash type");
if udt.script.code_hash.pack() == udt_script.code_hash()
&& udt.script.hash_type == _type
{
let args = format!("0x{:x}", udt_script.args().raw_data());
let pattern = Regex::new(&udt.script.args).expect("invalid expression");
if pattern.is_match(&args) {
return Some(udt);
if let Some(_type) = udt_script.hash_type().try_into().ok() {
if udt.script.code_hash.pack() == udt_script.code_hash()
&& udt.script.hash_type == _type
{
let args = format!("0x{:x}", udt_script.args().raw_data());
let pattern = Regex::new(&udt.script.args).expect("invalid expression");
if pattern.is_match(&args) {
return Some(udt);
}
}
}
}
Expand All @@ -206,18 +227,18 @@ impl ContractsContext {

pub static CONTRACTS_CONTEXT_INSTANCE: OnceCell<ContractsContext> = OnceCell::new();

pub fn init_contracts_context(
pub fn try_init_contracts_context(
genesis_block: BlockView,
fiber_scripts: Vec<FiberScript>,
udt_whitelist: UdtCfgInfos,
) {
) -> Result<(), ContractsContextError> {
CONTRACTS_CONTEXT_INSTANCE
.set(ContractsContext::new(
.set(ContractsContext::try_new(
genesis_block,
fiber_scripts,
udt_whitelist,
))
.expect("init_contracts_context should only be called once");
)?)
.map_err(|_| ContractsContextError::ContextAlreadyInitialized)
}

#[cfg(not(test))]
Expand Down
9 changes: 7 additions & 2 deletions src/fiber/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,12 @@ where
.expect("public channel exits")
.tlc_fee_proportional_millionths
.unwrap_or_default();
info!("expecting fee_rate: {}", fee_rate);
let expected_fee = calculate_tlc_forward_fee(forward_amount, fee_rate);
info!(
"forward_fee: {} expected_fee: {}",
forward_fee, expected_fee
);
if forward_fee < expected_fee {
error!(
"too low forward_fee: {}, expected_fee: {}",
Expand Down Expand Up @@ -2983,11 +2988,11 @@ impl ChannelActorState {
.sum::<u128>()
}

pub fn get_created_at_in_microseconds(&self) -> u64 {
pub fn get_created_at_in_millis(&self) -> u64 {
self.created_at
.duration_since(UNIX_EPOCH)
.expect("Duration since unix epoch")
.as_micros() as u64
.as_millis() as u64
}

pub fn is_closed(&self) -> bool {
Expand Down
62 changes: 45 additions & 17 deletions src/fiber/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::fiber::path::NodeHeapElement;
use crate::fiber::serde_utils::EntityHex;
use crate::fiber::types::PaymentHopData;
use crate::invoice::CkbInvoice;
use crate::now_timestamp;
use ckb_jsonrpc_types::JsonBytes;
use ckb_types::packed::{OutPoint, Script};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -112,6 +113,16 @@ impl ChannelInfo {
pub fn funding_tx_block_number(&self) -> u64 {
self.funding_tx_block_number
}

fn get_update_info_with(&self, node: Pubkey) -> Option<&ChannelUpdateInfo> {
if self.node2() == node {
self.node1_to_node2.as_ref()
} else if self.node1() == node {
self.node2_to_node1.as_ref()
} else {
None
}
}
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
Expand Down Expand Up @@ -393,8 +404,10 @@ where
&channel, &update
);
let update_info = if update.message_flags & 1 == 1 {
debug!("now update node1_to_node2: {:?}", &update);
&mut channel.node1_to_node2
} else {
debug!("now update node2_to_node1: {:?}", &update);
&mut channel.node2_to_node1
};

Expand Down Expand Up @@ -427,6 +440,7 @@ where
last_update_message: update.clone(),
});

info!("now new update_info: {:?}", *update_info);
self.store.insert_channel(channel.to_owned());
debug!(
"Processed channel update: channel {:?}, update {:?}",
Expand All @@ -449,12 +463,14 @@ where
self.channels.values().filter_map(move |channel| {
if let Some(info) = channel.node1_to_node2.as_ref() {
if info.enabled && channel.node2() == node_id {
debug!("now use node1_to_node2: {:?}", info);
return Some((channel.node1(), channel.node2(), channel, info));
}
}

if let Some(info) = channel.node2_to_node1.as_ref() {
if info.enabled && channel.node1() == node_id {
debug!("now use node2_to_node1: {:?}", info);
return Some((channel.node2(), channel.node1(), channel, info));
}
}
Expand Down Expand Up @@ -578,17 +594,18 @@ where
(0, 0)
} else {
let channel_info = self
.get_channel(&route[i + 1].channel_outpoint)
.get_channel(&route[i].channel_outpoint)
.expect("channel not found");
let channel_update = &if channel_info.node1() == route[i + 1].target {
channel_info.node2_to_node1.as_ref()
} else {
channel_info.node1_to_node2.as_ref()
}
.expect("channel_update is none");
let channel_update = channel_info
.get_update_info_with(route[i].target)
.expect("channel_update is none");
let fee_rate = channel_update.fee_rate;
let fee = calculate_tlc_forward_fee(current_amount, fee_rate as u128);
let expiry = channel_update.htlc_expiry_delta;
eprintln!(
"fee: {:?}, expiry: {:?}, current_amount: {:?}, fee_rate: {:?}",
fee, expiry, current_amount, fee_rate
);
(fee, expiry)
};

Expand Down Expand Up @@ -712,6 +729,7 @@ where
.values()
.any(|x| x == &channel_info.out_point())
{
eprintln!("here ......");
continue;
}

Expand All @@ -722,9 +740,15 @@ where
let fee = calculate_tlc_forward_fee(next_hop_received_amount, fee_rate as u128);
let amount_to_send = next_hop_received_amount + fee;

eprintln!("amount_to_send: {:?}", amount_to_send);
// if the amount to send is greater than the amount we have, skip this edge
if let Some(max_fee_amount) = max_fee_amount {
if amount_to_send > amount + max_fee_amount {
eprintln!(
"amount_to_send {} > amount + max_fee_amount {}",
amount_to_send,
amount + max_fee_amount
);
continue;
}
}
Expand All @@ -734,6 +758,13 @@ where
|| (channel_update.htlc_maximum_value != 0
&& amount_to_send > channel_update.htlc_maximum_value)
{
eprintln!(
"now .......amount: {:?} capacity: {:?}, channel_update.htlc_maximum_value: {:?}",
amount_to_send,
channel_info.capacity(),
channel_update.htlc_maximum_value

);
continue;
}
if amount_to_send < channel_update.htlc_minimum_value {
Expand All @@ -755,6 +786,7 @@ where
);

if probability < DEFAULT_MIN_PROBABILITY {
eprintln!("probability < DEFAULT_MIN_PROBABILITY");
continue;
}
let agg_weight =
Expand All @@ -767,6 +799,8 @@ where
continue;
}
}
eprintln!("\n\nfind_path from: {:?}, to: {:?}", from, to);
eprintln!("add use channel_info: {:?}\n\n", channel_info);
let node = NodeHeapElement {
node_id: from,
weight,
Expand Down Expand Up @@ -912,8 +946,8 @@ pub struct PaymentSession {
pub last_error: Option<String>,
pub try_limit: u32,
pub status: PaymentSessionStatus,
pub created_at: u128,
pub last_updated_at: u128,
pub created_at: u64,
pub last_updated_at: u64,
// The channel_outpoint and the tlc_id of the first hop
#[serde_as(as = "Option<EntityHex>")]
pub first_hop_channel_outpoint: Option<OutPoint>,
Expand All @@ -923,10 +957,7 @@ pub struct PaymentSession {

impl PaymentSession {
pub fn new(request: SendPaymentData, try_limit: u32) -> Self {
let now = std::time::UNIX_EPOCH
.elapsed()
.expect("Duration since unix epoch")
.as_millis();
let now = now_timestamp();
Self {
request,
retried_times: 0,
Expand All @@ -947,10 +978,7 @@ impl PaymentSession {

fn set_status(&mut self, status: PaymentSessionStatus) {
self.status = status;
self.last_updated_at = std::time::UNIX_EPOCH
.elapsed()
.expect("Duration since unix epoch")
.as_micros();
self.last_updated_at = now_timestamp();
}

pub fn set_inflight_status(&mut self, channel_outpoint: OutPoint, tlc_id: u64) {
Expand Down
4 changes: 2 additions & 2 deletions src/fiber/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ pub struct AcceptChannelResponse {
pub struct SendPaymentResponse {
pub payment_hash: Hash256,
pub status: PaymentSessionStatus,
pub created_at: u128,
pub last_updated_at: u128,
pub created_at: u64,
pub last_updated_at: u64,
pub failed_error: Option<String>,
}

Expand Down
Loading

0 comments on commit 90f0992

Please sign in to comment.