diff --git a/src/bin/bal-pusher.rs b/src/bin/bal-pusher.rs index 4d95899..b84a974 100644 --- a/src/bin/bal-pusher.rs +++ b/src/bin/bal-pusher.rs @@ -58,7 +58,7 @@ impl Default for MyConfig { send_stats: env::var("BAL_PUSHER_SEND_STATS") .unwrap_or("false".to_string()) .parse::() - .unwrap(), + .unwrap_or(false), url: env::var("BAL_SERVER_URL").unwrap_or("http://localhost/".to_string()), ssl_key_path: env::var("SSL_KEY_PATH").unwrap_or("privkey.pem".to_string()), } @@ -481,7 +481,12 @@ fn parse_env_netconfig(cfg_lock: &mut MyConfig, chain: &str) -> NetworkParams { match env::var(format!("BAL_PUSHER_{}_PORT", chain.to_uppercase())) { Ok(value) => match value.parse::() { Ok(value) => { - cfg.port = value.try_into().unwrap(); + match u16::try_from(value) { + Ok(port) => cfg.port = port, + Err(e) => { + error!("Port value {} exceeds u16 range for chain {}: {}", value, chain, e); + } + } } Err(_) => {} }, diff --git a/src/bin/bal-server.rs b/src/bin/bal-server.rs index ecdb880..0e8b358 100644 --- a/src/bin/bal-server.rs +++ b/src/bin/bal-server.rs @@ -259,13 +259,21 @@ async fn echo_info( Some(address) => address, None => { let next = get_next_address_index(&db, &netconfig.name, &netconfig.address); - let address = - new_address_from_xpub(&netconfig.address, next.1, netconfig.network) - .unwrap(); + match new_address_from_xpub(&netconfig.address, next.1, netconfig.network) { + Ok(address) => { save_new_address(&db, next.0, &address.0, &address.1, &remote_addr); debug!("save new address {} {}", address.0, address.1); trace!("next {} {}", next.0, next.1); address.0 + } + Err(e) => { + error!("Failed to derive address from xpub: {}", e); + // Return error response to the client + let mut response = Response::new(full(format!("Failed to derive address: {}", e))); + *response.status_mut() = StatusCode::BAD_REQUEST; + return Ok(response); + } + } } } } diff --git a/src/xpub.rs b/src/xpub.rs index 38e41f9..e00049a 100644 --- a/src/xpub.rs +++ b/src/xpub.rs @@ -103,7 +103,11 @@ fn calc_checksum(desc: &str) -> Result { } pub fn get_bitcoincore_descriptor(xpub: &String) -> String { - let fingerprint = calculate_fingerprint(xpub); + let fingerprint = match calculate_fingerprint(xpub) { + Ok(f) => f, + Err(_) => return String::new(), // Invalid xpub, return empty descriptor + }; + let mut bip = 84; let cpub = xpub.to_string(); match &xpub[0..4] { @@ -117,10 +121,14 @@ pub fn get_bitcoincore_descriptor(xpub: &String) -> String { bip = 84; } }; + let xpub_converted = match convert_xpub(xpub) { + Ok(c) => c, + Err(_) => return String::new(), // Invalid xpub, return empty descriptor + }; let descriptor = format!( "wpkh([{}/84h/0h/0h]{}/0/*)", fingerprint, - convert_xpub(xpub) + xpub_converted ); let descriptor = match calc_checksum(&descriptor) { Ok(checksum) => { @@ -135,18 +143,20 @@ pub fn get_bitcoincore_descriptor(xpub: &String) -> String { descriptor //format!("{}#{}",descriptor,checksum) } -fn convert_xpub(xpub: &String) -> String { - if xpub[0..4] == *"xpub" || xpub[0..4] == *"ypub" || xpub[0..4] == *"zpub" { - return convert_to(xpub, BS58Prefix::Xpub).unwrap(); +fn convert_xpub(xpub: &String) -> Result { + if xpub.len() >= 4 && (&xpub[0..4] == "xpub" || &xpub[0..4] == "ypub" || &xpub[0..4] == "zpub") { + convert_to(xpub, BS58Prefix::Xpub) + } else if xpub.len() >= 4 && (&xpub[0..4] == "tpub" || &xpub[0..4] == "vpub" || &xpub[0..4] == "upub") { + convert_to(xpub, BS58Prefix::Tpub) } else { - return convert_to(xpub, BS58Prefix::Tpub).unwrap(); + Err("Invalid xpub prefix: expected xpub, ypub, zpub, tpub, vpub, or upub".to_string()) } } -pub fn calculate_fingerprint(tpub: &str) -> String { - let xpub = Xpub::from_str(&convert_to(tpub, BS58Prefix::Xpub).unwrap()).unwrap(); +pub fn calculate_fingerprint(tpub: &str) -> Result { + let xpub = Xpub::from_str(&convert_to(tpub, BS58Prefix::Xpub)?).map_err(|e| format!("Invalid xpub: {}", e))?; let fp = xpub.fingerprint(); - let pp = xpub.parent_fingerprint; - format!("{}", fp) + let _pp = xpub.parent_fingerprint; + Ok(format!("{}", fp)) } fn base58check_decode(s: &str) -> Result, String> {