#[macro_use] mod test_utils; use bitcoin::Amount; use bitcoin_test_utils::rpc_helpers::init_clients; use bitcoincore_rpc::RpcApi; use dlc_manager::contract::contract_input::ContractInput; use dlc_manager::manager::Manager; use dlc_manager::{ channel::Channel, contract::Contract, Blockchain, CachedContractSignerProvider, Oracle, SimpleSigner, Storage, Wallet, }; use dlc_manager::{ChannelId, ContractId}; use dlc_messages::Message; use electrs_blockchain_provider::ElectrsBlockchainProvider; use lightning::util::ser::Writeable; use mocks::memory_storage_provider::MemoryStorage; use mocks::mock_oracle_provider::MockOracle; use mocks::mock_time::MockTime; use secp256k1_zkp::rand::{thread_rng, RngCore}; use secp256k1_zkp::EcdsaAdaptorSignature; use simple_wallet::SimpleWallet; use test_utils::{get_enum_test_params, TestParams}; use std::sync::mpsc::{sync_channel, Receiver, Sender}; use std::thread; use std::time::Duration; use std::{ collections::HashMap, sync::{ atomic::{AtomicBool, Ordering}, mpsc::channel, Arc, Mutex, }, }; use crate::test_utils::{refresh_wallet, EVENT_MATURITY}; type DlcParty = Arc< Mutex< Manager< Arc, Arc>>, Arc< CachedContractSignerProvider< Arc, Arc>>, SimpleSigner, >, >, Arc, Arc, Arc, Arc, Arc, SimpleSigner, >, >, >; fn get_established_channel_contract_id(dlc_party: &DlcParty, channel_id: &ChannelId) -> ContractId { let channel = dlc_party .lock() .unwrap() .get_store() .get_channel(channel_id) .unwrap() .unwrap(); if let Channel::Signed(s) = channel { return s.get_contract_id().expect("to have a contract id"); } panic!("Invalid channel state {:?}.", channel); } fn alter_adaptor_sig(input: &EcdsaAdaptorSignature) -> EcdsaAdaptorSignature { let mut copy = input.as_ref().to_vec(); let i = thread_rng().next_u32() as usize % secp256k1_zkp::ffi::ECDSA_ADAPTOR_SIGNATURE_LENGTH; copy[i] = copy[i].checked_add(1).unwrap_or(0); EcdsaAdaptorSignature::from_slice(©).expect("to be able to create an adaptor signature") } /// We wrap updating the state of the chain monitor and calling the /// `Manager::periodic_check` because the latter will only be aware of /// newly confirmed transactions if the former processes new blocks. fn periodic_check(dlc_party: DlcParty) { let dlc_manager = dlc_party.lock().unwrap(); dlc_manager.periodic_chain_monitor().unwrap(); dlc_manager.periodic_check(true).unwrap(); } #[derive(Eq, PartialEq, Clone)] enum TestPath { Close, BadAcceptBufferAdaptorSignature, BadSignBufferAdaptorSignature, SettleClose, BufferCheat, RenewedClose, SettleCheat, CollaborativeClose, SettleRenewSettle, SettleOfferTimeout, SettleAcceptTimeout, SettleConfirmTimeout, SettleReject, SettleRace, RenewOfferTimeout, RenewAcceptTimeout, RenewConfirmTimeout, RenewFinalizeTimeout, RenewReject, RenewRace, RenewEstablishedClose, CancelOffer, } #[test] #[ignore] fn channel_established_close_test() { channel_execution_test(get_enum_test_params(1, 1, None), TestPath::Close); } #[test] #[ignore] fn channel_bad_accept_buffer_adaptor_test() { channel_execution_test( get_enum_test_params(1, 1, None), TestPath::BadAcceptBufferAdaptorSignature, ); } #[test] #[ignore] fn channel_bad_sign_buffer_adaptor_test() { channel_execution_test( get_enum_test_params(1, 1, None), TestPath::BadSignBufferAdaptorSignature, ); } #[test] #[ignore] fn channel_settled_close_test() { channel_execution_test(get_enum_test_params(1, 1, None), TestPath::SettleClose); } #[test] #[ignore] fn channel_punish_buffer_test() { channel_execution_test(get_enum_test_params(1, 1, None), TestPath::BufferCheat); } #[test] #[ignore] fn channel_renew_close_test() { channel_execution_test(get_enum_test_params(1, 1, None), TestPath::RenewedClose); } #[test] #[ignore] fn channel_renew_established_close_test() { channel_execution_test( get_enum_test_params(1, 1, None), TestPath::RenewEstablishedClose, ); } #[test] #[ignore] fn channel_settle_cheat_test() { channel_execution_test(get_enum_test_params(1, 1, None), TestPath::SettleCheat); } #[test] #[ignore] fn channel_collaborative_close_test() { channel_execution_test( get_enum_test_params(1, 1, None), TestPath::CollaborativeClose, ); } #[test] #[ignore] fn channel_settle_renew_settle_test() { channel_execution_test( get_enum_test_params(1, 1, None), TestPath::SettleRenewSettle, ); } #[test] #[ignore] fn channel_settle_offer_timeout_test() { channel_execution_test( get_enum_test_params(1, 1, None), TestPath::SettleOfferTimeout, ); } #[test] #[ignore] fn channel_settle_accept_timeout_test() { channel_execution_test( get_enum_test_params(1, 1, None), TestPath::SettleAcceptTimeout, ); } #[test] #[ignore] fn channel_settle_confirm_timeout_test() { channel_execution_test( get_enum_test_params(1, 1, None), TestPath::SettleConfirmTimeout, ); } #[test] #[ignore] fn channel_settle_reject_test() { channel_execution_test(get_enum_test_params(1, 1, None), TestPath::SettleReject); } #[test] #[ignore] fn channel_settle_race_test() { channel_execution_test(get_enum_test_params(1, 1, None), TestPath::SettleRace); } #[test] #[ignore] fn channel_renew_offer_timeout_test() { channel_execution_test( get_enum_test_params(1, 1, None), TestPath::RenewOfferTimeout, ); } #[test] #[ignore] fn channel_renew_accept_timeout_test() { channel_execution_test( get_enum_test_params(1, 1, None), TestPath::RenewAcceptTimeout, ); } #[test] #[ignore] fn channel_renew_confirm_timeout_test() { channel_execution_test( get_enum_test_params(1, 1, None), TestPath::RenewConfirmTimeout, ); } #[test] #[ignore] fn channel_renew_finalize_timeout_test() { channel_execution_test( get_enum_test_params(1, 1, None), TestPath::RenewFinalizeTimeout, ); } #[test] #[ignore] fn channel_renew_reject_test() { channel_execution_test(get_enum_test_params(1, 1, None), TestPath::RenewReject); } #[test] #[ignore] fn channel_renew_race_test() { channel_execution_test(get_enum_test_params(1, 1, None), TestPath::RenewRace); } #[test] #[ignore] fn channel_offer_reject_test() { channel_execution_test(get_enum_test_params(1, 1, None), TestPath::CancelOffer); } fn channel_execution_test(test_params: TestParams, path: TestPath) { env_logger::init(); let (alice_send, bob_receive) = channel::>(); let (bob_send, alice_receive) = channel::>(); let (alice_sync_send, alice_sync_receive) = sync_channel::<()>(0); let (bob_sync_send, bob_sync_receive) = sync_channel::<()>(0); let (_, _, sink_rpc) = init_clients(); let mut alice_oracles = HashMap::with_capacity(1); let mut bob_oracles = HashMap::with_capacity(1); for oracle in test_params.oracles { let oracle = Arc::new(oracle); alice_oracles.insert(oracle.get_public_key(), Arc::clone(&oracle)); bob_oracles.insert(oracle.get_public_key(), Arc::clone(&oracle)); } let alice_store = Arc::new(mocks::memory_storage_provider::MemoryStorage::new()); let bob_store = Arc::new(mocks::memory_storage_provider::MemoryStorage::new()); let mock_time = Arc::new(mocks::mock_time::MockTime {}); mocks::mock_time::set_time((EVENT_MATURITY as u64) - 1); let electrs = Arc::new(ElectrsBlockchainProvider::new( "http://localhost:3004/".to_string(), bitcoin::Network::Regtest, )); let alice_wallet = Arc::new(SimpleWallet::new( electrs.clone(), alice_store.clone(), bitcoin::Network::Regtest, )); let bob_wallet = Arc::new(SimpleWallet::new( electrs.clone(), bob_store.clone(), bitcoin::Network::Regtest, )); let alice_fund_address = alice_wallet.get_new_address().unwrap(); let bob_fund_address = bob_wallet.get_new_address().unwrap(); sink_rpc .send_to_address( &alice_fund_address, Amount::from_btc(2.0).unwrap(), None, None, None, None, None, None, ) .unwrap(); sink_rpc .send_to_address( &bob_fund_address, Amount::from_btc(2.0).unwrap(), None, None, None, None, None, None, ) .unwrap(); let generate_blocks = |nb_blocks: u64| { let prev_blockchain_height = electrs.get_blockchain_height().unwrap(); let sink_address = sink_rpc .get_new_address(None, None) .expect("RPC Error") .assume_checked(); sink_rpc .generate_to_address(nb_blocks, &sink_address) .expect("RPC Error"); // Wait for electrs to have processed the new blocks let mut cur_blockchain_height = prev_blockchain_height; while cur_blockchain_height < prev_blockchain_height + nb_blocks { std::thread::sleep(std::time::Duration::from_millis(200)); cur_blockchain_height = electrs.get_blockchain_height().unwrap(); } }; generate_blocks(6); refresh_wallet(&alice_wallet, 200000000); refresh_wallet(&bob_wallet, 200000000); let alice_manager = Arc::new(Mutex::new( Manager::new( Arc::clone(&alice_wallet), Arc::clone(&alice_wallet), Arc::clone(&electrs), alice_store, alice_oracles, Arc::clone(&mock_time), Arc::clone(&electrs), ) .unwrap(), )); let alice_manager_loop = Arc::clone(&alice_manager); let alice_manager_send = Arc::clone(&alice_manager); let bob_manager = Arc::new(Mutex::new( Manager::new( Arc::clone(&bob_wallet), Arc::clone(&bob_wallet), Arc::clone(&electrs), Arc::clone(&bob_store), bob_oracles, Arc::clone(&mock_time), Arc::clone(&electrs), ) .unwrap(), )); let bob_manager_loop = Arc::clone(&bob_manager); let bob_manager_send = Arc::clone(&bob_manager); let alice_send_loop = alice_send.clone(); let bob_send_loop = bob_send.clone(); let alice_expect_error = Arc::new(AtomicBool::new(false)); let bob_expect_error = Arc::new(AtomicBool::new(false)); let alice_expect_error_loop = alice_expect_error.clone(); let bob_expect_error_loop = bob_expect_error.clone(); let path_copy = path.clone(); let msg_filter = move |msg| { if let TestPath::SettleAcceptTimeout = path_copy { if let Message::SettleConfirm(_) = msg { return None; } } if let TestPath::SettleConfirmTimeout = path_copy { if let Message::SettleFinalize(_) = msg { return None; } } if let TestPath::RenewAcceptTimeout = path_copy { if let Message::RenewConfirm(_) = msg { return None; } } if let TestPath::RenewConfirmTimeout = path_copy { if let Message::RenewFinalize(_) = msg { return None; } } Some(msg) }; let msg_filter_copy = msg_filter.clone(); let path_copy = path.clone(); let alter_sign = move |msg| match msg { Message::SignChannel(mut sign_channel) => { if path_copy == TestPath::BadSignBufferAdaptorSignature { sign_channel.buffer_adaptor_signature = alter_adaptor_sig(&sign_channel.buffer_adaptor_signature); } Some(Message::SignChannel(sign_channel)) } _ => msg_filter_copy(msg), }; let alice_handle = receive_loop!( alice_receive, alice_manager_loop, alice_send_loop, alice_expect_error_loop, alice_sync_send, msg_filter, |msg| msg ); let bob_handle = receive_loop!( bob_receive, bob_manager_loop, bob_send_loop, bob_expect_error_loop, bob_sync_send, alter_sign, |msg| msg ); let offer_msg = bob_manager_send .lock() .unwrap() .offer_channel( &test_params.contract_input, "0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166" .parse() .unwrap(), ) .expect("Send offer error"); let temporary_channel_id = offer_msg.temporary_channel_id; bob_send .send(Some(Message::OfferChannel(offer_msg))) .unwrap(); assert_channel_state!(bob_manager_send, temporary_channel_id, Offered); alice_sync_receive.recv().expect("Error synchronizing"); assert_channel_state!(alice_manager_send, temporary_channel_id, Offered); if let TestPath::CancelOffer = path { let (reject_msg, _) = alice_manager_send .lock() .unwrap() .reject_channel(&temporary_channel_id) .expect("Error rejecting contract offer"); assert_channel_state!(alice_manager_send, temporary_channel_id, Cancelled); alice_send.send(Some(Message::Reject(reject_msg))).unwrap(); bob_sync_receive.recv().expect("Error synchronizing"); assert_channel_state!(bob_manager_send, temporary_channel_id, Cancelled); return; } let (mut accept_msg, channel_id, contract_id, _) = alice_manager_send .lock() .unwrap() .accept_channel(&temporary_channel_id) .expect("Error accepting contract offer"); assert_channel_state!(alice_manager_send, channel_id, Accepted); match path { TestPath::BadAcceptBufferAdaptorSignature => { accept_msg.buffer_adaptor_signature = alter_adaptor_sig(&accept_msg.buffer_adaptor_signature); bob_expect_error.store(true, Ordering::Relaxed); alice_send .send(Some(Message::AcceptChannel(accept_msg))) .unwrap(); bob_sync_receive.recv().expect("Error synchronizing"); assert_channel_state!(bob_manager_send, temporary_channel_id, FailedAccept); } TestPath::BadSignBufferAdaptorSignature => { alice_expect_error.store(true, Ordering::Relaxed); alice_send .send(Some(Message::AcceptChannel(accept_msg))) .unwrap(); // Bob receives accept message bob_sync_receive.recv().expect("Error synchronizing"); // Alice receives sign message alice_sync_receive.recv().expect("Error synchronizing"); assert_channel_state!(alice_manager_send, channel_id, FailedSign); } _ => { alice_send .send(Some(Message::AcceptChannel(accept_msg))) .unwrap(); bob_sync_receive.recv().expect("Error synchronizing"); assert_channel_state!(bob_manager_send, channel_id, Signed, Established); alice_sync_receive.recv().expect("Error synchronizing"); assert_channel_state!(alice_manager_send, channel_id, Signed, Established); generate_blocks(6); mocks::mock_time::set_time((EVENT_MATURITY as u64) + 1); periodic_check(alice_manager_send.clone()); periodic_check(bob_manager_send.clone()); assert_contract_state!(alice_manager_send, contract_id, Confirmed); assert_contract_state!(bob_manager_send, contract_id, Confirmed); // Select the first one to close or refund randomly let (first, first_send, first_receive, second, second_send, second_receive) = if thread_rng().next_u32() % 2 == 0 { ( alice_manager_send, &alice_send, &alice_sync_receive, bob_manager_send, &bob_send, &bob_sync_receive, ) } else { ( bob_manager_send, &bob_send, &bob_sync_receive, alice_manager_send, &alice_send, &alice_sync_receive, ) }; match path { TestPath::Close => { close_established_channel(first, second, channel_id, &generate_blocks); } TestPath::CollaborativeClose => { collaborative_close( first, first_send, second, channel_id, second_receive, &generate_blocks, ); } TestPath::SettleOfferTimeout | TestPath::SettleAcceptTimeout | TestPath::SettleConfirmTimeout => { settle_timeout( first, first_send, first_receive, second, second_send, second_receive, channel_id, path, ); } TestPath::SettleReject => { settle_reject( first, first_send, first_receive, second, second_send, second_receive, channel_id, ); } TestPath::SettleRace => { settle_race( first, first_send, first_receive, second, second_send, second_receive, channel_id, ); } _ => { // Shuffle positions let (first, first_send, first_receive, second, second_send, second_receive) = if thread_rng().next_u32() % 2 == 0 { ( first, first_send, first_receive, second, second_send, second_receive, ) } else { ( second, second_send, second_receive, first, first_send, first_receive, ) }; first.lock().unwrap().get_store().save(); if let TestPath::RenewEstablishedClose = path { } else { settle_channel( first.clone(), first_send, first_receive, second.clone(), second_send, second_receive, channel_id, ); } match path { TestPath::SettleClose => { let closer = if thread_rng().next_u32() % 2 == 0 { first } else { second }; closer .lock() .unwrap() .force_close_channel(&channel_id) .expect("to be able to unilaterally close the channel."); } TestPath::BufferCheat => { cheat_punish(first, second, channel_id, &generate_blocks, true); } TestPath::RenewOfferTimeout | TestPath::RenewAcceptTimeout | TestPath::RenewConfirmTimeout => { renew_timeout( first, first_send, first_receive, second, second_send, second_receive, channel_id, &test_params.contract_input, path, &generate_blocks, ); } TestPath::RenewReject => { renew_reject( first, first_send, first_receive, second, second_send, second_receive, channel_id, &test_params.contract_input, ); } TestPath::RenewRace => { renew_race( first, first_send, first_receive, second, second_send, second_receive, channel_id, &test_params.contract_input, ); } TestPath::RenewedClose | TestPath::SettleCheat | TestPath::RenewEstablishedClose => { first.lock().unwrap().get_store().save(); let check_prev_contract_close = if let TestPath::RenewEstablishedClose = path { true } else { false }; renew_channel( first.clone(), first_send, first_receive, second.clone(), second_send, second_receive, channel_id, &test_params.contract_input, check_prev_contract_close, ); if let TestPath::RenewedClose = path { close_established_channel( first, second, channel_id, &generate_blocks, ); } else if let TestPath::SettleCheat = path { cheat_punish(first, second, channel_id, &generate_blocks, false); } } TestPath::SettleRenewSettle => { renew_channel( first.clone(), first_send, first_receive, second.clone(), second_send, second_receive, channel_id, &test_params.contract_input, false, ); settle_channel( first, first_send, first_receive, second, second_send, second_receive, channel_id, ); } _ => (), } } } } } alice_send.send(None).unwrap(); bob_send.send(None).unwrap(); alice_handle.join().unwrap(); bob_handle.join().unwrap(); } fn close_established_channel( first: DlcParty, second: DlcParty, channel_id: ChannelId, generate_blocks: &F, ) where F: Fn(u64), { first .lock() .unwrap() .force_close_channel(&channel_id) .expect("to be able to unilaterally close."); assert_channel_state!(first, channel_id, Signed, Closing); let contract_id = get_established_channel_contract_id(&first, &channel_id); periodic_check(first.clone()); let wait = dlc_manager::manager::CET_NSEQUENCE; generate_blocks(10); periodic_check(second.clone()); assert_channel_state!(second, channel_id, Signed, Closing); periodic_check(first.clone()); // Should not have changed state before the CET is spendable. assert_channel_state!(first, channel_id, Signed, Closing); generate_blocks(wait as u64 - 9); periodic_check(first.clone()); assert_channel_state!(first, channel_id, Closed); assert_contract_state!(first, contract_id, PreClosed); generate_blocks(1); periodic_check(second.clone()); assert_channel_state!(second, channel_id, CounterClosed); assert_contract_state!(second, contract_id, PreClosed); generate_blocks(5); periodic_check(first.clone()); periodic_check(second.clone()); assert_contract_state!(first, contract_id, Closed); assert_contract_state!(second, contract_id, Closed); } fn cheat_punish( first: DlcParty, second: DlcParty, channel_id: ChannelId, generate_blocks: &F, established: bool, ) { first.lock().unwrap().get_store().rollback(); if established { first .lock() .unwrap() .force_close_channel(&channel_id) .expect("the cheater to be able to close on established"); } else { first .lock() .unwrap() .force_close_channel(&channel_id) .expect("the cheater to be able to close on settled"); } generate_blocks(2); periodic_check(second.clone()); assert_channel_state!(second, channel_id, ClosedPunished); } fn settle_channel( first: DlcParty, first_send: &Sender>, first_receive: &Receiver<()>, second: DlcParty, second_send: &Sender>, second_receive: &Receiver<()>, channel_id: ChannelId, ) { let (settle_offer, _) = first .lock() .unwrap() .settle_offer(&channel_id, test_utils::ACCEPT_COLLATERAL) .expect("to be able to offer a settlement of the contract."); first_send .send(Some(Message::SettleOffer(settle_offer))) .unwrap(); second_receive.recv().expect("Error synchronizing"); assert_channel_state!(first, channel_id, Signed, SettledOffered); assert_channel_state!(second, channel_id, Signed, SettledReceived); let (settle_accept, _) = second .lock() .unwrap() .accept_settle_offer(&channel_id) .expect("to be able to accept a settlement offer"); second_send .send(Some(Message::SettleAccept(settle_accept))) .unwrap(); // Process Accept first_receive.recv().expect("Error synchronizing"); // Process Confirm second_receive.recv().expect("Error synchronizing"); // Process Finalize first_receive.recv().expect("Error synchronizing"); assert_channel_state!(first, channel_id, Signed, Settled); assert_channel_state!(second, channel_id, Signed, Settled); } fn settle_reject( first: DlcParty, first_send: &Sender>, first_receive: &Receiver<()>, second: DlcParty, second_send: &Sender>, second_receive: &Receiver<()>, channel_id: ChannelId, ) { let (settle_offer, _) = first .lock() .unwrap() .settle_offer(&channel_id, test_utils::ACCEPT_COLLATERAL) .expect("to be able to reject a settlement of the contract."); first_send .send(Some(Message::SettleOffer(settle_offer))) .unwrap(); second_receive.recv().expect("Error synchronizing"); assert_channel_state!(first, channel_id, Signed, SettledOffered); assert_channel_state!(second, channel_id, Signed, SettledReceived); let (settle_reject, _) = second .lock() .unwrap() .reject_settle_offer(&channel_id) .expect("to be able to reject a settlement offer"); second_send .send(Some(Message::Reject(settle_reject))) .unwrap(); first_receive.recv().expect("Error synchronizing"); assert_channel_state!(first, channel_id, Signed, Established); assert_channel_state!(second, channel_id, Signed, Established); } fn settle_race( first: DlcParty, first_send: &Sender>, first_receive: &Receiver<()>, second: DlcParty, second_send: &Sender>, second_receive: &Receiver<()>, channel_id: ChannelId, ) { let (settle_offer, _) = first .lock() .unwrap() .settle_offer(&channel_id, test_utils::ACCEPT_COLLATERAL) .expect("to be able to offer a settlement of the contract."); let (settle_offer_2, _) = second .lock() .unwrap() .settle_offer(&channel_id, test_utils::ACCEPT_COLLATERAL) .expect("to be able to offer a settlement of the contract."); first_send .send(Some(Message::SettleOffer(settle_offer))) .unwrap(); second_send .send(Some(Message::SettleOffer(settle_offer_2))) .unwrap(); // Process 2 offers + 2 rejects first_receive .recv_timeout(Duration::from_secs(2)) .expect("Error synchronizing 1"); second_receive .recv_timeout(Duration::from_secs(2)) .expect("Error synchronizing 2"); first_receive .recv_timeout(Duration::from_secs(2)) .expect("Error synchronizing 3"); second_receive .recv_timeout(Duration::from_secs(2)) .expect("Error synchronizing 4"); assert_channel_state!(first, channel_id, Signed, Established); assert_channel_state!(second, channel_id, Signed, Established); } fn renew_channel( first: DlcParty, first_send: &Sender>, first_receive: &Receiver<()>, second: DlcParty, second_send: &Sender>, second_receive: &Receiver<()>, channel_id: ChannelId, contract_input: &ContractInput, check_prev_contract_close: bool, ) { let prev_contract_id = if check_prev_contract_close { Some(get_established_channel_contract_id(&first, &channel_id)) } else { None }; let (renew_offer, _) = first .lock() .unwrap() .renew_offer(&channel_id, test_utils::ACCEPT_COLLATERAL, contract_input) .expect("to be able to renew channel contract"); first_send .send(Some(Message::RenewOffer(renew_offer))) .expect("to be able to send the renew offer"); // Process Renew Offer second_receive.recv().expect("Error synchronizing"); assert_channel_state!(first, channel_id, Signed, RenewOffered); assert_channel_state!(second, channel_id, Signed, RenewOffered); let (accept_renew, _) = second .lock() .unwrap() .accept_renew_offer(&channel_id) .expect("to be able to accept the renewal"); second_send .send(Some(Message::RenewAccept(accept_renew))) .expect("to be able to send the accept renew"); // Process Renew Accept first_receive.recv().expect("Error synchronizing"); assert_channel_state!(first, channel_id, Signed, RenewConfirmed); // Process Renew Confirm second_receive.recv().expect("Error synchronizing"); // Process Renew Finalize first_receive.recv().expect("Error synchronizing"); // Process Renew Revoke second_receive.recv().expect("Error synchronizing"); if let Some(prev_contract_id) = prev_contract_id { assert_contract_state!(first, prev_contract_id, Closed); assert_contract_state!(second, prev_contract_id, Closed); } let new_contract_id = get_established_channel_contract_id(&first, &channel_id); assert_channel_state!(first, channel_id, Signed, Established); assert_contract_state!(first, new_contract_id, Confirmed); assert_channel_state!(second, channel_id, Signed, Established); assert_contract_state!(second, new_contract_id, Confirmed); } fn renew_reject( first: DlcParty, first_send: &Sender>, first_receive: &Receiver<()>, second: DlcParty, second_send: &Sender>, second_receive: &Receiver<()>, channel_id: ChannelId, contract_input: &ContractInput, ) { let (renew_offer, _) = first .lock() .unwrap() .renew_offer(&channel_id, test_utils::ACCEPT_COLLATERAL, contract_input) .expect("to be able to renew channel contract"); first_send .send(Some(Message::RenewOffer(renew_offer))) .expect("to be able to send the renew offer"); // Process Renew Offer second_receive.recv().expect("Error synchronizing"); assert_channel_state!(first, channel_id, Signed, RenewOffered); assert_channel_state!(second, channel_id, Signed, RenewOffered); let (renew_reject, _) = second .lock() .unwrap() .reject_renew_offer(&channel_id) .expect("to be able to reject the renewal"); second_send .send(Some(Message::Reject(renew_reject))) .expect("to be able to send the renew reject"); // Process Renew Reject first_receive.recv().expect("Error synchronizing"); assert_channel_state!(first, channel_id, Signed, Settled); assert_channel_state!(second, channel_id, Signed, Settled); } fn renew_race( first: DlcParty, first_send: &Sender>, first_receive: &Receiver<()>, second: DlcParty, second_send: &Sender>, second_receive: &Receiver<()>, channel_id: ChannelId, contract_input: &ContractInput, ) { let (renew_offer, _) = first .lock() .unwrap() .renew_offer(&channel_id, test_utils::OFFER_COLLATERAL, contract_input) .expect("to be able to renew channel contract"); let mut contract_input_2 = contract_input.clone(); contract_input_2.accept_collateral = contract_input.offer_collateral; contract_input_2.offer_collateral = contract_input.accept_collateral; let (renew_offer_2, _) = second .lock() .unwrap() .renew_offer(&channel_id, test_utils::OFFER_COLLATERAL, &contract_input_2) .expect("to be able to renew channel contract"); first_send .send(Some(Message::RenewOffer(renew_offer))) .expect("to be able to send the renew offer"); second_send .send(Some(Message::RenewOffer(renew_offer_2))) .expect("to be able to send the renew offer"); // Process 2 offers + 2 rejects first_receive .recv_timeout(Duration::from_secs(2)) .expect("Error synchronizing 1"); second_receive .recv_timeout(Duration::from_secs(2)) .expect("Error synchronizing 2"); first_receive .recv_timeout(Duration::from_secs(2)) .expect("Error synchronizing 3"); second_receive .recv_timeout(Duration::from_secs(2)) .expect("Error synchronizing 4"); assert_channel_state!(first, channel_id, Signed, Settled); assert_channel_state!(second, channel_id, Signed, Settled); } fn collaborative_close( first: DlcParty, first_send: &Sender>, second: DlcParty, channel_id: ChannelId, sync_receive: &Receiver<()>, generate_blocks: &F, ) { let contract_id = get_established_channel_contract_id(&first, &channel_id); let close_offer = first .lock() .unwrap() .offer_collaborative_close(&channel_id, 100000000) .expect("to be able to propose a collaborative close"); first_send .send(Some(Message::CollaborativeCloseOffer(close_offer))) .expect("to be able to send collaborative close"); sync_receive.recv().expect("Error synchronizing"); assert_channel_state!(first, channel_id, Signed, CollaborativeCloseOffered); assert_channel_state!(second, channel_id, Signed, CollaborativeCloseOffered); second .lock() .unwrap() .accept_collaborative_close(&channel_id) .expect("to be able to accept a collaborative close"); assert_channel_state!(second, channel_id, CollaborativelyClosed); assert_contract_state!(second, contract_id, Closed); generate_blocks(2); periodic_check(first.clone()); assert_channel_state!(first, channel_id, CollaborativelyClosed); assert_contract_state!(first, contract_id, Closed); } fn renew_timeout( first: DlcParty, first_send: &Sender>, first_receive: &Receiver<()>, second: DlcParty, second_send: &Sender>, second_receive: &Receiver<()>, channel_id: ChannelId, contract_input: &ContractInput, path: TestPath, generate_blocks: &F, ) { { let (renew_offer, _) = first .lock() .unwrap() .renew_offer(&channel_id, test_utils::ACCEPT_COLLATERAL, contract_input) .expect("to be able to offer a settlement of the contract."); first_send .send(Some(Message::RenewOffer(renew_offer))) .unwrap(); second_receive.recv().expect("Error synchronizing"); if let TestPath::RenewOfferTimeout = path { mocks::mock_time::set_time( (EVENT_MATURITY as u64) + dlc_manager::manager::PEER_TIMEOUT + 2, ); periodic_check(first.clone()); assert_channel_state!(first, channel_id, Closed); } else { let (renew_accept, _) = second .lock() .unwrap() .accept_renew_offer(&channel_id) .expect("to be able to accept a settlement offer"); second_send .send(Some(Message::RenewAccept(renew_accept))) .unwrap(); // Process Accept first_receive.recv().expect("Error synchronizing"); if let TestPath::RenewAcceptTimeout = path { mocks::mock_time::set_time( (EVENT_MATURITY as u64) + dlc_manager::manager::PEER_TIMEOUT + 2, ); periodic_check(second.clone()); assert_channel_state!(second, channel_id, Closed); } else if let TestPath::RenewConfirmTimeout = path { // Process Confirm second_receive.recv().expect("Error synchronizing"); mocks::mock_time::set_time( (EVENT_MATURITY as u64) + dlc_manager::manager::PEER_TIMEOUT + 2, ); periodic_check(first.clone()); assert_channel_state!(first, channel_id, Closed); } else if let TestPath::RenewFinalizeTimeout = path { //Process confirm second_receive.recv().expect("Error synchronizing"); // Process Finalize first_receive.recv().expect("Error synchronizing"); mocks::mock_time::set_time( (EVENT_MATURITY as u64) + dlc_manager::manager::PEER_TIMEOUT + 2, ); periodic_check(second.clone()); generate_blocks(289); periodic_check(second.clone()); assert_channel_state!(second, channel_id, Closed); } } } } fn settle_timeout( first: DlcParty, first_send: &Sender>, first_receive: &Receiver<()>, second: DlcParty, second_send: &Sender>, second_receive: &Receiver<()>, channel_id: ChannelId, path: TestPath, ) { let (settle_offer, _) = first .lock() .unwrap() .settle_offer(&channel_id, test_utils::ACCEPT_COLLATERAL) .expect("to be able to offer a settlement of the contract."); first_send .send(Some(Message::SettleOffer(settle_offer))) .unwrap(); second_receive.recv().expect("Error synchronizing"); if let TestPath::SettleOfferTimeout = path { mocks::mock_time::set_time( (EVENT_MATURITY as u64) + dlc_manager::manager::PEER_TIMEOUT + 2, ); periodic_check(first.clone()); assert_channel_state!(first, channel_id, Signed, Closing); } else { let (settle_accept, _) = second .lock() .unwrap() .accept_settle_offer(&channel_id) .expect("to be able to accept a settlement offer"); second_send .send(Some(Message::SettleAccept(settle_accept))) .unwrap(); // Process Accept first_receive.recv().expect("Error synchronizing"); if let TestPath::SettleAcceptTimeout = path { mocks::mock_time::set_time( (EVENT_MATURITY as u64) + dlc_manager::manager::PEER_TIMEOUT + 2, ); periodic_check(second.clone()); second .lock() .unwrap() .get_store() .get_channel(&channel_id) .unwrap(); assert_channel_state!(second, channel_id, Signed, Closing); } else if let TestPath::SettleConfirmTimeout = path { // Process Confirm second_receive.recv().expect("Error synchronizing"); mocks::mock_time::set_time( (EVENT_MATURITY as u64) + dlc_manager::manager::PEER_TIMEOUT + 2, ); periodic_check(first.clone()); assert_channel_state!(first, channel_id, Signed, Closing); } } }