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(watchtower): fix watchtower taker-side restart bug #1908

Merged
merged 61 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from 59 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
6402adf
fix watcher taker-side bug after restart
caglaryucekaya Jul 11, 2023
7759ebc
Merge branch 'dev' of github.com:KomodoPlatform/atomicDEX-API into bu…
caglaryucekaya Jul 11, 2023
2be4266
order swap events after taker restart
caglaryucekaya Jul 12, 2023
17b1837
improve tests for taker restart
caglaryucekaya Jul 13, 2023
9f35e5c
improve taker restart after watcher refund test
caglaryucekaya Jul 14, 2023
fda5261
add append_event function for TakerSwap
caglaryucekaya Jul 14, 2023
5f28226
Merge branch 'dev' of github.com:KomodoPlatform/atomicDEX-API into bu…
caglaryucekaya Jul 16, 2023
159c964
check watcher payments for unsuccessfully finished swaps
caglaryucekaya Jul 18, 2023
b3fc0e1
add test case for taker restart after watcher spending maker payment
caglaryucekaya Jul 18, 2023
e177b54
add TakerPaymentRefundedByWatcher event and a test case
caglaryucekaya Jul 18, 2023
31dc710
fix a test case
caglaryucekaya Jul 18, 2023
3508dcd
add new test case taker restart after watcher refund
caglaryucekaya Jul 18, 2023
2904071
add WatcherRefundNotFound event, a test case for it, and fix bugs tests
caglaryucekaya Jul 18, 2023
51443c9
move watcher payment checks out of the saved events loop
caglaryucekaya Jul 19, 2023
2e5e883
improve check_watcher_payments function
caglaryucekaya Jul 19, 2023
81d9e94
add only TakerPaymentRefundedByWatcher at restart after watcher refund
caglaryucekaya Jul 19, 2023
b87cb60
add MakerPaymentSpendtByWatcher event and adapt relevant test cases
caglaryucekaya Jul 20, 2023
07559bd
minor fixes
caglaryucekaya Jul 20, 2023
fcc4c4e
ignore test_two_watchers_spend_maker_payment_eth_erc20
caglaryucekaya Jul 20, 2023
5d50639
fix test_watcher_waits_for_taker_utxo
caglaryucekaya Jul 20, 2023
105e67e
add debug logs to swap_watcher
caglaryucekaya Jul 20, 2023
0514d5c
fix a bug in swap kick starting conditions
caglaryucekaya Jul 20, 2023
9ebd7e5
reduce duplicate code in watcher taker restart tests
caglaryucekaya Jul 20, 2023
f891298
reduce duplication in watcher taker restart tests
caglaryucekaya Jul 20, 2023
b0ffd0d
validate maker payment spend and taker payment refund on taker restart
caglaryucekaya Jul 28, 2023
6749e64
add test for watcher refund validation
caglaryucekaya Jul 30, 2023
955f67b
add test for validate watcher spend
caglaryucekaya Jul 30, 2023
2192e88
add taker payment refund validation for eth and erc20
caglaryucekaya Aug 1, 2023
4dd5459
validate maker payment spend validation on taker restart for eth
caglaryucekaya Aug 4, 2023
f15afa1
activate watchtowers for UTXO
caglaryucekaya Aug 5, 2023
07b8947
change structure of check_watcher_payments
caglaryucekaya Aug 7, 2023
47c2257
kickstart only unfinished swaps
caglaryucekaya Aug 8, 2023
7fbc2af
build a single success scenario on taker restart
caglaryucekaya Aug 10, 2023
bfe9289
add error checks for taker payment refund validations
caglaryucekaya Aug 10, 2023
484c132
add error checks for maker payment spend validations
caglaryucekaya Aug 10, 2023
49a305f
small fixes and improvements
caglaryucekaya Aug 10, 2023
14d12d1
fix success events check in check_my_swap_status
caglaryucekaya Aug 11, 2023
a6f24f4
check only unfinished swaps for watcher payments
caglaryucekaya Aug 13, 2023
627d796
use commands to check watcher payments at taker restart
caglaryucekaya Aug 14, 2023
a689a62
minor improvements
caglaryucekaya Aug 15, 2023
563b9d9
check time before checking watcher refund on restart
caglaryucekaya Aug 15, 2023
87c66e7
remove the WatcherSpendOrRefundNotFound event
caglaryucekaya Aug 16, 2023
d78b503
Merge branch 'dev' of github.com:KomodoPlatform/atomicDEX-API into bu…
caglaryucekaya Aug 16, 2023
052f9a4
minor improvements on get_watcher_payments function
caglaryucekaya Aug 17, 2023
08a0e42
minor fixes
caglaryucekaya Aug 17, 2023
ee7b9b2
move taker restart related functionality to swap watcher module
caglaryucekaya Aug 17, 2023
cc7ddf7
remove duplicate code
caglaryucekaya Aug 17, 2023
6d319eb
combine validate taker payment refund and maker payment spend functions
caglaryucekaya Aug 17, 2023
1c1d93e
move taker restart functionality to a separate module
caglaryucekaya Aug 18, 2023
9888dc5
remove unnecessary validation functions in taker restart module
caglaryucekaya Aug 18, 2023
c83eb59
add TakerPaymentRefundedByWatcher to TAKER_ERROR_EVENTS, fix taker_sw…
shamardy Aug 22, 2023
60a303a
fix recreate swap tests
shamardy Aug 22, 2023
e15fe63
Merge branch 'dev' of github.com:KomodoPlatform/atomicDEX-API into bu…
shamardy Aug 23, 2023
70d0213
fix trade_test_with_maker_segwit, trade_test_with_taker_segwit
shamardy Aug 23, 2023
7df06c1
fix taker_swap_should_not_kick_start_if_finished_during_waiting_for_f…
shamardy Aug 24, 2023
d1d09b4
Merge remote-tracking branch 'origin/dev' into bugfix-watchtower
shamardy Aug 24, 2023
1eb1d48
fix is_recoverable for taker
shamardy Aug 29, 2023
7ab33a2
Merge remote-tracking branch 'origin/dev' into bugfix-watchtower
shamardy Sep 11, 2023
edf9ba1
Merge remote-tracking branch 'origin/dev' into bugfix-watchtower
shamardy Sep 18, 2023
90853f8
Merge remote-tracking branch 'origin/dev' into bugfix-watchtower
shamardy Oct 25, 2023
10cd6dc
* convert body bytes to string in single_response error
shamardy Oct 25, 2023
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
239 changes: 238 additions & 1 deletion mm2src/coins/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
use super::eth::Action::{Call, Create};
use crate::lp_price::get_base_price_in_rel;
use crate::nft::nft_structs::{ContractType, ConvertChain, TransactionNftDetails, WithdrawErc1155, WithdrawErc721};
use crate::{ValidateWatcherSpendInput, WatcherSpendType};
use async_trait::async_trait;
use bitcrypto::{keccak256, ripemd160, sha256};
use bitcrypto::{dhash160, keccak256, ripemd160, sha256};
use common::custom_futures::repeatable::{Ready, Retry, RetryOnError};
use common::custom_futures::timeout::FutureTimerExt;
use common::executor::{abortable_queue::AbortableQueue, AbortableSystem, AbortedError, Timer};
Expand Down Expand Up @@ -1469,6 +1470,242 @@ impl WatcherOps for EthCoin {
// 1.Validate if taker fee is old
}

