Skip to content

Commit

Permalink
fix tests for no dex fee for swaps v1, add tests for no dex fee for s…
Browse files Browse the repository at this point in the history
…wap v2
  • Loading branch information
dimxy committed Aug 26, 2024
1 parent b0fabcf commit f6cc684
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 11 deletions.
3 changes: 2 additions & 1 deletion mm2src/coins/lp_coins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3732,7 +3732,8 @@ impl DexFee {
) -> DexFee {
if let Some(taker_pubkey) = taker_pubkey {
if !taker_coin.is_privacy() && taker_coin.dex_pubkey() == taker_pubkey {
return DexFee::NoFee; // do not change dex fee for the dex pubkey as the taker
// Only updated taker nodes will use this feature (no need to activate by version)
return DexFee::NoFee; // no dex fee if the taker is the dex pubkey
}
}
// calc dex fee
Expand Down
50 changes: 49 additions & 1 deletion mm2src/coins/utxo/utxo_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,29 @@ async fn gen_taker_payment_spend_preimage<T: UtxoCommonOps + SwapOps>(
},
&DexFee::Standard(..) => {}, // We do not add maker output here, only the single dex fee output (signed with SIGHASH_SINGLE) is created by the taker or validated by the maker
}

#[cfg(feature = "run-docker-tests")]
{
match *args.dex_fee {
DexFee::NoFee => {
if args.taker_pub.to_vec().as_slice() != coin.dex_pubkey() {
panic!("taker pubkey must be equal to dex pubkey for DexFee::NoFee");
}
assert_eq!(outputs.len(), 1); // only the maker output
},
DexFee::Standard(..) => {
if args.taker_pub.to_vec().as_slice() == coin.dex_pubkey() {
panic!("taker pubkey must NOT be equal to dex pubkey for DexFee::Standard");
}
assert_eq!(outputs.len(), 1); // only the dex fee output (maker output will be added later)
},
DexFee::WithBurn { .. } => {
if args.taker_pub.to_vec().as_slice() == coin.dex_pubkey() {
panic!("taker pubkey must NOT be equal to dex pubkey for DexFee::WithBurn");
}
assert_eq!(outputs.len(), 3); // dex fee, burn and maker outputs
},
}
}

