1+ use super :: error:: TakerError ;
12use crate :: {
23 protocol:: {
34 contract2:: {
@@ -52,7 +53,20 @@ use std::{
5253 collections:: HashSet , net:: TcpStream , path:: PathBuf , sync:: mpsc, thread, time:: Duration ,
5354} ;
5455
55- use super :: error:: TakerError ;
56+ /// Represents different behaviors taker can have during the swap.
57+ /// Used for testing various possible scenarios that can happen during a swap.
58+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
59+ #[ cfg( feature = "integration-test" ) ]
60+ pub enum TakerBehavior {
61+ /// Normal behaviour
62+ Normal ,
63+ /// Close connection after receiving AckResponse message from the maker. (no outgoing/incoming contract created)
64+ CloseAtAckResponse ,
65+ /// Close connection after sending SendersContract (outgoing contract created)
66+ CloseAtSendersContract ,
67+ /// Close connection after receiving SendersContract from maker (outgoing contract created).
68+ CloseAtSendersContractFromMaker ,
69+ }
5670
5771/// Represents how a taproot contract output was spent
5872#[ derive( Debug , Clone ) ]
@@ -201,6 +215,8 @@ pub struct Taker {
201215 ongoing_swap_state : OngoingSwapState ,
202216 watch_service : WatchService ,
203217 offer_sync_handle : OfferSyncHandle ,
218+ #[ cfg( feature = "integration-test" ) ]
219+ behavior : TakerBehavior ,
204220}
205221
206222impl Drop for Taker {
@@ -219,6 +235,7 @@ impl Drop for Taker {
219235
220236impl Taker {
221237 /// Initialize a new Taker instance
238+ #[ allow( clippy:: too_many_arguments) ]
222239 pub fn init (
223240 data_dir : Option < PathBuf > ,
224241 wallet_file_name : Option < String > ,
@@ -227,6 +244,7 @@ impl Taker {
227244 tor_auth_password : Option < String > ,
228245 zmq_addr : String ,
229246 password : Option < String > ,
247+ #[ cfg( feature = "integration-test" ) ] behavior : TakerBehavior ,
230248 ) -> Result < Taker , TakerError > {
231249 let data_dir = data_dir. unwrap_or_else ( get_taker_dir) ;
232250
@@ -302,6 +320,8 @@ impl Taker {
302320 ongoing_swap_state : OngoingSwapState :: default ( ) ,
303321 watch_service,
304322 offer_sync_handle,
323+ #[ cfg( feature = "integration-test" ) ]
324+ behavior,
305325 } )
306326 }
307327
@@ -348,6 +368,16 @@ impl Taker {
348368 self . choose_makers_for_swap ( swap_params) ?;
349369 self . setup_contract_keys_and_scripts ( ) ?;
350370
371+ #[ cfg( feature = "integration-test" ) ]
372+ {
373+ if self . behavior == TakerBehavior :: CloseAtAckResponse {
374+ log:: error!(
375+ "Dropping Swap Process after receiving Ack Response message from maker"
376+ ) ;
377+ return Err ( TakerError :: General ( "Taker Dropping after receiving AckResponse message from maker. (Test behavior)" . to_string ( ) , ) ) ;
378+ }
379+ }
380+
351381 let outgoing_signed_contract_transactions = self . create_outgoing_contract_transactions ( ) ?;
352382 let tx = match outgoing_signed_contract_transactions. first ( ) {
353383 Some ( tx) => tx,
@@ -380,7 +410,6 @@ impl Taker {
380410 for tx in & outgoing_signed_contract_transactions {
381411 self . wallet . wait_for_tx_confirmation ( tx. compute_txid ( ) ) ?;
382412 }
383-
384413 match self
385414 . negotiate_with_makers_and_coordinate_sweep ( & outgoing_signed_contract_transactions)
386415 {
@@ -391,6 +420,7 @@ impl Taker {
391420
392421 // Store swap state before reset for report generation
393422 let prereset_swapstate = self . ongoing_swap_state . clone ( ) ;
423+ self . ongoing_swap_state = OngoingSwapState :: default ( ) ;
394424
395425 // Sync wallet and generate report
396426 self . wallet . sync_and_save ( ) ?;
@@ -763,19 +793,20 @@ impl Taker {
763793 } ;
764794
765795 let msg = TakerToMakerMessage :: SwapDetails ( swap_details) ;
766- let response = self . send_to_maker_and_get_response ( & suitable_maker. address , msg) ? ;
796+ let response = self . send_to_maker_and_get_response ( & suitable_maker. address , msg) ;
767797 match response {
768- MakerToTakerMessage :: AckResponse ( AckResponse :: Ack ) => {
798+ Ok ( MakerToTakerMessage :: AckResponse ( AckResponse :: Ack ) ) => {
769799 log:: info!( "Received AckResponse from maker: {:?}" , suitable_maker) ;
770800 self . ongoing_swap_state
771801 . chosen_makers
772802 . push ( suitable_maker. clone ( ) ) ;
773803 }
774- MakerToTakerMessage :: AckResponse ( AckResponse :: Nack ) => {
804+ Ok ( MakerToTakerMessage :: AckResponse ( AckResponse :: Nack ) ) => {
775805 log:: warn!( "Maker {:?} did not accept the swap request" , suitable_maker) ;
776806 continue ;
777807 }
778808 _ => {
809+ self . offerbook . add_bad_maker ( suitable_maker) ;
779810 log:: warn!( "Received unexpected message from maker: {:?}" , response) ;
780811 continue ;
781812 }
@@ -872,6 +903,10 @@ impl Taker {
872903
873904 suitable_makers
874905 }
906+ /// Get all the bad makers
907+ pub fn get_bad_makers ( & self ) -> Vec < OfferAndAddress > {
908+ self . offerbook . get_bad_makers ( & MakerProtocol :: Taproot )
909+ }
875910
876911 /// Setup contract keys and scripts for the swap
877912 fn setup_contract_keys_and_scripts ( & mut self ) -> Result < ( ) , TakerError > {
@@ -1052,13 +1087,24 @@ impl Taker {
10521087 } ;
10531088
10541089 let msg = TakerToMakerMessage :: SendersContract ( senders_contract. clone ( ) ) ;
1055- let response = self . send_to_maker_and_get_response ( & first_maker. address , msg) ?;
1090+ let response = self . send_to_maker_and_get_response ( & first_maker. address , msg) ;
1091+ #[ cfg( feature = "integration-test" ) ]
1092+ {
1093+ if self . behavior == TakerBehavior :: CloseAtSendersContract {
1094+ log:: error!( "Dropping connection after sending SendersContract to Maker" ) ;
1095+ return Err ( TakerError :: General (
1096+ "Taker dropping of after sending Senders Contract to Maker (test behavior) "
1097+ . to_string ( ) ,
1098+ ) ) ;
1099+ }
1100+ }
10561101
10571102 match response {
1058- MakerToTakerMessage :: SenderContractFromMaker ( incoming_contract) => {
1103+ Ok ( MakerToTakerMessage :: SenderContractFromMaker ( incoming_contract) ) => {
10591104 self . forward_contracts_and_coordinate_sweep ( incoming_contract) ?;
10601105 }
10611106 _ => {
1107+ self . offerbook . add_bad_maker ( first_maker) ;
10621108 return Err ( TakerError :: General (
10631109 "Unexpected response from first maker" . to_string ( ) ,
10641110 ) ) ;
@@ -1124,11 +1170,21 @@ impl Taker {
11241170 } ;
11251171
11261172 let forward_msg = TakerToMakerMessage :: SendersContract ( forward_contract) ;
1127- let maker_response =
1128- self . send_to_maker_and_get_response ( & maker. address , forward_msg) ?;
1173+ let maker_response = self . send_to_maker_and_get_response ( & maker. address , forward_msg) ;
11291174
11301175 match maker_response {
1131- MakerToTakerMessage :: SenderContractFromMaker ( maker_contract) => {
1176+ Ok ( MakerToTakerMessage :: SenderContractFromMaker ( maker_contract) ) => {
1177+ #[ cfg( feature = "integration-test" ) ]
1178+ {
1179+ if self . behavior == TakerBehavior :: CloseAtSendersContractFromMaker {
1180+ log:: error!(
1181+ "Dropping connection after receiving Sender Contract from Maker"
1182+ ) ;
1183+ return Err ( TakerError :: General (
1184+ "Taker dropping of after receiving Senders Contract from Maker (test behavior) " . to_string ( ) , ) ) ;
1185+ }
1186+ }
1187+
11321188 if maker_index == maker_count - 1 {
11331189 // This is the last maker - store its response as final contract data
11341190 self . store_final_contract_data ( & maker_contract) ?;
@@ -1140,6 +1196,7 @@ impl Taker {
11401196 }
11411197 }
11421198 _ => {
1199+ self . offerbook . add_bad_maker ( maker) ;
11431200 return Err ( TakerError :: General ( format ! (
11441201 "Unexpected response from maker {}" ,
11451202 maker_index
@@ -1272,15 +1329,28 @@ impl Taker {
12721329 } ) ;
12731330
12741331 // Send to maker and get their outgoing key in response
1275- let response = self . send_to_maker_and_get_response ( & maker_address, privkey_msg) ?;
1276-
1332+ let response = self . send_to_maker_and_get_response ( & maker_address, privkey_msg) ;
12771333 // remove taker's outgoing swapcoin since we've handed over the key
12781334 if maker_index == 0 {
12791335 let outgoing_txid = self
12801336 . ongoing_swap_state
12811337 . outgoing_contract
12821338 . contract_tx
12831339 . compute_txid ( ) ;
1340+ for ( vout, _) in self
1341+ . ongoing_swap_state
1342+ . outgoing_contract
1343+ . contract_tx
1344+ . output
1345+ . iter ( )
1346+ . enumerate ( )
1347+ {
1348+ let outpoint = OutPoint {
1349+ txid : outgoing_txid,
1350+ vout : vout as u32 ,
1351+ } ;
1352+ self . watch_service . unwatch ( outpoint) ;
1353+ }
12841354 self . wallet . remove_outgoing_swapcoin_v2 ( & outgoing_txid) ;
12851355 log:: info!(
12861356 "Removed taker's outgoing swapcoin {} after sending PrivateKeyHandover" ,
@@ -1291,7 +1361,7 @@ impl Taker {
12911361
12921362 // Extract maker's outgoing key from response
12931363 match response {
1294- MakerToTakerMessage :: PrivateKeyHandover ( maker_privkey_handover) => {
1364+ Ok ( MakerToTakerMessage :: PrivateKeyHandover ( maker_privkey_handover) ) => {
12951365 let maker_outgoing_privkey = maker_privkey_handover. secret_key ;
12961366
12971367 log:: info!( " [Maker {}] Received outgoing private key" , maker_index) ;
@@ -1301,6 +1371,8 @@ impl Taker {
13011371 Some ( maker_outgoing_privkey) ;
13021372 }
13031373 _ => {
1374+ self . offerbook
1375+ . add_bad_maker ( & self . ongoing_swap_state . chosen_makers [ maker_index] ) ;
13041376 return Err ( TakerError :: General ( format ! (
13051377 "Unexpected response from maker {}: expected PrivateKeyHandover" ,
13061378 maker_index
@@ -1512,6 +1584,21 @@ impl Taker {
15121584 incoming_contract_txid
15131585 ) ;
15141586
1587+ for ( vout, _) in self
1588+ . ongoing_swap_state
1589+ . incoming_contract
1590+ . contract_tx
1591+ . output
1592+ . iter ( )
1593+ . enumerate ( )
1594+ {
1595+ let outpoint = OutPoint {
1596+ txid : incoming_contract_txid,
1597+ vout : vout as u32 ,
1598+ } ;
1599+ self . watch_service . unwatch ( outpoint) ;
1600+ }
1601+
15151602 // Remove the incoming swapcoin since we've successfully swept it
15161603 self . wallet
15171604 . remove_incoming_swapcoin_v2 ( & incoming_contract_txid) ;
0 commit comments