fn taker_validates_payment_spend_or_refund(&self, input: ValidateWatcherSpendInput) -> ValidatePaymentFut<()> {
let watcher_reward = try_f!(input
.watcher_reward
.clone()
.ok_or_else(|| ValidatePaymentError::WatcherRewardError("Watcher reward not found".to_string())));
let expected_reward_amount = try_f!(wei_from_big_decimal(&watcher_reward.amount, self.decimals));

let expected_swap_contract_address = try_f!(input
.swap_contract_address
.try_to_address()
.map_to_mm(ValidatePaymentError::InvalidParameter));

let unsigned: UnverifiedTransaction = try_f!(rlp::decode(&input.payment_tx));
let tx =
try_f!(SignedEthTx::new(unsigned)
.map_to_mm(|err| ValidatePaymentError::TxDeserializationError(err.to_string())));

let selfi = self.clone();
let swap_id = selfi.etomic_swap_id(input.time_lock, &input.secret_hash);
let decimals = self.decimals;
let secret_hash = if input.secret_hash.len() == 32 {
ripemd160(&input.secret_hash).to_vec()
} else {
input.secret_hash.to_vec()
};
let maker_addr =
try_f!(addr_from_raw_pubkey(&input.maker_pub).map_to_mm(ValidatePaymentError::InvalidParameter));

let trade_amount = try_f!(wei_from_big_decimal(&(input.amount), decimals));
let fut = async move {
match tx.action {
Call(contract_address) => {
if contract_address != expected_swap_contract_address {
return MmError::err(ValidatePaymentError::WrongPaymentTx(format!(
"Transaction {:?} was sent to wrong address, expected {:?}",
contract_address, expected_swap_contract_address,
)));
}
},
Create => {
return MmError::err(ValidatePaymentError::WrongPaymentTx(
"Tx action must be Call, found Create instead".to_string(),
));
},
};

let actual_status = selfi
.payment_status(expected_swap_contract_address, Token::FixedBytes(swap_id.clone()))
.compat()
.await
.map_to_mm(ValidatePaymentError::Transport)?;
let expected_status = match input.spend_type {
WatcherSpendType::MakerPaymentSpend => U256::from(PaymentState::Spent as u8),
WatcherSpendType::TakerPaymentRefund => U256::from(PaymentState::Refunded as u8),
};
if actual_status != expected_status {
return MmError::err(ValidatePaymentError::UnexpectedPaymentState(format!(
"Payment state is not {}, got {}",
expected_status, actual_status
)));
}

let function_name = match input.spend_type {
WatcherSpendType::MakerPaymentSpend => get_function_name("receiverSpend", true),
WatcherSpendType::TakerPaymentRefund => get_function_name("senderRefund", true),
};
let function = SWAP_CONTRACT
.function(&function_name)
.map_to_mm(|err| ValidatePaymentError::InternalError(err.to_string()))?;

let decoded = decode_contract_call(function, &tx.data)
.map_to_mm(|err| ValidatePaymentError::TxDeserializationError(err.to_string()))?;

let swap_id_input = get_function_input_data(&decoded, function, 0)
.map_to_mm(ValidatePaymentError::TxDeserializationError)?;
if swap_id_input != Token::FixedBytes(swap_id.clone()) {
return MmError::err(ValidatePaymentError::WrongPaymentTx(format!(
"Transaction invalid swap_id arg {:?}, expected {:?}",
swap_id_input,
Token::FixedBytes(swap_id.clone())
)));
}

let hash_input = match input.spend_type {
WatcherSpendType::MakerPaymentSpend => {
let secret_input = get_function_input_data(&decoded, function, 2)
.map_to_mm(ValidatePaymentError::TxDeserializationError)?
.into_fixed_bytes()
.ok_or_else(|| {
ValidatePaymentError::WrongPaymentTx("Invalid type for secret hash argument".to_string())
})?;
dhash160(&secret_input).to_vec()
},
WatcherSpendType::TakerPaymentRefund => get_function_input_data(&decoded, function, 2)
.map_to_mm(ValidatePaymentError::TxDeserializationError)?
.into_fixed_bytes()
.ok_or_else(|| {
ValidatePaymentError::WrongPaymentTx("Invalid type for secret argument".to_string())
})?,
};
if hash_input != secret_hash {
return MmError::err(ValidatePaymentError::WrongPaymentTx(format!(
"Transaction secret or secret_hash arg {:?} is invalid, expected {:?}",
hash_input,
Token::FixedBytes(secret_hash),
)));
}

let sender_input = get_function_input_data(&decoded, function, 4)
.map_to_mm(ValidatePaymentError::TxDeserializationError)?;
let expected_sender = match input.spend_type {
WatcherSpendType::MakerPaymentSpend => maker_addr,
WatcherSpendType::TakerPaymentRefund => selfi.my_address,
};
if sender_input != Token::Address(expected_sender) {
return MmError::err(ValidatePaymentError::WrongPaymentTx(format!(
"Transaction sender arg {:?} is invalid, expected {:?}",
sender_input,
Token::Address(expected_sender)
)));
}

let receiver_input = get_function_input_data(&decoded, function, 5)
.map_to_mm(ValidatePaymentError::TxDeserializationError)?;
let expected_receiver = match input.spend_type {
WatcherSpendType::MakerPaymentSpend => selfi.my_address,
WatcherSpendType::TakerPaymentRefund => maker_addr,
};
if receiver_input != Token::Address(expected_receiver) {
return MmError::err(ValidatePaymentError::WrongPaymentTx(format!(
"Transaction receiver arg {:?} is invalid, expected {:?}",
receiver_input,
Token::Address(expected_receiver)
)));
}

let reward_target_input = get_function_input_data(&decoded, function, 6)
.map_to_mm(ValidatePaymentError::TxDeserializationError)?;
if reward_target_input != Token::Uint(U256::from(watcher_reward.reward_target as u8)) {
return MmError::err(ValidatePaymentError::WrongPaymentTx(format!(
"Transaction reward target arg {:?} is invalid, expected {:?}",
reward_target_input,
Token::Uint(U256::from(watcher_reward.reward_target as u8))
)));
}

let contract_reward_input = get_function_input_data(&decoded, function, 7)
.map_to_mm(ValidatePaymentError::TxDeserializationError)?;
if contract_reward_input != Token::Bool(watcher_reward.send_contract_reward_on_spend) {
return MmError::err(ValidatePaymentError::WrongPaymentTx(format!(
"Transaction sends contract reward on spend arg {:?} is invalid, expected {:?}",
contract_reward_input,
Token::Bool(watcher_reward.send_contract_reward_on_spend)
)));
}

let reward_amount_input = get_function_input_data(&decoded, function, 8)
.map_to_mm(ValidatePaymentError::TxDeserializationError)?;
if reward_amount_input != Token::Uint(expected_reward_amount) {
return MmError::err(ValidatePaymentError::WrongPaymentTx(format!(
"Transaction watcher reward amount arg {:?} is invalid, expected {:?}",
reward_amount_input,
Token::Uint(expected_reward_amount)
)));
}

if tx.value != U256::zero() {
return MmError::err(ValidatePaymentError::WrongPaymentTx(format!(
"Transaction value arg {:?} is invalid, expected 0",
tx.value
)));
}

match &selfi.coin_type {
EthCoinType::Eth => {
let amount_input = get_function_input_data(&decoded, function, 1)
.map_to_mm(ValidatePaymentError::TxDeserializationError)?;
let total_amount = match input.spend_type {
WatcherSpendType::MakerPaymentSpend => {
if let RewardTarget::None = watcher_reward.reward_target {
trade_amount
} else {
trade_amount + expected_reward_amount
}
},
WatcherSpendType::TakerPaymentRefund => trade_amount + expected_reward_amount,
};
if amount_input != Token::Uint(total_amount) {
return MmError::err(ValidatePaymentError::WrongPaymentTx(format!(
"Transaction amount arg {:?} is invalid, expected {:?}",
amount_input,
Token::Uint(total_amount),
)));
}

let token_address_input = get_function_input_data(&decoded, function, 3)
.map_to_mm(ValidatePaymentError::TxDeserializationError)?;
if token_address_input != Token::Address(Address::default()) {
return MmError::err(ValidatePaymentError::WrongPaymentTx(format!(
"Transaction token address arg {:?} is invalid, expected {:?}",
token_address_input,
Token::Address(Address::default()),
)));
}
},
EthCoinType::Erc20 {
platform: _,
token_addr,
} => {
let amount_input = get_function_input_data(&decoded, function, 1)
.map_to_mm(ValidatePaymentError::TxDeserializationError)?;
if amount_input != Token::Uint(trade_amount) {
return MmError::err(ValidatePaymentError::WrongPaymentTx(format!(
"Transaction amount arg {:?} is invalid, expected {:?}",
amount_input,
Token::Uint(trade_amount),
)));
}

let token_address_input = get_function_input_data(&decoded, function, 3)
.map_to_mm(ValidatePaymentError::TxDeserializationError)?;
if token_address_input != Token::Address(*token_addr) {
return MmError::err(ValidatePaymentError::WrongPaymentTx(format!(
"Transaction token address arg {:?} is invalid, expected {:?}",
token_address_input,
Token::Address(*token_addr),
)));
}
},
}

Ok(())
};
Box::new(fut.boxed().compat())
}