p2sh_spending_tx_preimage(
Expand Down Expand Up @@ -1405,6 +1428,8 @@ pub async fn sign_and_broadcast_taker_payment_spend<T: UtxoCommonOps>(
payment_input.amount = payment_output.value;
signer.consensus_branch_id = coin.as_ref().conf.consensus_branch_id;

// Add the maker output if DexFee is Standard (when the single dex fee output is signed with SIGHASH_SINGLE)
// (in other DexFee options the make output is added in gen_taker_payment_spend_preimage fn)
if let DexFee::Standard(dex_fee) = gen_args.dex_fee {
let dex_fee_sat = try_tx_s!(sat_from_big_decimal(&dex_fee.to_decimal(), coin.as_ref().decimals));

Expand Down Expand Up @@ -1471,16 +1496,39 @@ where
{
let outputs = try_tx_fus!(generate_taker_fee_tx_outputs(&coin, &dex_fee,));

#[cfg(feature = "run-docker-tests")]
{
let taker_pub = coin.derive_htlc_pubkey(&[]);
match dex_fee {
DexFee::NoFee => {
panic!("should not send dex fee for DexFee::NoFee");
},
DexFee::Standard(..) => {
if taker_pub.as_slice() == coin.dex_pubkey() {
panic!("taker pubkey must NOT be equal to dex pubkey for DexFee::Standard");
}
assert_eq!(outputs.len(), 1);
},
DexFee::WithBurn { .. } => {
if taker_pub.as_slice() == coin.dex_pubkey() {
panic!("taker pubkey must NOT be equal to dex pubkey for DexFee::WithBurn");
}
assert_eq!(outputs.len(), 2);
},
}
}

send_outputs_from_my_address(coin, outputs)
}

// Create dex fee (burn fee) outputs
fn generate_taker_fee_tx_outputs<T>(coin: &T, dex_fee: &DexFee) -> Result<Vec<TransactionOutput>, String>
where
T: UtxoCommonOps + SwapOps,
{
match dex_fee {
DexFee::NoFee => Ok(vec![]),
// TODO: for DexFee::Standard return an error like 'dex fee must contain burn amount' when nodes upgraded to this code
// TODO: return an error for DexFee::Standard like 'dex fee must contain burn amount' when nodes upgraded to this code
DexFee::Standard(_) | DexFee::WithBurn { .. } => {
let dex_address = address_from_raw_pubkey(
coin.dex_pubkey(),
Expand Down
4 changes: 2 additions & 2 deletions mm2src/mm2_main/src/lp_swap/maker_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::lp_swap::{NegotiationDataMsgVersion, SwapMsgExt};
use coins::lp_price::fetch_swap_coins_price;
use coins::swap_features::SwapFeature;
use coins::SWAP_PROTOCOL_VERSION;
#[cfg(feature = "for-tests")]
#[cfg(feature = "run-docker-tests")]
use coins::TEST_DEX_FEE_ADDR_RAW_PUBKEY;
use coins::{CanRefundHtlc, CheckIfMyPaymentSentArgs, ConfirmPaymentInput, DexFee, FeeApproxStage, FoundSwapTxSpend,
MmCoin, MmCoinEnum, PaymentInstructionArgs, PaymentInstructions, PaymentInstructionsErr,
Expand Down Expand Up @@ -487,7 +487,7 @@ impl MakerSwap {
}

async fn start(&self) -> Result<(Option<MakerSwapCommand>, Vec<MakerSwapEvent>), String> {
#[cfg(feature = "for-tests")]
#[cfg(feature = "run-docker-tests")]
if let Ok(env_pubkey) = std::env::var("TEST_DEX_FEE_ADDR_RAW_PUBKEY") {
unsafe {
TEST_DEX_FEE_ADDR_RAW_PUBKEY = Some(hex::decode(env_pubkey).expect("valid hex"));
Expand Down
16 changes: 16 additions & 0 deletions mm2src/mm2_main/src/lp_swap/maker_swap_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use crate::lp_swap::{broadcast_swap_v2_msg_every, check_balance_for_maker_swap,
use crate::lp_swap::{swap_v2_pb::*, NO_REFUND_FEE};
use async_trait::async_trait;
use bitcrypto::{dhash160, sha256};
#[cfg(feature = "run-docker-tests")]
use coins::TEST_DEX_FEE_ADDR_RAW_PUBKEY;
use coins::{CanRefundHtlc, ConfirmPaymentInput, DexFee, FeeApproxStage, FundingTxSpend, GenTakerFundingSpendArgs,
GenTakerPaymentSpendArgs, MakerCoinSwapOpsV2, MmCoin, ParseCoinAssocTypes, RefundMakerPaymentArgs,
RefundPaymentArgs, SearchForFundingSpendErr, SendMakerPaymentArgs, SwapTxTypeWithSecretHash,
Expand Down Expand Up @@ -464,6 +466,13 @@ impl<MakerCoin: MmCoin + MakerCoinSwapOpsV2, TakerCoin: MmCoin + TakerCoinSwapOp
mut repr: MakerSwapDbRepr,
recreate_ctx: Self::RecreateCtx,
) -> Result<(RestoredMachine<Self>, Box<dyn RestoredState<StateMachine = Self>>), Self::RecreateError> {
#[cfg(feature = "run-docker-tests")]
if let Ok(env_pubkey) = std::env::var("TEST_DEX_FEE_ADDR_RAW_PUBKEY") {
unsafe {
TEST_DEX_FEE_ADDR_RAW_PUBKEY = Some(hex::decode(env_pubkey).expect("valid hex"));
}
}

if repr.events.is_empty() {
return MmError::err(SwapRecreateError::ReprEventsEmpty);
}
Expand Down Expand Up @@ -795,6 +804,13 @@ impl<MakerCoin: MmCoin + MakerCoinSwapOpsV2, TakerCoin: MmCoin + TakerCoinSwapOp
type StateMachine = MakerSwapStateMachine<MakerCoin, TakerCoin>;

async fn on_changed(self: Box<Self>, state_machine: &mut Self::StateMachine) -> StateResult<Self::StateMachine> {
#[cfg(feature = "run-docker-tests")]
if let Ok(env_pubkey) = std::env::var("TEST_DEX_FEE_ADDR_RAW_PUBKEY") {
unsafe {
TEST_DEX_FEE_ADDR_RAW_PUBKEY = Some(hex::decode(env_pubkey).expect("valid hex"));
}
}

let maker_coin_start_block = match state_machine.maker_coin.current_block().compat().await {
Ok(b) => b,
Err(e) => {
Expand Down
4 changes: 2 additions & 2 deletions mm2src/mm2_main/src/lp_swap/taker_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::lp_swap::{NegotiationDataMsgVersion, SwapMsgExt};
use coins::lp_price::fetch_swap_coins_price;
use coins::swap_features::SwapFeature;
use coins::SWAP_PROTOCOL_VERSION;
#[cfg(feature = "for-tests")]
#[cfg(feature = "run-docker-tests")]
use coins::TEST_DEX_FEE_ADDR_RAW_PUBKEY;
use coins::{lp_coinfind, CanRefundHtlc, CheckIfMyPaymentSentArgs, ConfirmPaymentInput, DexFee, FeeApproxStage,
FoundSwapTxSpend, MmCoin, MmCoinEnum, PaymentInstructionArgs, PaymentInstructions, PaymentInstructionsErr,
Expand Down Expand Up @@ -1005,7 +1005,7 @@ impl TakerSwap {
}

async fn start(&self) -> Result<(Option<TakerSwapCommand>, Vec<TakerSwapEvent>), String> {
#[cfg(feature = "for-tests")]
#[cfg(feature = "run-docker-tests")]
if let Ok(env_pubkey) = std::env::var("TEST_DEX_FEE_ADDR_RAW_PUBKEY") {
unsafe {
TEST_DEX_FEE_ADDR_RAW_PUBKEY = Some(hex::decode(env_pubkey).expect("valid hex"));
Expand Down
16 changes: 16 additions & 0 deletions mm2src/mm2_main/src/lp_swap/taker_swap_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use crate::lp_swap::{broadcast_swap_v2_msg_every, check_balance_for_taker_swap,
use crate::lp_swap::{swap_v2_pb::*, NO_REFUND_FEE};
use async_trait::async_trait;
use bitcrypto::{dhash160, sha256};
#[cfg(feature = "run-docker-tests")]
use coins::TEST_DEX_FEE_ADDR_RAW_PUBKEY;
use coins::{CanRefundHtlc, ConfirmPaymentInput, DexFee, FeeApproxStage, GenTakerFundingSpendArgs,
GenTakerPaymentSpendArgs, MakerCoinSwapOpsV2, MmCoin, ParseCoinAssocTypes, RefundFundingSecretArgs,
RefundPaymentArgs, SendTakerFundingArgs, SpendMakerPaymentArgs, SwapTxTypeWithSecretHash,
Expand Down Expand Up @@ -494,6 +496,13 @@ impl<MakerCoin: MmCoin + MakerCoinSwapOpsV2, TakerCoin: MmCoin + TakerCoinSwapOp
mut repr: TakerSwapDbRepr,
recreate_ctx: Self::RecreateCtx,
) -> Result<(RestoredMachine<Self>, Box<dyn RestoredState<StateMachine = Self>>), Self::RecreateError> {
#[cfg(feature = "run-docker-tests")]
if let Ok(env_pubkey) = std::env::var("TEST_DEX_FEE_ADDR_RAW_PUBKEY") {
unsafe {
TEST_DEX_FEE_ADDR_RAW_PUBKEY = Some(hex::decode(env_pubkey).expect("valid hex"));
}
}

if repr.events.is_empty() {
return MmError::err(SwapRecreateError::ReprEventsEmpty);
}
Expand Down Expand Up @@ -910,6 +919,13 @@ impl<MakerCoin: MmCoin + MakerCoinSwapOpsV2, TakerCoin: MmCoin + TakerCoinSwapOp
type StateMachine = TakerSwapStateMachine<MakerCoin, TakerCoin>;

async fn on_changed(self: Box<Self>, state_machine: &mut Self::StateMachine) -> StateResult<Self::StateMachine> {
#[cfg(feature = "run-docker-tests")]
if let Ok(env_pubkey) = std::env::var("TEST_DEX_FEE_ADDR_RAW_PUBKEY") {
unsafe {
TEST_DEX_FEE_ADDR_RAW_PUBKEY = Some(hex::decode(env_pubkey).expect("valid hex"));
}
}

let maker_coin_start_block = match state_machine.maker_coin.current_block().compat().await {
Ok(b) => b,
Err(e) => {
Expand Down
47 changes: 42 additions & 5 deletions mm2src/mm2_main/tests/docker_tests/swap_proto_v2_tests.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::{generate_utxo_coin_with_random_privkey, MYCOIN, MYCOIN1};
use crate::{generate_utxo_coin_with_random_privkey, MYCOIN, MYCOIN1, SET_DEX_PUBKEY_TO_ALICE};
use bitcrypto::dhash160;
use coins::utxo::UtxoCommonOps;
use coins::{ConfirmPaymentInput, DexFee, FundingTxSpend, GenTakerFundingSpendArgs, GenTakerPaymentSpendArgs,
MakerCoinSwapOpsV2, MarketCoinOps, ParseCoinAssocTypes, RefundFundingSecretArgs, RefundMakerPaymentArgs,
RefundPaymentArgs, SendMakerPaymentArgs, SendTakerFundingArgs, SwapTxTypeWithSecretHash,
TakerCoinSwapOpsV2, Transaction, ValidateMakerPaymentArgs, ValidateTakerFundingArgs};
use common::{block_on, now_sec};
use crypto::privkey::key_pair_from_secret;
use futures01::Future;
use mm2_number::MmNumber;
use mm2_test_helpers::for_tests::{active_swaps, check_recent_swaps, coins_needed_for_kickstart, disable_coin,
Expand Down Expand Up @@ -608,21 +609,53 @@ fn send_and_refund_maker_payment_taker_secret() {
}

#[test]
fn test_v2_swap_utxo_utxo() {
fn test_v2_swap_utxo_utxo() { test_v2_swap_utxo_utxo_impl(); }

// test a swap when taker is dex pubkey (no dex fee should be paid)
#[test]
fn test_v2_swap_utxo_utxo_dex_as_alice() {
SET_DEX_PUBKEY_TO_ALICE.set(true);
test_v2_swap_utxo_utxo_impl();
}

fn test_v2_swap_utxo_utxo_impl() {
let (_ctx, _, bob_priv_key) = generate_utxo_coin_with_random_privkey(MYCOIN, 1000.into());
let (_ctx, _, alice_priv_key) = generate_utxo_coin_with_random_privkey(MYCOIN1, 1000.into());
let coins = json!([mycoin_conf(1000), mycoin1_conf(1000)]);

let alice_pubkey_str = hex::encode(
key_pair_from_secret(alice_priv_key.as_ref())
.expect("valid test key pair")
.public()
.to_vec(),
);
let mut envs = vec![];
if SET_DEX_PUBKEY_TO_ALICE.get() {
envs.push(("TEST_DEX_FEE_ADDR_RAW_PUBKEY", alice_pubkey_str.as_str()));
}

let bob_conf = Mm2TestConf::seednode_trade_v2(&format!("0x{}", hex::encode(bob_priv_key)), &coins);
let mut mm_bob = MarketMakerIt::start(bob_conf.conf, bob_conf.rpc_password, None).unwrap();
let mut mm_bob = block_on(MarketMakerIt::start_with_envs(
bob_conf.conf,
bob_conf.rpc_password,
None,
&envs,
))
.unwrap();
let (_bob_dump_log, _bob_dump_dashboard) = mm_dump(&mm_bob.log_path);
log!("Bob log path: {}", mm_bob.log_path.display());

let alice_conf =
Mm2TestConf::light_node_trade_v2(&format!("0x{}", hex::encode(alice_priv_key)), &coins, &[&mm_bob
.ip
.to_string()]);
let mut mm_alice = MarketMakerIt::start(alice_conf.conf, alice_conf.rpc_password, None).unwrap();
let mut mm_alice = block_on(MarketMakerIt::start_with_envs(
alice_conf.conf,
alice_conf.rpc_password,
None,
&envs,
))
.unwrap();
let (_alice_dump_log, _alice_dump_dashboard) = mm_dump(&mm_alice.log_path);
log!("Alice log path: {}", mm_alice.log_path.display());

Expand Down Expand Up @@ -670,7 +703,11 @@ fn test_v2_swap_utxo_utxo() {

let locked_alice = block_on(get_locked_amount(&mm_alice, MYCOIN1));
assert_eq!(locked_alice.coin, MYCOIN1);
let expected: MmNumberMultiRepr = MmNumber::from("778.00001").into();
let expected: MmNumberMultiRepr = if SET_DEX_PUBKEY_TO_ALICE.get() {
MmNumber::from("777.00001").into() // no dex fee if dex pubkey is alice
} else {
MmNumber::from("778.00001").into()
};
assert_eq!(locked_alice.locked_amount, expected);

// amount must unlocked after funding tx is sent
Expand Down

0 comments on commit f6cc684

Please sign in to comment.