From 1ba7263278ad1e7058d422bb1fe2e93c1cfe9da3 Mon Sep 17 00:00:00 2001 From: neoz666 Date: Sun, 4 Jan 2026 00:05:16 +0530 Subject: [PATCH 1/2] Segregation of Incoming and Outgoing Contracts in Taproot Swap Signed-off-by: neoz666 --- src/taker/api2.rs | 68 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/src/taker/api2.rs b/src/taker/api2.rs index a619f39d..41626e18 100644 --- a/src/taker/api2.rs +++ b/src/taker/api2.rs @@ -109,6 +109,8 @@ struct OngoingSwapState { // Private key handover: store maker outgoing contract private keys (indexed by maker position) // Each maker hands over their outgoing contract private key after sweeping their incoming contract pub maker_outgoing_privkeys: Vec>, + // Here storing maker contract transaction IDs for reporting (indexed by maker position) + pub maker_contract_txs: Vec>, } impl Default for OngoingSwapState { @@ -166,6 +168,7 @@ impl Default for OngoingSwapState { swap_id: None, }, maker_outgoing_privkeys: Vec::new(), + maker_contract_txs: Vec::new(), } } } @@ -580,12 +583,54 @@ impl Taker { println!(" Transaction Details"); println!("────────────────────────────────────────────────────────────────────────────────\x1b[0m"); - // In V2 taproot, we have one outgoing contract tx - let outgoing_txid = swap_state.outgoing_contract.contract_tx.compute_txid(); - println!( - "\x1b[1;37mOutgoing Contract :\x1b[0m \x1b[2m{}\x1b[0m", - outgoing_txid - ); + // Outgoing contracts section + + println!("\n\x1b[1;37mOutgoing Contracts:\x1b[0m"); + // Taker's outgoing contract (sent to first maker) + let taker_outgoing_txid = swap_state.outgoing_contract.contract_tx.compute_txid(); + println!(" \x1b[1;33mTaker:\x1b[0m"); + println!(" ← \x1b[2m{}\x1b[0m → ", taker_outgoing_txid); + let mut all_outgoing_txid = vec![vec![taker_outgoing_txid.to_string()]]; + // Each maker's outgoing contracts + for (maker_index, maker_txs) in swap_state.maker_contract_txs.iter().enumerate() { + if !maker_txs.is_empty() { + println!(" \x1b[1;33mMaker {}:\x1b[0m", maker_index + 1); + all_outgoing_txid.push( + maker_txs + .iter() + .map(|txid| txid.to_string()) + .collect::>() + .clone(), + ); + for txid in maker_txs.iter() { + println!(" ← \x1b[2m{}\x1b[0m → ", txid); + } + } + } + + // Incoming contracts section + + println!("\n\x1b[1;37mIncoming Contracts:\x1b[0m"); + // First maker receives taker's outgoing + println!(" \x1b[1;33mMaker 1:\x1b[0m"); + println!(" → \x1b[2m{}\x1b[0m ← ", taker_outgoing_txid); + if swap_state.maker_contract_txs.len() > 1 { + // For more than a single maker, the outgoing txn of maker at index `i` is the incoming txn of maker at index `i+1` + for maker_index in 0..(swap_state.maker_contract_txs.len() - 1) { + if let Some(maker_txs) = swap_state.maker_contract_txs.get(maker_index) { + if !maker_txs.is_empty() { + if let Some(txid) = maker_txs.first() { + println!(" \x1b[1;33mMaker {}:\x1b[0m", maker_index + 2); + println!(" → \x1b[2m{}\x1b[0m ← ", txid); + } + } + } + } + } + // Taker receives last maker's outgoing + let taker_incoming_txid = swap_state.incoming_contract.contract_tx.compute_txid(); + println!(" \x1b[1;33mTaker:\x1b[0m"); + println!(" → \x1b[2m{}\x1b[0m ← ", taker_incoming_txid); println!("\n\x1b[1;36m────────────────────────────────────────────────────────────────────────────────"); println!(" Fee Information"); @@ -661,7 +706,9 @@ impl Taker { .collect::>(); // For V2, we have a single funding tx (the outgoing contract) - let funding_txids_by_hop = vec![vec![outgoing_txid.to_string()]]; + let funding_txids_by_hop = all_outgoing_txid; + let total_funding_txs = funding_txids_by_hop.len(); + println!("funding_txids_by_hop: {:?}", funding_txids_by_hop); let report = SwapReport { swap_id: swap_state.id.clone(), @@ -671,7 +718,7 @@ impl Taker { total_output_amount, makers_count: swap_state.swap_params.maker_count, maker_addresses, - total_funding_txs: 1, + total_funding_txs, funding_txids_by_hop, total_fee, total_maker_fees, @@ -829,6 +876,7 @@ impl Taker { // Initialize storage for maker private keys received during handover let chosen_makers_count = self.ongoing_swap_state.chosen_makers.len(); self.ongoing_swap_state.maker_outgoing_privkeys = vec![None; chosen_makers_count]; + self.ongoing_swap_state.maker_contract_txs = vec![Vec::new(); chosen_makers_count]; Ok(()) } @@ -1101,6 +1149,8 @@ impl Taker { match response { Ok(MakerToTakerMessage::SenderContractFromMaker(incoming_contract)) => { + self.ongoing_swap_state.maker_contract_txs[0] = + incoming_contract.contract_txs.clone(); self.forward_contracts_and_coordinate_sweep(incoming_contract)?; } _ => { @@ -1174,6 +1224,8 @@ impl Taker { match maker_response { Ok(MakerToTakerMessage::SenderContractFromMaker(maker_contract)) => { + self.ongoing_swap_state.maker_contract_txs[maker_index] = + maker_contract.contract_txs.clone(); #[cfg(feature = "integration-test")] { if self.behavior == TakerBehavior::CloseAtSendersContractFromMaker { From c765e1e545eb68d75968a2cfd513a1baea455e88 Mon Sep 17 00:00:00 2001 From: neoz666 Date: Sun, 4 Jan 2026 00:30:08 +0530 Subject: [PATCH 2/2] Timerelative fee is now dynamic, amountrelative fee corrected, added serialize to swapreport Signed-off-by: neoz666 --- src/taker/api2.rs | 45 +++++++++++++++++++++++---------------------- src/wallet/ffi.rs | 5 +++-- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/taker/api2.rs b/src/taker/api2.rs index 41626e18..393505dc 100644 --- a/src/taker/api2.rs +++ b/src/taker/api2.rs @@ -642,37 +642,40 @@ impl Taker { // Collect maker fee information for V2 let mut maker_fee_info = Vec::new(); let mut total_maker_fees = 0u64; + let mut temp_target_amount = swap_state.swap_params.send_amount.to_sat(); for (maker_index, maker) in swap_state.chosen_makers.iter().enumerate() { - let maker_fee = calculate_coinswap_fee( - swap_state.swap_params.send_amount.to_sat(), - 0, // timelock not used for fee display in report - maker.offer.base_fee, - maker.offer.amount_relative_fee_pct, - maker.offer.time_relative_fee_pct, - ); + let maker_refund_locktime = REFUND_LOCKTIME + + REFUND_LOCKTIME_STEP + * (swap_state.swap_params.maker_count - maker_index - 1) as u16; + let base_fee = maker.offer.base_fee as f64; + let amount_rel_fee = + (maker.offer.amount_relative_fee_pct * temp_target_amount as f64) / 100.0; + let time_rel_fee = (maker.offer.time_relative_fee_pct + * maker_refund_locktime as f64 + * temp_target_amount as f64) + / 100.0; println!("\n\x1b[1;33mMaker {}:\x1b[0m", maker_index + 1); println!(" Address : {}", maker.address); - println!(" Base Fee : {}", maker.offer.base_fee); - println!( - " Amount Relative Fee : {:.2}%", - maker.offer.amount_relative_fee_pct - ); - println!(" Total Fee : {} sats", maker_fee); + println!(" Base Fee : {base_fee}"); + println!(" Amount Relative Fee : {amount_rel_fee:.2}"); + println!(" Time Relative Fee : {time_rel_fee:.2}"); + + let total_maker_fee = base_fee + amount_rel_fee + time_rel_fee; + println!(" Total Fee : {total_maker_fee:.2} sats"); maker_fee_info.push(MakerFeeInfo { maker_index, maker_address: maker.address.to_string(), - base_fee: maker.offer.base_fee as f64, - amount_relative_fee: (maker.offer.amount_relative_fee_pct - * swap_state.swap_params.send_amount.to_sat() as f64) - / 100.0, - time_relative_fee: 0.0, // Simplified for report - total_fee: maker_fee as f64, + base_fee, + amount_relative_fee: amount_rel_fee, + time_relative_fee: time_rel_fee, + total_fee: total_maker_fee, }); - total_maker_fees += maker_fee; + temp_target_amount = temp_target_amount.saturating_sub(total_maker_fee as u64); + total_maker_fees += total_maker_fee as u64; } let mining_fee = total_fee.saturating_sub(total_maker_fees); @@ -708,7 +711,6 @@ impl Taker { // For V2, we have a single funding tx (the outgoing contract) let funding_txids_by_hop = all_outgoing_txid; let total_funding_txs = funding_txids_by_hop.len(); - println!("funding_txids_by_hop: {:?}", funding_txids_by_hop); let report = SwapReport { swap_id: swap_state.id.clone(), @@ -731,7 +733,6 @@ impl Taker { output_swap_utxos, output_change_utxos, }; - Ok(report) } diff --git a/src/wallet/ffi.rs b/src/wallet/ffi.rs index 96876285..2d79dac6 100644 --- a/src/wallet/ffi.rs +++ b/src/wallet/ffi.rs @@ -19,13 +19,14 @@ use crate::{ }; use bitcoin::{Address, Amount, OutPoint, Txid}; use bitcoind::bitcoincore_rpc::{json::ListTransactionResult, RpcApi}; +use serde::Serialize; use std::{ path::{Path, PathBuf}, str::FromStr, }; /// Information about individual maker fees in a swap -#[derive(Debug)] +#[derive(Debug, Serialize)] pub struct MakerFeeInfo { /// Index of maker in the swap route pub maker_index: usize, @@ -42,7 +43,7 @@ pub struct MakerFeeInfo { } /// Complete swap report containing all swap information -#[derive(Debug)] +#[derive(Debug, Serialize)] pub struct SwapReport { /// Unique swap ID pub swap_id: String,