From 4b8581e7f8801b9847edfdb8438db6c926ba5435 Mon Sep 17 00:00:00 2001 From: chris-belcher Date: Thu, 24 Feb 2022 16:05:43 +0000 Subject: [PATCH] Remove NETWORK const, instead detect from json-rpc --- src/contracts.rs | 33 +++--- src/direct_send.rs | 6 +- src/lib.rs | 175 +++++++++++++++++++------------- src/main.rs | 19 +++- src/maker_protocol.rs | 10 +- src/offerbook_sync.rs | 15 +-- src/taker_protocol.rs | 2 +- src/wallet_sync.rs | 26 ++--- src/watchtower_protocol.rs | 19 ++-- tests/test_standard_coinswap.rs | 22 ++-- 10 files changed, 192 insertions(+), 135 deletions(-) diff --git a/src/contracts.rs b/src/contracts.rs index a5843620..dbcd13de 100644 --- a/src/contracts.rs +++ b/src/contracts.rs @@ -12,7 +12,7 @@ use bitcoin::{ secp256k1::{Message, Secp256k1, SecretKey, Signature}, util::bip143::SigHashCache, util::ecdsa::PublicKey, - Address, OutPoint, SigHashType, Transaction, TxIn, TxOut, + OutPoint, SigHashType, Transaction, TxIn, TxOut, }; use bitcoincore_rpc::{Client, RpcApi}; @@ -23,7 +23,7 @@ use rand::RngCore; use crate::error::Error; use crate::messages::ConfirmedCoinSwapTxInfo; use crate::wallet_sync::{ - create_multisig_redeemscript, IncomingSwapCoin, OutgoingSwapCoin, Wallet, NETWORK, + create_multisig_redeemscript, IncomingSwapCoin, OutgoingSwapCoin, Wallet, }; //relatively simple handling of miner fees for now, each funding transaction is considered @@ -79,6 +79,14 @@ pub fn calculate_coinswap_fee( + (time_in_blocks * time_relative_fee_ppb / 1_000_000_000) } +pub fn redeemscript_to_scriptpubkey(redeemscript: &Script) -> Script { + //p2wsh address + Script::new_witness_program( + bitcoin::bech32::u5::try_from_u8(0).unwrap(), + &redeemscript.wscript_hash().to_vec(), + ) +} + pub fn calculate_maker_pubkey_from_nonce( tweakable_point: PublicKey, nonce: SecretKey, @@ -249,8 +257,6 @@ pub fn create_senders_contract_tx( input_value: u64, contract_redeemscript: &Script, ) -> Transaction { - let contract_address = Address::p2wsh(&contract_redeemscript, NETWORK); - Transaction { input: vec![TxIn { previous_output: input, @@ -259,7 +265,7 @@ pub fn create_senders_contract_tx( script_sig: Script::new(), }], output: vec![TxOut { - script_pubkey: contract_address.script_pubkey(), + script_pubkey: redeemscript_to_scriptpubkey(&contract_redeemscript), value: input_value - 1000, }], lock_time: 0, @@ -291,8 +297,7 @@ fn is_contract_out_valid( let redeemscript_from_request = create_contract_redeemscript(hashlock_pubkey, timelock_pubkey, hashvalue, locktime); - let contract_spk_from_request = - Address::p2wsh(&redeemscript_from_request, NETWORK).script_pubkey(); + let contract_spk_from_request = redeemscript_to_scriptpubkey(&redeemscript_from_request); if contract_output.script_pubkey != contract_spk_from_request { return Err(Error::Protocol( "given transaction does not pay to requested contract", @@ -370,7 +375,7 @@ pub fn find_funding_output<'a>( funding_tx: &'a Transaction, multisig_redeemscript: &Script, ) -> Option<(u32, &'a TxOut)> { - let multisig_spk = Address::p2wsh(&multisig_redeemscript, NETWORK).script_pubkey(); + let multisig_spk = redeemscript_to_scriptpubkey(&multisig_redeemscript); funding_tx .output .iter() @@ -456,7 +461,7 @@ pub fn verify_proof_of_funding( //check that the provided contract matches the scriptpubkey from the //cache which was populated when the signsendercontracttx message arrived - let contract_spk = Address::p2wsh(&funding_info.contract_redeemscript, NETWORK).script_pubkey(); + let contract_spk = redeemscript_to_scriptpubkey(&funding_info.contract_redeemscript); if !wallet.does_prevout_match_cached_contract( &OutPoint { @@ -501,7 +506,7 @@ pub fn validate_contract_tx( return Err(Error::Protocol("not spending the funding outpoint")); } if receivers_contract_tx.output[0].script_pubkey - != Address::p2wsh(&contract_redeemscript, NETWORK).script_pubkey() + != redeemscript_to_scriptpubkey(&contract_redeemscript) { return Err(Error::Protocol("doesnt pay to requested contract")); } @@ -911,8 +916,8 @@ mod test { let multisig_reedemscript = Script::from(Vec::from_hex("5221032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af21039b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef52ae").unwrap()); let another_script = Script::from(Vec::from_hex("020000000156944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d2a0000000000000000014871000000000000220020dad1b452caf4a0f26aecf1cc43aaae9b903a043c34f75ad9a36c86317b22236800000000").unwrap()); - let multi_script_pubkey = Address::p2wsh(&multisig_reedemscript, NETWORK).script_pubkey(); - let another_script_pubkey = Address::p2wsh(&another_script, NETWORK).script_pubkey(); + let multi_script_pubkey = redeemscript_to_scriptpubkey(&multisig_reedemscript); + let another_script_pubkey = redeemscript_to_scriptpubkey(&another_script); // Create the funding transaction let funding_tx = Transaction { @@ -1034,7 +1039,7 @@ mod test { // Change contract transaction to pay into wrong output let mut contract_tx_err2 = contract_tx.clone(); let multisig_redeemscript = Script::from(Vec::from_hex("5221032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af21039b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef52ae").unwrap()); - let multi_script_pubkey = Address::p2wsh(&multisig_redeemscript, NETWORK).script_pubkey(); + let multi_script_pubkey = redeemscript_to_scriptpubkey(&multisig_redeemscript); contract_tx_err2.output[0] = TxOut { script_pubkey: multi_script_pubkey, value: 3000, @@ -1065,7 +1070,7 @@ mod test { let funding_outpoint_script = crate::wallet_sync::create_multisig_redeemscript(&pub1, &pub2); - let funding_spk = Address::p2sh(&funding_outpoint_script, NETWORK).script_pubkey(); + let funding_spk = redeemscript_to_scriptpubkey(&funding_outpoint_script); let funding_tx = Transaction { input: vec![TxIn { diff --git a/src/direct_send.rs b/src/direct_send.rs index 015e805b..933f5f53 100644 --- a/src/direct_send.rs +++ b/src/direct_send.rs @@ -8,7 +8,7 @@ use bitcoincore_rpc::Client; use crate::contracts::SwapCoin; use crate::error::Error; -use crate::wallet_sync::{UTXOSpendInfo, Wallet, NETWORK}; +use crate::wallet_sync::{UTXOSpendInfo, Wallet}; #[derive(Debug)] pub enum SendAmount { @@ -179,8 +179,8 @@ impl Wallet { //so a.network is always testnet even if the address is signet let testnet_signet_type = (a.network == Network::Testnet || a.network == Network::Signet) - && (NETWORK == Network::Testnet || NETWORK == Network::Signet); - if a.network != NETWORK && !testnet_signet_type { + && (self.network == Network::Testnet || self.network == Network::Signet); + if a.network != self.network && !testnet_signet_type { panic!("wrong address network type (e.g. mainnet, testnet, regtest, signet)"); } a diff --git a/src/lib.rs b/src/lib.rs index 31b0f77b..3b81f13c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,7 @@ use bitcoin_wallet::mnemonic; use bitcoincore_rpc::{Auth, Client, Error, RpcApi}; pub mod wallet_sync; -use wallet_sync::{Wallet, WalletSwapCoin, WalletSyncAddressAmount, NETWORK}; +use wallet_sync::{Wallet, WalletSwapCoin, WalletSyncAddressAmount}; pub mod direct_send; use direct_send::{CoinToSpend, Destination, SendAmount}; @@ -47,7 +47,17 @@ pub mod watchtower_protocol; static INIT: Once = Once::new(); -pub fn get_bitcoin_rpc() -> Result { +fn str_to_bitcoin_network(net_str: &str) -> Network { + match net_str { + "main" => Network::Bitcoin, + "test" => Network::Testnet, + "signet" => Network::Signet, + "regtest" => Network::Regtest, + _ => panic!("unknown network: {}", net_str), + } +} + +pub fn get_bitcoin_rpc() -> Result<(Client, Network), Error> { let auth = match RPC_CREDENTIALS { Some((user, pass)) => Auth::UserPass(user.to_string(), pass.to_string()), None => { @@ -61,22 +71,8 @@ pub fn get_bitcoin_rpc() -> Result { format!("http://{}/wallet/{}", RPC_HOSTPORT, RPC_WALLET), auth, )?; - //TODO remove this network configuring entirely and just have teleport automatically - // detect it from the node - let network_chain = rpc.get_blockchain_info()?.chain; - let teleport_chain = match NETWORK { - Network::Bitcoin => "main", - Network::Testnet => "test", - Network::Signet => "signet", - Network::Regtest => "regtest", - }; - if network_chain != teleport_chain { - panic!( - "Incorrectly configured network: connected bitcoin node chain = {}, our chain = {}", - network_chain, teleport_chain - ); - } - Ok(rpc) + let network = str_to_bitcoin_network(rpc.get_blockchain_info()?.chain.as_str()); + Ok((rpc, network)) } /// Setup function that will only run once, even if called multiple times. @@ -92,7 +88,7 @@ pub fn setup_logger() { } pub fn generate_wallet(wallet_file_name: &PathBuf) -> std::io::Result<()> { - let rpc = match get_bitcoin_rpc() { + let (rpc, network) = match get_bitcoin_rpc() { Ok(rpc) => rpc, Err(error) => { log::error!(target: "main", "error connecting to bitcoin node: {:?}", error); @@ -109,8 +105,11 @@ pub fn generate_wallet(wallet_file_name: &PathBuf) -> std::io::Result<()> { Wallet::save_new_wallet_file(&wallet_file_name, mnemonic.to_string(), extension.clone()) .unwrap(); - let w = match Wallet::load_wallet_from_file(&wallet_file_name, WalletSyncAddressAmount::Normal) - { + let w = match Wallet::load_wallet_from_file( + &wallet_file_name, + network, + WalletSyncAddressAmount::Normal, + ) { Ok(w) => w, Err(error) => panic!("error loading wallet file: {:?}", error), }; @@ -158,21 +157,24 @@ pub fn recover_wallet(wallet_file_name: &PathBuf) -> std::io::Result<()> { } pub fn display_wallet_balance(wallet_file_name: &PathBuf, long_form: Option) { - let mut wallet = - match Wallet::load_wallet_from_file(wallet_file_name, WalletSyncAddressAmount::Normal) { - Ok(w) => w, - Err(error) => { - log::error!(target: "main", "error loading wallet file: {:?}", error); - return; - } - }; - let rpc = match get_bitcoin_rpc() { + let (rpc, network) = match get_bitcoin_rpc() { Ok(rpc) => rpc, Err(error) => { log::error!(target: "main", "error connecting to bitcoin node: {:?}", error); return; } }; + let mut wallet = match Wallet::load_wallet_from_file( + wallet_file_name, + network, + WalletSyncAddressAmount::Normal, + ) { + Ok(w) => w, + Err(error) => { + log::error!(target: "main", "error loading wallet file: {:?}", error); + return; + } + }; wallet.startup_sync(&rpc).unwrap(); let long_form = long_form.unwrap_or(false); @@ -335,33 +337,39 @@ pub fn display_wallet_balance(wallet_file_name: &PathBuf, long_form: Option w, - Err(error) => { - log::error!(target: "main", "error loading wallet file: {:?}", error); - return; - } - }; + let wallet = match Wallet::load_wallet_from_file( + wallet_file_name, + Network::Regtest, + WalletSyncAddressAmount::Normal, + ) { + Ok(w) => w, + Err(error) => { + log::error!(target: "main", "error loading wallet file: {:?}", error); + return; + } + }; wallet.print_wallet_key_data(); } pub fn print_receive_invoice(wallet_file_name: &PathBuf) { - let mut wallet = - match Wallet::load_wallet_from_file(wallet_file_name, WalletSyncAddressAmount::Normal) { - Ok(w) => w, - Err(error) => { - log::error!(target: "main", "error loading wallet file: {:?}", error); - return; - } - }; - let rpc = match get_bitcoin_rpc() { + let (rpc, network) = match get_bitcoin_rpc() { Ok(rpc) => rpc, Err(error) => { log::error!(target: "main", "error connecting to bitcoin node: {:?}", error); return; } }; + let mut wallet = match Wallet::load_wallet_from_file( + wallet_file_name, + network, + WalletSyncAddressAmount::Normal, + ) { + Ok(w) => w, + Err(error) => { + log::error!(target: "main", "error loading wallet file: {:?}", error); + return; + } + }; wallet.startup_sync(&rpc).unwrap(); let addr = match wallet.get_next_external_address(&rpc) { @@ -381,14 +389,14 @@ pub fn run_maker( maker_behavior: MakerBehavior, kill_flag: Option>>, ) { - let rpc = match get_bitcoin_rpc() { + let (rpc, network) = match get_bitcoin_rpc() { Ok(rpc) => rpc, Err(error) => { log::error!(target: "main", "error connecting to bitcoin node: {:?}", error); return; } }; - let mut wallet = match Wallet::load_wallet_from_file(wallet_file_name, sync_amount) { + let mut wallet = match Wallet::load_wallet_from_file(wallet_file_name, network, sync_amount) { Ok(w) => w, Err(error) => { log::error!(target: "main", "error loading wallet file: {:?}", error); @@ -423,14 +431,14 @@ pub fn run_taker( maker_count: u16, tx_count: u32, ) { - let rpc = match get_bitcoin_rpc() { + let (rpc, network) = match get_bitcoin_rpc() { Ok(rpc) => rpc, Err(error) => { log::error!(target: "main", "error connecting to bitcoin node: {:?}", error); return; } }; - let mut wallet = match Wallet::load_wallet_from_file(wallet_file_name, sync_amount) { + let mut wallet = match Wallet::load_wallet_from_file(wallet_file_name, network, sync_amount) { Ok(w) => w, Err(error) => { log::error!(target: "main", "error loading wallet file: {:?}", error); @@ -456,21 +464,24 @@ pub fn recover_from_incomplete_coinswap( hashvalue: Hash160, dont_broadcast: bool, ) { - let mut wallet = - match Wallet::load_wallet_from_file(wallet_file_name, WalletSyncAddressAmount::Normal) { - Ok(w) => w, - Err(error) => { - log::error!(target: "main", "error loading wallet file: {:?}", error); - return; - } - }; - let rpc = match get_bitcoin_rpc() { + let (rpc, network) = match get_bitcoin_rpc() { Ok(rpc) => rpc, Err(error) => { log::error!(target: "main", "error connecting to bitcoin node: {:?}", error); return; } }; + let mut wallet = match Wallet::load_wallet_from_file( + wallet_file_name, + network, + WalletSyncAddressAmount::Normal, + ) { + Ok(w) => w, + Err(error) => { + log::error!(target: "main", "error loading wallet file: {:?}", error); + return; + } + }; wallet.startup_sync(&rpc).unwrap(); let incomplete_coinswaps = wallet.find_incomplete_coinswaps(&rpc).unwrap(); @@ -520,13 +531,29 @@ pub fn recover_from_incomplete_coinswap( } #[tokio::main] -pub async fn download_and_display_offers(maker_address: Option) { +pub async fn download_and_display_offers( + network_str: Option, + maker_address: Option, +) { let maker_addresses = if let Some(maker_addr) = maker_address { vec![MakerAddress::Tor { address: maker_addr, }] } else { - get_advertised_maker_addresses() + let network = match get_bitcoin_rpc() { + Ok((_rpc, network)) => network, + Err(error) => { + if let Some(net_str) = network_str { + str_to_bitcoin_network(net_str.as_str()) + } else { + panic!( + "network string not provided, and error connecting to bitcoin node: {:?}", + error + ); + } + } + }; + get_advertised_maker_addresses(network) .await .expect("unable to sync maker addresses from directory servers") }; @@ -583,21 +610,24 @@ pub fn direct_send( coins_to_spend: &[CoinToSpend], dont_broadcast: bool, ) { - let rpc = match get_bitcoin_rpc() { + let (rpc, network) = match get_bitcoin_rpc() { Ok(rpc) => rpc, Err(error) => { log::error!(target: "main", "error connecting to bitcoin node: {:?}", error); return; } }; - let mut wallet = - match Wallet::load_wallet_from_file(wallet_file_name, WalletSyncAddressAmount::Normal) { - Ok(w) => w, - Err(error) => { - log::error!(target: "main", "error loading wallet file: {:?}", error); - return; - } - }; + let mut wallet = match Wallet::load_wallet_from_file( + wallet_file_name, + network, + WalletSyncAddressAmount::Normal, + ) { + Ok(w) => w, + Err(error) => { + log::error!(target: "main", "error loading wallet file: {:?}", error); + return; + } + }; wallet.startup_sync(&rpc).unwrap(); let tx = wallet .create_direct_send(&rpc, fee_rate, send_amount, destination, coins_to_spend) @@ -629,7 +659,7 @@ pub fn direct_send( } pub fn run_watchtower(kill_flag: Option>>) { - let rpc = match get_bitcoin_rpc() { + let (rpc, network) = match get_bitcoin_rpc() { Ok(rpc) => rpc, Err(error) => { log::error!(target: "main", "error connecting to bitcoin node: {:?}", error); @@ -639,6 +669,7 @@ pub fn run_watchtower(kill_flag: Option>>) { watchtower_protocol::start_watchtower( &rpc, + network, if kill_flag.is_none() { Arc::new(RwLock::new(false)) } else { diff --git a/src/main.rs b/src/main.rs index 0306f580..971d2434 100644 --- a/src/main.rs +++ b/src/main.rs @@ -78,8 +78,16 @@ enum Subcommand { hashvalue: Hash160, }, - /// Download all offers from all makers out there. Optionally download from one given maker - DownloadOffers { maker_address: Option }, + /// Download all offers from all makers out there. If bitcoin node not configured then + /// provide the network as an argument, can also optionally download from one given maker + DownloadOffers { + /// Network in question, options are "main", "test", "signet". Only used if configured + /// bitcoin node RPC is unreachable + network: Option, + /// Optional single maker address to only download from. Useful if testing if your own + /// maker is reachable + maker_address: Option, + }, /// Send a transaction from the wallet DirectSend { @@ -158,8 +166,11 @@ fn main() -> Result<(), Box> { args.dont_broadcast, ); } - Subcommand::DownloadOffers { maker_address } => { - teleport::download_and_display_offers(maker_address); + Subcommand::DownloadOffers { + network, + maker_address, + } => { + teleport::download_and_display_offers(network, maker_address); } Subcommand::DirectSend { send_amount, diff --git a/src/maker_protocol.rs b/src/maker_protocol.rs index 5079efda..05f5e2e5 100644 --- a/src/maker_protocol.rs +++ b/src/maker_protocol.rs @@ -41,7 +41,7 @@ use crate::messages::{ SendersContractSig, SignReceiversContractTx, SignSendersAndReceiversContractTxes, SignSendersContractTx, SwapCoinPrivateKey, TakerToMakerMessage, }; -use crate::wallet_sync::{IncomingSwapCoin, OutgoingSwapCoin, Wallet, WalletSwapCoin, NETWORK}; +use crate::wallet_sync::{IncomingSwapCoin, OutgoingSwapCoin, Wallet, WalletSwapCoin}; use crate::watchtower_client::{ping_watchtowers, register_coinswap_with_watchtowers}; use crate::watchtower_protocol::{ContractTransaction, ContractsInfo}; @@ -112,9 +112,9 @@ async fn run( log::info!("Pinging watchtowers. . ."); ping_watchtowers().await?; - if NETWORK != Network::Regtest { + if wallet.read().unwrap().network != Network::Regtest { log::info!("Adding my address at the directory servers. . ."); - post_maker_address_to_directory_servers(NETWORK, MAKER_ONION_ADDR) + post_maker_address_to_directory_servers(wallet.read().unwrap().network, MAKER_ONION_ADDR) .await .unwrap(); } @@ -171,12 +171,12 @@ async fn run( let directory_servers_refresh_interval = Duration::from_secs( config.directory_servers_refresh_interval_secs ); - if NETWORK != Network::Regtest + if wallet.read().unwrap().network != Network::Regtest && Instant::now().saturating_duration_since(last_directory_servers_refresh) > directory_servers_refresh_interval { last_directory_servers_refresh = Instant::now(); let result_expiry_time = post_maker_address_to_directory_servers( - NETWORK, + wallet.read().unwrap().network, MAKER_ONION_ADDR ).await; log::info!("Refreshing my address at the directory servers = {:?}", diff --git a/src/offerbook_sync.rs b/src/offerbook_sync.rs index f9d0dd9c..c4e2b8e9 100644 --- a/src/offerbook_sync.rs +++ b/src/offerbook_sync.rs @@ -17,7 +17,6 @@ use crate::taker_protocol::{ handshake_maker, read_message, send_message, FIRST_CONNECT_ATTEMPTS, FIRST_CONNECT_ATTEMPT_TIMEOUT_SEC, FIRST_CONNECT_SLEEP_DELAY_SEC, }; -use crate::wallet_sync::NETWORK; #[derive(Debug, Clone)] pub enum MakerAddress { @@ -151,14 +150,18 @@ pub async fn sync_offerbook_with_addresses( result } -pub async fn get_advertised_maker_addresses() -> Result, DirectoryServerError> { - Ok(if NETWORK == Network::Regtest { +pub async fn get_advertised_maker_addresses( + network: Network, +) -> Result, DirectoryServerError> { + Ok(if network == Network::Regtest { get_regtest_maker_addresses() } else { - sync_maker_addresses_from_directory_servers(NETWORK).await? + sync_maker_addresses_from_directory_servers(network).await? }) } -pub async fn sync_offerbook() -> Result, DirectoryServerError> { - Ok(sync_offerbook_with_addresses(get_advertised_maker_addresses().await?).await) +pub async fn sync_offerbook( + network: Network, +) -> Result, DirectoryServerError> { + Ok(sync_offerbook_with_addresses(get_advertised_maker_addresses(network).await?).await) } diff --git a/src/taker_protocol.rs b/src/taker_protocol.rs index bea9f4be..c1c07671 100644 --- a/src/taker_protocol.rs +++ b/src/taker_protocol.rs @@ -92,7 +92,7 @@ pub async fn start_taker(rpc: &Client, wallet: &mut Wallet, config: TakerConfig) } async fn run(rpc: &Client, wallet: &mut Wallet, config: TakerConfig) -> Result<(), Error> { - let offers_addresses = sync_offerbook() + let offers_addresses = sync_offerbook(wallet.network) .await .expect("unable to sync maker addresses from directory servers"); log::info!("<=== Got Offers"); diff --git a/src/wallet_sync.rs b/src/wallet_sync.rs index 768ec3b7..fe16f9b7 100644 --- a/src/wallet_sync.rs +++ b/src/wallet_sync.rs @@ -1,10 +1,3 @@ -//TODO this goes in the config file -pub const NETWORK: Network = Network::Regtest; -//other options: Network::Signet, Network::Bitcoin, Network::Testnet -//Signet is probably the best for this early stage of the project if -// you want to coinswap with other people -//Mainnet/Bitcoin only for the brave - // this file contains code handling the wallet and sync'ing the wallet // for now the wallet is only sync'd via bitcoin core's RPC // makers will only ever sync this way, but one day takers may sync in other @@ -81,6 +74,7 @@ struct WalletFileData { } pub struct Wallet { + pub network: Network, master_key: ExtendedPrivKey, wallet_file_name: String, external_index: u32, @@ -450,10 +444,10 @@ impl Wallet { ); for (multisig_redeemscript, swapcoin) in &self.incoming_swapcoins { - Self::print_script_and_coin(multisig_redeemscript, swapcoin); + Self::print_script_and_coin(multisig_redeemscript, swapcoin, self.network); } for (multisig_redeemscript, swapcoin) in &self.outgoing_swapcoins { - Self::print_script_and_coin(multisig_redeemscript, swapcoin); + Self::print_script_and_coin(multisig_redeemscript, swapcoin, self.network); } println!( "swapcoin count = {}", @@ -461,11 +455,11 @@ impl Wallet { ); } - fn print_script_and_coin(script: &Script, coin: &dyn SwapCoin) { + fn print_script_and_coin(script: &Script, coin: &dyn SwapCoin, network: Network) { let contract_tx = coin.get_contract_tx(); println!( "{} {}:{} {}", - Address::p2wsh(script, NETWORK), + Address::p2wsh(script, network), contract_tx.input[0].previous_output.txid, contract_tx.input[0].previous_output.vout, if coin.is_hash_preimage_known() { @@ -508,6 +502,7 @@ impl Wallet { pub fn load_wallet_from_file>( wallet_file_name: P, + network: Network, sync_amount: WalletSyncAddressAmount, ) -> Result { let wallet_file_name = wallet_file_name @@ -527,7 +522,7 @@ impl Wallet { let seed = mnemonic_ret .unwrap() .to_seed(Some(&wallet_file_data.extension)); - let xprv = ExtendedPrivKey::new_master(NETWORK, &seed.0).unwrap(); + let xprv = ExtendedPrivKey::new_master(network, &seed.0).unwrap(); log::debug!(target: "wallet", "loaded wallet file, external_index={} incoming_swapcoins={} outgoing_swapcoins={}", @@ -535,6 +530,7 @@ impl Wallet { wallet_file_data.incoming_swapcoins.len(), wallet_file_data.outgoing_swapcoins.len()); let wallet = Wallet { + network, master_key: xprv, wallet_file_name, external_index: wallet_file_data.external_index, @@ -861,7 +857,7 @@ impl Wallet { .values() .map(|osc| { ( - Address::p2wsh(&osc.contract_redeemscript, NETWORK).script_pubkey(), + contracts::redeemscript_to_scriptpubkey(&osc.contract_redeemscript), osc, ) }) @@ -875,7 +871,7 @@ impl Wallet { .values() .map(|isc| { ( - Address::p2wsh(&isc.contract_redeemscript, NETWORK).script_pubkey(), + contracts::redeemscript_to_scriptpubkey(&isc.contract_redeemscript), isc, ) }) @@ -1653,7 +1649,7 @@ pub fn import_redeemscript( redeemscript: &Script, address_label: &String, ) -> Result<(), bitcoincore_rpc::Error> { - let spk = Address::p2wsh(&redeemscript, NETWORK).script_pubkey(); + let spk = contracts::redeemscript_to_scriptpubkey(&redeemscript); let result = rpc.import_multi( &[ImportMultiRequest { timestamp: ImportMultiRescanSince::Now, diff --git a/src/watchtower_protocol.rs b/src/watchtower_protocol.rs index 503c4324..6805dd4b 100644 --- a/src/watchtower_protocol.rs +++ b/src/watchtower_protocol.rs @@ -14,7 +14,7 @@ use tokio::time::sleep; use serde::{Deserialize, Serialize}; use bitcoin::hashes::{hash160::Hash as Hash160, Hash}; -use bitcoin::{Address, Script, Transaction, Txid}; +use bitcoin::{Address, Network, Script, Transaction, Txid}; use bitcoincore_rpc::{ json::{GetBlockResult, ListTransactionResult}, Client, RpcApi, @@ -25,7 +25,7 @@ use crate::contracts::{ read_locktime_from_contract, read_timelock_pubkey_from_contract, }; use crate::error::Error; -use crate::wallet_sync::{import_redeemscript, NETWORK}; +use crate::wallet_sync::import_redeemscript; //TODO these two structs below are used for two different purposes //one purpose is as a message format for messages sent down the wire @@ -108,7 +108,7 @@ impl ContractsInfoDisplay { .iter() .map(|ctx| ContractTransactionDisplay { _tx: ctx.tx.txid(), - _redeemscript: Address::p2wsh(&ctx.redeemscript, NETWORK), + _redeemscript: Address::p2wsh(&ctx.redeemscript, Network::Regtest), _hashlock_spend_without_preimage: ctx .hashlock_spend_without_preimage .as_ref() @@ -122,14 +122,14 @@ impl ContractsInfoDisplay { } #[tokio::main] -pub async fn start_watchtower(rpc: &Client, kill_flag: Arc>) { - match run(rpc, kill_flag).await { +pub async fn start_watchtower(rpc: &Client, network: Network, kill_flag: Arc>) { + match run(rpc, network, kill_flag).await { Ok(_o) => log::info!("watchtower ended without error"), Err(e) => log::info!("watchtower ended with err {:?}", e), }; } -async fn run(rpc: &Client, kill_flag: Arc>) -> Result<(), Error> { +async fn run(rpc: &Client, network: Network, kill_flag: Arc>) -> Result<(), Error> { //TODO port number in config file let port = 6103; let listener = TcpListener::bind((Ipv4Addr::LOCALHOST, port)).await?; @@ -176,6 +176,7 @@ async fn run(rpc: &Client, kill_flag: Arc>) -> Result<(), Error> { _ = sleep(Duration::from_secs(10)) => { accepting_clients = run_contract_checks( &rpc, + network, &mut coinswap_in_progress_contracts, &mut last_checked_block_height, &mut live_contracts, @@ -298,6 +299,7 @@ async fn handle_message( fn run_contract_checks( rpc: &Client, + network: Network, coinswap_in_progress_contracts: &mut Vec, last_checked_block_height: &mut Option, live_contracts: &mut Vec, @@ -324,7 +326,7 @@ fn run_contract_checks( last_checked_block_height, )?; if !broadcasted_contracts.is_empty() { - import_broadcasted_contract_redeemscripts(rpc, &broadcasted_contracts)?; + import_broadcasted_contract_redeemscripts(rpc, network, &broadcasted_contracts)?; //remove broadcasted_contracts from the vec coinswap_in_progress_contracts coinswap_in_progress_contracts.retain(|cipc| { broadcasted_contracts @@ -454,6 +456,7 @@ pub fn check_for_broadcasted_contract_txes( fn import_broadcasted_contract_redeemscripts( rpc: &Client, + network: Network, broadcasted_contracts: &[ContractsInfo], ) -> Result<(), bitcoincore_rpc::Error> { log::debug!( @@ -463,7 +466,7 @@ fn import_broadcasted_contract_redeemscripts( .map(|ci| ci .contract_txes .iter() - .map(|ctx| Address::p2wsh(&ctx.redeemscript, NETWORK)) + .map(|ctx| Address::p2wsh(&ctx.redeemscript, network)) .collect::>()) .collect::>>() ); diff --git a/tests/test_standard_coinswap.rs b/tests/test_standard_coinswap.rs index c000e42f..556d780d 100644 --- a/tests/test_standard_coinswap.rs +++ b/tests/test_standard_coinswap.rs @@ -1,4 +1,5 @@ use bitcoin::util::amount::Amount; +use bitcoin::Network; use bitcoin_wallet::mnemonic; use bitcoincore_rpc::{Client, RpcApi}; @@ -25,7 +26,9 @@ fn create_wallet_and_import(rpc: &Client, filename: PathBuf) -> Wallet { Wallet::save_new_wallet_file(&filename, mnemonic.to_string(), "".to_string()).unwrap(); - let wallet = Wallet::load_wallet_from_file(filename, WalletSyncAddressAmount::Testing).unwrap(); + let wallet = + Wallet::load_wallet_from_file(filename, Network::Regtest, WalletSyncAddressAmount::Testing) + .unwrap(); // import intital addresses to core wallet .import_initial_addresses( @@ -53,7 +56,8 @@ pub fn generate_1_block(rpc: &Client) { async fn test_standard_coinswap() { teleport::setup_logger(); - let rpc = teleport::get_bitcoin_rpc().unwrap(); + let (rpc, network) = teleport::get_bitcoin_rpc().unwrap(); + assert_eq!(network, Network::Regtest); // unlock all utxos to avoid "insufficient fund" error rpc.call::("lockunspent", &[Value::Bool(true)]) @@ -179,7 +183,7 @@ async fn test_standard_coinswap() { let taker_thread = thread::spawn(|| { // Wait and then start the taker - thread::sleep(time::Duration::from_secs(5)); + thread::sleep(time::Duration::from_secs(20)); teleport::run_taker( &PathBuf::from_str(TAKER).unwrap(), WalletSyncAddressAmount::Testing, @@ -210,18 +214,22 @@ async fn test_standard_coinswap() { // Recreate the wallet let taker_wallet = - Wallet::load_wallet_from_file(&TAKER, WalletSyncAddressAmount::Testing).unwrap(); + Wallet::load_wallet_from_file(&TAKER, Network::Regtest, WalletSyncAddressAmount::Testing) + .unwrap(); let maker1_wallet = - Wallet::load_wallet_from_file(&MAKER1, WalletSyncAddressAmount::Testing).unwrap(); + Wallet::load_wallet_from_file(&MAKER1, Network::Regtest, WalletSyncAddressAmount::Testing) + .unwrap(); let maker2_wallet = - Wallet::load_wallet_from_file(&MAKER2, WalletSyncAddressAmount::Testing).unwrap(); + Wallet::load_wallet_from_file(&MAKER2, Network::Regtest, WalletSyncAddressAmount::Testing) + .unwrap(); // Check assertions assert_eq!(taker_wallet.get_swapcoins_count(), 6); assert_eq!(maker1_wallet.get_swapcoins_count(), 6); assert_eq!(maker2_wallet.get_swapcoins_count(), 6); - let rpc = teleport::get_bitcoin_rpc().unwrap(); + let (rpc, network) = teleport::get_bitcoin_rpc().unwrap(); + assert_eq!(network, Network::Regtest); let utxos = taker_wallet.list_unspent_from_wallet(&rpc, false).unwrap(); let balance: Amount = utxos