fn watcher_validate_taker_payment(&self, input: WatcherValidatePaymentInput) -> ValidatePaymentFut<()> {
let unsigned: UnverifiedTransaction = try_f!(rlp::decode(&input.payment_tx));
let tx =
Expand Down
11 changes: 8 additions & 3 deletions mm2src/coins/lightning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ use crate::{BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, CoinFutSpawner, C
TradePreimageFut, TradePreimageResult, TradePreimageValue, Transaction, TransactionEnum, TransactionErr,
TransactionFut, TransactionResult, TxMarshalingErr, UnexpectedDerivationMethod, UtxoStandardCoin,
ValidateAddressResult, ValidateFeeArgs, ValidateInstructionsErr, ValidateOtherPubKeyErr,
ValidatePaymentError, ValidatePaymentFut, ValidatePaymentInput, VerificationError, VerificationResult,
WaitForHTLCTxSpendArgs, WatcherOps, WatcherReward, WatcherRewardError, WatcherSearchForSwapTxSpendInput,
WatcherValidatePaymentInput, WatcherValidateTakerFeeInput, WithdrawError, WithdrawFut, WithdrawRequest};
ValidatePaymentError, ValidatePaymentFut, ValidatePaymentInput, ValidateWatcherSpendInput,
VerificationError, VerificationResult, WaitForHTLCTxSpendArgs, WatcherOps, WatcherReward,
WatcherRewardError, WatcherSearchForSwapTxSpendInput, WatcherValidatePaymentInput,
WatcherValidateTakerFeeInput, WithdrawError, WithdrawFut, WithdrawRequest};
use async_trait::async_trait;
use bitcoin::bech32::ToBase32;
use bitcoin::hashes::Hash;
Expand Down Expand Up @@ -995,6 +996,10 @@ impl WatcherOps for LightningCoin {
unimplemented!();
}

