From 11f490fd4b58f6bf44927d4587cd84caf076b605 Mon Sep 17 00:00:00 2001 From: HalFinneyIsMyHomeBoy Date: Tue, 4 Feb 2025 17:07:32 +0000 Subject: [PATCH] Fallback to cookie file if UserPass fails --- Cargo.toml | 2 ++ src/config.rs | 84 ++++++++++++++++++++++++++++++++++++++++----------- src/main.rs | 7 +++-- 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6b84896..9dbace5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,8 @@ edition = "2021" rand = "0.8.5" bitcoin = "0.32.4" bitcoincore-rpc = "0.19.0" +tracing = "0.1.41" +anyhow = "1.0.95" [features] default = ["regtest"] diff --git a/src/config.rs b/src/config.rs index eddac94..5f01f08 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,8 +1,7 @@ -use std::env; - use bitcoin::Network; - -use bitcoincore_rpc::{Auth, Client, RpcApi}; +use tracing::{error, info}; +use std::path::PathBuf; +use bitcoincore_rpc::{Auth, Client, RpcApi, Error}; // https://bitcoinops.org/en/bitcoin-core-28-wallet-integration-guide/ // mainnet: bc1pfeessrawgf @@ -32,7 +31,7 @@ impl NetworkConfig { #[cfg(feature = "signet")] { let wallet_name = env::var("SIGNET_WALLET").expect("SIGNET_WALLET env var not set"); - println!("wallet name: {}", wallet_name); + info!("wallet name: {} \n", wallet_name); return Self { network: Network::Signet, port: "38332", @@ -43,32 +42,81 @@ impl NetworkConfig { //wen mainnet } - pub fn bitcoin_rpc(&self) -> Client { - let bitcoin_rpc_user = - env::var("BITCOIN_RPC_USER").expect("BITCOIN_RPC_USER env var not set"); - let bitcoin_rpc_pass = - env::var("BITCOIN_RPC_PASS").expect("BITCOIN_RPC_PASS env var not set"); + pub fn get_env_var(var_name: &str, default_value: &str) -> String { + std::env::var(var_name).unwrap_or_else(|_| default_value.to_string()) + } + + pub fn bitcoin_rpc(&self) -> Result { + let bitcoin_rpc_user = Self::get_env_var("BITCOIN_RPC_USER", "NA"); + let bitcoin_rpc_pass = Self::get_env_var("BITCOIN_RPC_PASS", "NA"); + let bitcoin_rpc_cookie_path = Self::get_env_var("BITCOIN_RPC_COOKIE_PATH", "NA"); let bitcoin_rpc_url = format!("http://localhost:{}/wallet/{}", self.port, self.wallet_name,); - println!("wallet name in use: {}", self.wallet_name); + info!("wallet name in use: {} \n", self.wallet_name); + + //Check if user/pass or cookie is found in enviroment variables. + //If both are found, UserPass will be tried first. + let test_auth = if bitcoin_rpc_user != "NA" && bitcoin_rpc_pass != "NA" { + Auth::UserPass(bitcoin_rpc_user.to_string(), bitcoin_rpc_pass.to_string()) + } else if bitcoin_rpc_cookie_path != "NA" { + Auth::CookieFile(PathBuf::from(bitcoin_rpc_cookie_path.clone())) + } else { + error!("No User/Pass or Cookie found!"); + return Err(Error::InvalidCookieFile); + }; + + let test_bitcoin_rpc_userpass = Client::new(&bitcoin_rpc_url, test_auth)?; + + let bitcoin_rpc = match test_bitcoin_rpc_userpass.get_best_block_hash() { + Ok(_) => { + //UserPass authentication succeeded + test_bitcoin_rpc_userpass + } + Err(e) => { + if &bitcoin_rpc_cookie_path == "NA" { + error!("UserPass failed and no cookie file was found!"); + return Err(Error::ReturnedError(e.to_string())); + } + + info!("UserPass would not authenticate, trying CookieFile now"); + + match Client::new( + &bitcoin_rpc_url, + Auth::CookieFile(PathBuf::from(&bitcoin_rpc_cookie_path)), + ) { + Ok(test_bitcoin_rpc_cookiefile) => { + match test_bitcoin_rpc_cookiefile.get_best_block_hash() { + Ok(_) => { + info!("Cookie File authentication succeeded!"); + test_bitcoin_rpc_cookiefile + } - let bitcoin_rpc = Client::new( - &bitcoin_rpc_url, - Auth::UserPass(bitcoin_rpc_user, bitcoin_rpc_pass), - ) - .unwrap(); + Err(e) => { + //Both Userpass and cookie have failed + error!("Cookie File authenication failed!: {}", e); + return Err(Error::InvalidCookieFile {}); + } + } + } + Err(e) => { + error!("{}", e); + return Err(Error::InvalidCookieFile {}); + } + } + } + }; #[cfg(feature = "regtest")] let regtest_wallet = bitcoin_rpc.create_wallet(&self.wallet_name, None, None, None, None); #[cfg(feature = "regtest")] if regtest_wallet.is_ok() { - println!("regtest wallet created") + info!("regtest wallet created \n") } let _ = bitcoin_rpc.load_wallet(&self.wallet_name); - bitcoin_rpc + Ok(bitcoin_rpc) } } diff --git a/src/main.rs b/src/main.rs index 044235a..ae3d9e3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use bitcoincore_rpc::RpcApi; use config::NetworkConfig; +use anyhow::Result; use ctv_scripts::{calc_ctv_hash, create_ctv_address, spend_ctv}; use rpc_helper::{get_vout, get_vout_after_confirmation, send_funding_transaction}; @@ -25,9 +26,9 @@ const CPFP_FEE_AMOUNT: Amount = Amount::from_sat(69180); //this is the min dust amount required to anchor the transaction const ANCHOR_AMOUNT: Amount = Amount::from_sat(240); -fn main() { +fn main() -> Result<()> { let config = NetworkConfig::new(); - let rpc = config.bitcoin_rpc(); + let rpc = config.bitcoin_rpc()?; let ctv_spend_to_address = rpc .get_new_address(None, None) @@ -170,4 +171,6 @@ fn main() { #[cfg(feature = "regtest")] let _ = rpc.generate_to_address(1, &ctv_spend_to_address); + + Ok(()) }