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 Maker fees & Document fees workflow. #355

Merged
merged 5 commits into from
Jan 1, 2025
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
8 changes: 6 additions & 2 deletions directory.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
[directory_config]
# Listening port
port = 8080
# Socks port
socks_port = 19060
connection_type = "tor"
# Connection type
connection_type = TOR
# RPC listening port
rpc_port = 4321
39 changes: 13 additions & 26 deletions maker.toml
Original file line number Diff line number Diff line change
@@ -1,29 +1,16 @@
[maker_config]
# Listening port
port = 6102
# Time interval between connection checks
heart_beat_interval_secs = 3
# Time interval to ping the RPC backend
rpc_ping_interval_secs = 60
# Time interval to ping directory server
# 12 hours = 60*60*12 = 43200
directory_servers_refresh_interval_secs = 43200
# Time interval to close a connection if no response is received
idle_connection_timeout = 300
# Absolute coinswap fee
absolute_fee_sats = 1000
# Fee rate per swap amount in ppb.
amount_relative_fee_ppb = 10000000
# Fee rate for timelocked contract in ppb
time_relative_fee_ppb = 100000
# No of confirmation required for funding transaction
required_confirms = 1
# Minimum timelock difference between contract transaction of two hops
min_contract_reaction_time = 48
# Minimum coinswap amount size in sats
min_size = 10000
# RPC listening port
rpc_port
# Minimum Coinswap amount
min_swap_amount = 100000
# Socks port
socks_part = 19050
# Directory server onion address
directory_server_onion_address = "directoryhiddenserviceaddress.onion:8080"
connection_type = "tor"
socks_port = 19050
# Directory server address
directory_server_address = 127.0.0.1:8080
# Fidelity Bond amount
fidelity_amount = 5000000
# Fidelity Bond timelock in Block heights
fidelity_timelock = 26000
# Connection type
connection_type = TOR
8 changes: 3 additions & 5 deletions src/bin/directoryd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
#[clap(version = option_env ! ("CARGO_PKG_VERSION").unwrap_or("unknown"),
author = option_env ! ("CARGO_PKG_AUTHORS").unwrap_or(""))]
struct Cli {
/// Optional network type.
#[clap(long, short = 'n', default_value = "tor", possible_values = &["tor", "clearnet"])]
network: String,
/// Optional DNS data directory. Default value : "~/.coinswap/dns"
#[clap(long, short = 'd')]
data_directory: Option<PathBuf>,
Expand Down Expand Up @@ -53,21 +50,22 @@

let rpc_network = bitcoin::Network::from_str(&args.rpc_network).unwrap();

let conn_type = ConnectionType::from_str(&args.network)?;

let rpc_config = RPCConfig {
url: args.rpc,
auth: Auth::UserPass(args.auth.0, args.auth.1),
network: rpc_network,
wallet_name: "random".to_string(), // we can put anything here as it will get updated in the init.
};

let conn_type = ConnectionType::TOR;

Check warning on line 60 in src/bin/directoryd.rs

View check run for this annotation

Codecov / codecov/patch

src/bin/directoryd.rs#L60

Added line #L60 was not covered by tests

#[cfg(feature = "tor")]
{
if conn_type == ConnectionType::TOR {
setup_mitosis();
}
}

let directory = Arc::new(DirectoryServer::new(args.data_directory, Some(conn_type))?);

start_directory_server(directory, Some(rpc_config))?;
Expand Down
7 changes: 2 additions & 5 deletions src/bin/makerd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@
#[clap(version = option_env ! ("CARGO_PKG_VERSION").unwrap_or("unknown"),
author = option_env ! ("CARGO_PKG_AUTHORS").unwrap_or(""))]
struct Cli {
/// Optional Connection Network Type
#[clap(long, default_value = "tor", possible_values = &["tor", "clearnet"])]
network: String,
/// Optional DNS data directory. Default value : "~/.coinswap/maker"
#[clap(long, short = 'd')]
data_directory: Option<PathBuf>,
Expand Down Expand Up @@ -60,15 +57,15 @@

let rpc_network = bitcoin::Network::from_str(&args.rpc_network).unwrap();

let conn_type = ConnectionType::from_str(&args.network)?;

let rpc_config = RPCConfig {
url: args.rpc,
auth: Auth::UserPass(args.auth.0, args.auth.1),
network: rpc_network,
wallet_name: "random".to_string(), // we can put anything here as it will get updated in the init.
};

let conn_type = ConnectionType::TOR;

Check warning on line 67 in src/bin/makerd.rs

View check run for this annotation

Codecov / codecov/patch

src/bin/makerd.rs#L67

Added line #L67 was not covered by tests

#[cfg(feature = "tor")]
{
if conn_type == ConnectionType::TOR {
Expand Down
13 changes: 4 additions & 9 deletions src/bin/taker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use clap::Parser;
use coinswap::{
taker::{error::TakerError, SwapParams, Taker, TakerBehavior},
utill::{parse_proxy_auth, setup_taker_logger, ConnectionType},
utill::{parse_proxy_auth, setup_taker_logger, ConnectionType, REQUIRED_CONFIRMS},
wallet::{Destination, RPCConfig, SendAmount},
};
use log::LevelFilter;
Expand All @@ -14,9 +14,6 @@
#[clap(version = option_env ! ("CARGO_PKG_VERSION").unwrap_or("unknown"),
author = option_env ! ("CARGO_PKG_AUTHORS").unwrap_or(""))]
struct Cli {
/// Optional Connection Network Type
#[clap(long, default_value = "clearnet",short= 'c', possible_values = &["tor","clearnet"])]
connection_type: String,
/// Optional DNS data directory. Default value : "~/.coinswap/taker"
#[clap(long, short = 'd')]
data_directory: Option<PathBuf>,
Expand Down Expand Up @@ -54,9 +51,6 @@
/// Sets the transaction count.
#[clap(name = "tx_count", default_value = "3")]
pub tx_count: u32,
/// Sets the required on-chain confirmations.
#[clap(name = "required_confirms", default_value = "1000")]
pub required_confirms: u64,
/// List of sub commands to process various endpoints of taker cli app.
#[clap(subcommand)]
command: Commands,
Expand Down Expand Up @@ -101,7 +95,8 @@
let args = Cli::parse();

let rpc_network = bitcoin::Network::from_str(&args.bitcoin_network).unwrap();
let connection_type = ConnectionType::from_str(&args.connection_type)?;

let connection_type = ConnectionType::TOR;

Check warning on line 99 in src/bin/taker.rs

View check run for this annotation

Codecov / codecov/patch

src/bin/taker.rs#L99

Added line #L99 was not covered by tests

let rpc_config = RPCConfig {
url: args.rpc,
Expand All @@ -114,7 +109,7 @@
send_amount: Amount::from_sat(args.send_amount),
maker_count: args.maker_count,
tx_count: args.tx_count,
required_confirms: args.required_confirms,
required_confirms: REQUIRED_CONFIRMS,
};

let mut taker = Taker::init(
Expand Down
79 changes: 70 additions & 9 deletions src/maker/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ use crate::{
messages::{FidelityProof, ReqContractSigsForSender},
Hash160,
},
utill::{get_maker_dir, redeemscript_to_scriptpubkey, ConnectionType},
utill::{
get_maker_dir, redeemscript_to_scriptpubkey, ConnectionType, HEART_BEAT_INTERVAL,
REQUIRED_CONFIRMS,
},
wallet::{RPCConfig, SwapCoin, WalletSwapCoin},
};
use bitcoin::{
Expand Down Expand Up @@ -46,9 +49,60 @@ use crate::{

use super::{config::MakerConfig, error::MakerError};

use crate::maker::server::{
HEART_BEAT_INTERVAL_SECS, MIN_CONTRACT_REACTION_TIME, REQUIRED_CONFIRMS,
};
/// Interval for health checks on a stable RPC connection with bitcoind.
pub const RPC_PING_INTERVAL: Duration = Duration::from_secs(60);

// Currently we don't refresh address at DNS. The Maker only post it once at startup.
// If the address record gets deleted, or the DNS gets blasted, the Maker won't know.
// TODO: Make the maker repost their address to DNS once a day in spawned thread.
// pub const DIRECTORY_SERVERS_REFRESH_INTERVAL_SECS: u64 = Duartion::from_days(1); // Once a day.

/// Maker triggers the recovery mechanism, if Taker is idle for more than 300 secs.
pub const IDLE_CONNECTION_TIMEOUT: Duration = Duration::from_secs(300);

/// The minimum difference in locktime (in blocks) between the incoming and outgoing swaps.
///
/// This value specifies the reaction time, in blocks, available to a Maker
/// to claim the refund transaction in case of recovery.
///
/// According to [BOLT #2](https://github.com/lightning/bolts/blob/aa5207aeaa32d841353dd2df3ce725a4046d528d/02-peer-protocol.md?plain=1#L1798),
/// the estimated minimum `cltv_expiry_delta` is 18 blocks.
/// To enhance safety, the default value is set to 20 blocks.
pub const MIN_CONTRACT_REACTION_TIME: u16 = 20;

/// # Fee Parameters for Coinswap
///
/// These parameters define the fees charged by Makers in a coinswap transaction.
///
/// TODO: These parameters are currently hardcoded. Consider making them configurable for Makers in the future.
///p
/// - `BASE_FEE`: A fixed base fee charged by the Maker for providing its services
/// - `AMOUNT_RELATIVE_FEE_PCT`: A percentage fee based on the swap amount.
/// - `TIME_RELATIVE_FEE_PCT`: A percentage fee based on the refund locktime (duration the Maker must wait for a refund).
///
/// The coinswap fee increases with both the swap amount and the refund locktime.
/// Refer to `REFUND_LOCKTIME` and `REFUND_LOCKTIME_STEP` in `taker::api.rs` for related parameters.
///
/// ### Fee Calculation
/// The total fee for a swap is calculated as:
/// `total_fee = base_fee + (swap_amount * amount_relative_fee_pct) / 100 + (swap_amount * refund_locktime * time_relative_fee_pct) / 100`
///
/// ### Example (Default Values)
/// For a swap amount of 100,000 sats and a refund locktime of 20 blocks:
/// - `base_fee` = 1,000 sats
/// - `amount_relative_fee` = (100,000 * 2.5) / 100 = 2,500 sats
/// - `time_relative_fee` = (100,000 * 20 * 0.1) / 100 = 2,000 sats
/// - `total_fee` = 5,500 sats (5.5%)
///
/// Fee rates are designed to asymptotically approach 5% of the swap amount as the swap amount increases..
pub const BASE_FEE: u64 = 1000;
pub const AMOUNT_RELATIVE_FEE_PCT: f64 = 2.50;
pub const TIME_RELATIVE_FEE_PCT: f64 = 0.10;

/// Minimum Coinswap amount; makers will not accept amounts below this.
pub const MIN_SWAP_AMOUNT: u64 = 100000;

// What's the use of RefundLocktimeStep?

/// Used to configure the maker for testing purposes.
#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -278,7 +332,7 @@ impl Maker {
// check that the new locktime is sufficently short enough compared to the
// locktime in the provided funding tx
let locktime = read_contract_locktime(&funding_info.contract_redeemscript)?;
if locktime - message.next_locktime < MIN_CONTRACT_REACTION_TIME {
if locktime - message.refund_locktime < MIN_CONTRACT_REACTION_TIME {
return Err(MakerError::General(
"Next hop locktime too close to current hop locktime",
));
Expand All @@ -298,7 +352,7 @@ impl Maker {
)
.map_err(WalletError::Rpc)?
{
if txout.confirmations < (REQUIRED_CONFIRMS as u32) {
if txout.confirmations < REQUIRED_CONFIRMS {
return Err(MakerError::General(
"funding tx not confirmed to required depth",
));
Expand Down Expand Up @@ -525,7 +579,7 @@ pub fn check_for_broadcasted_contracts(maker: Arc<Maker>) -> Result<(), MakerErr
}
} // All locks are cleared here.

std::thread::sleep(Duration::from_secs(HEART_BEAT_INTERVAL_SECS));
std::thread::sleep(HEART_BEAT_INTERVAL);
}

Ok(())
Expand All @@ -537,6 +591,13 @@ pub fn check_for_broadcasted_contracts(maker: Arc<Maker>) -> Result<(), MakerErr
/// Broadcast the contract transactions and claim funds via timelock.
pub fn check_for_idle_states(maker: Arc<Maker>) -> Result<(), MakerError> {
let mut bad_ip = Vec::new();

let conn_timeout = if cfg!(feature = "integration-test") {
Duration::from_secs(60)
} else {
IDLE_CONNECTION_TIMEOUT
};

loop {
if maker.shutdown.load(Relaxed) {
break;
Expand All @@ -558,7 +619,7 @@ pub fn check_for_idle_states(maker: Arc<Maker>) -> Result<(), MakerError> {
ip,
no_response_since
);
if no_response_since > std::time::Duration::from_secs(60) {
if no_response_since > conn_timeout {
log::error!(
"[{}] Potential Dropped Connection from {}",
maker.config.port,
Expand Down Expand Up @@ -610,7 +671,7 @@ pub fn check_for_idle_states(maker: Arc<Maker>) -> Result<(), MakerError> {
}
} // All locks are cleared here

std::thread::sleep(Duration::from_secs(HEART_BEAT_INTERVAL_SECS));
std::thread::sleep(HEART_BEAT_INTERVAL);
}

Ok(())
Expand Down
Loading
Loading