fn taker_validates_payment_spend_or_refund(&self, _input: ValidateWatcherSpendInput) -> ValidatePaymentFut<()> {
unimplemented!()
}

async fn watcher_search_for_swap_tx_spend(
&self,
_input: WatcherSearchForSwapTxSpendInput<'_>,
Expand Down
20 changes: 20 additions & 0 deletions mm2src/coins/lp_coins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,24 @@ pub struct WatcherValidatePaymentInput {
pub maker_coin: MmCoinEnum,
}

#[derive(Clone)]
pub enum WatcherSpendType {
TakerPaymentRefund,
MakerPaymentSpend,
}

#[derive(Clone)]
pub struct ValidateWatcherSpendInput {
pub payment_tx: Vec<u8>,
pub maker_pub: Vec<u8>,
pub swap_contract_address: Option<BytesJson>,
pub time_lock: u32,
pub secret_hash: Vec<u8>,
pub amount: BigDecimal,
pub watcher_reward: Option<WatcherReward>,
pub spend_type: WatcherSpendType,
}

#[derive(Clone, Debug)]
pub struct ValidatePaymentInput {
pub payment_tx: Vec<u8>,
Expand Down Expand Up @@ -995,6 +1013,8 @@ pub trait WatcherOps {

fn watcher_validate_taker_payment(&self, _input: WatcherValidatePaymentInput) -> ValidatePaymentFut<()>;

fn taker_validates_payment_spend_or_refund(&self, _input: ValidateWatcherSpendInput) -> ValidatePaymentFut<()>;

async fn watcher_search_for_swap_tx_spend(
&self,
input: WatcherSearchForSwapTxSpendInput<'_>,
Expand Down
8 changes: 6 additions & 2 deletions mm2src/coins/qrc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use crate::{BalanceError, BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, Coi
TradePreimageValue, TransactionDetails, TransactionEnum, TransactionErr, TransactionFut,
TransactionResult, TransactionType, TxMarshalingErr, UnexpectedDerivationMethod, ValidateAddressResult,
ValidateFeeArgs, ValidateInstructionsErr, ValidateOtherPubKeyErr, ValidatePaymentFut,
ValidatePaymentInput, VerificationResult, WaitForHTLCTxSpendArgs, WatcherOps, WatcherReward,
WatcherRewardError, WatcherSearchForSwapTxSpendInput, WatcherValidatePaymentInput,
ValidatePaymentInput, ValidateWatcherSpendInput, VerificationResult, WaitForHTLCTxSpendArgs, WatcherOps,
WatcherReward, WatcherRewardError, WatcherSearchForSwapTxSpendInput, WatcherValidatePaymentInput,
WatcherValidateTakerFeeInput, WithdrawError, WithdrawFee, WithdrawFut, WithdrawRequest, WithdrawResult};
use async_trait::async_trait;
use bitcrypto::{dhash160, sha256};
Expand Down Expand Up @@ -1126,6 +1126,10 @@ impl WatcherOps for Qrc20Coin {
unimplemented!();
}

fn taker_validates_payment_spend_or_refund(&self, _input: ValidateWatcherSpendInput) -> ValidatePaymentFut<()> {
unimplemented!()
}

async fn watcher_search_for_swap_tx_spend(
&self,
_input: WatcherSearchForSwapTxSpendInput<'_>,
Expand Down
6 changes: 5 additions & 1 deletion mm2src/coins/solana.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{BalanceError, BalanceFut, CheckIfMyPaymentSentArgs, CoinFutSpawner,
TransactionDetails, TransactionFut, TransactionResult, TransactionType, TxMarshalingErr,
UnexpectedDerivationMethod, ValidateAddressResult, ValidateFeeArgs, ValidateInstructionsErr,
ValidateOtherPubKeyErr, ValidatePaymentError, ValidatePaymentFut, ValidatePaymentInput,
VerificationResult, WaitForHTLCTxSpendArgs, WatcherReward, WatcherRewardError,
ValidateWatcherSpendInput, VerificationResult, WaitForHTLCTxSpendArgs, WatcherReward, WatcherRewardError,
WatcherSearchForSwapTxSpendInput, WatcherValidatePaymentInput, WatcherValidateTakerFeeInput,
WithdrawError, WithdrawFut, WithdrawRequest, WithdrawResult};
use async_trait::async_trait;
Expand Down Expand Up @@ -647,6 +647,10 @@ impl WatcherOps for SolanaCoin {
unimplemented!();
}

fn taker_validates_payment_spend_or_refund(&self, _input: ValidateWatcherSpendInput) -> ValidatePaymentFut<()> {
unimplemented!()
}

async fn watcher_search_for_swap_tx_spend(
&self,
input: WatcherSearchForSwapTxSpendInput<'_>,
Expand Down
10 changes: 7 additions & 3 deletions mm2src/coins/solana/spl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ use crate::{BalanceFut, CheckIfMyPaymentSentArgs, CoinFutSpawner, ConfirmPayment
TradePreimageResult, TradePreimageValue, TransactionDetails, TransactionFut, TransactionResult,
TransactionType, TxMarshalingErr, UnexpectedDerivationMethod, ValidateAddressResult, ValidateFeeArgs,
ValidateInstructionsErr, ValidateOtherPubKeyErr, ValidatePaymentError, ValidatePaymentFut,
ValidatePaymentInput, VerificationResult, WaitForHTLCTxSpendArgs, WatcherReward, WatcherRewardError,
WatcherSearchForSwapTxSpendInput, WatcherValidatePaymentInput, WatcherValidateTakerFeeInput,
WithdrawError, WithdrawFut, WithdrawRequest, WithdrawResult};
ValidatePaymentInput, ValidateWatcherSpendInput, VerificationResult, WaitForHTLCTxSpendArgs,
WatcherReward, WatcherRewardError, WatcherSearchForSwapTxSpendInput, WatcherValidatePaymentInput,
WatcherValidateTakerFeeInput, WithdrawError, WithdrawFut, WithdrawRequest, WithdrawResult};
use async_trait::async_trait;
use bincode::serialize;
use common::executor::{abortable_queue::AbortableQueue, AbortableSystem, AbortedError};
Expand Down Expand Up @@ -468,6 +468,10 @@ impl WatcherOps for SplToken {
unimplemented!();
}

fn taker_validates_payment_spend_or_refund(&self, _input: ValidateWatcherSpendInput) -> ValidatePaymentFut<()> {
unimplemented!()
}

async fn watcher_search_for_swap_tx_spend(
&self,
input: WatcherSearchForSwapTxSpendInput<'_>,
Expand Down
Loading
Loading