Skip to content

Commit

Permalink
Handle errors properly instead of unwraps.
Browse files Browse the repository at this point in the history
  • Loading branch information
rajarshimaitra committed Dec 8, 2021
1 parent 7aa4c7a commit 2be6cd9
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 65 deletions.
56 changes: 25 additions & 31 deletions src/bdk_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,31 +100,33 @@ pub enum ReplSubCommand {
Exit,
}

fn prepare_home_dir() -> PathBuf {
fn prepare_home_dir() -> Result<PathBuf, Error> {
let mut dir = PathBuf::new();
dir.push(&dirs_next::home_dir().unwrap());
dir.push(
&dirs_next::home_dir().ok_or_else(|| Error::Generic("home dir not found".to_string()))?,
);
dir.push(".bdk-bitcoin");

if !dir.exists() {
info!("Creating home directory {}", dir.as_path().display());
fs::create_dir(&dir).unwrap();
fs::create_dir(&dir).map_err(|e| Error::Generic(e.to_string()))?;
}

#[cfg(not(feature = "compact_filters"))]
dir.push("database.sled");

#[cfg(feature = "compact_filters")]
dir.push("compact_filters");
dir
Ok(dir)
}

fn open_database(wallet_opts: &WalletOpts) -> Tree {
let mut database_path = prepare_home_dir();
fn open_database(wallet_opts: &WalletOpts) -> Result<Tree, Error> {
let mut database_path = prepare_home_dir()?;
database_path.push(wallet_opts.wallet.clone());
let database = sled::open(database_path).unwrap();
let tree = database.open_tree(&wallet_opts.wallet).unwrap();
let database = sled::open(database_path)?;
let tree = database.open_tree(&wallet_opts.wallet)?;
debug!("database opened successfully");
tree
Ok(tree)
}

#[cfg(any(
Expand Down Expand Up @@ -183,7 +185,10 @@ where
AnyBlockchainConfig::CompactFilters(CompactFiltersBlockchainConfig {
peers,
network,
storage_dir: prepare_home_dir().into_os_string().into_string().unwrap(),
storage_dir: prepare_home_dir()?
.into_os_string()
.into_string()
.map_err(|_| Error::Generic("Internal OS_String conversion error".to_string()))?,
skip_blocks: Some(wallet_opts.compactfilter_opts.skip_blocks),
})
};
Expand Down Expand Up @@ -277,7 +282,7 @@ fn handle_command(cli_opts: CliOpts, network: Network) -> Result<String, Error>
wallet_opts,
subcommand: WalletSubCommand::OnlineWalletSubCommand(online_subcommand),
} => {
let database = open_database(&wallet_opts);
let database = open_database(&wallet_opts)?;
let wallet = new_online_wallet(network, &wallet_opts, database)?;
let result = bdk_cli::handle_online_wallet_subcommand(&wallet, online_subcommand)?;
serde_json::to_string_pretty(&result)?
Expand All @@ -286,7 +291,7 @@ fn handle_command(cli_opts: CliOpts, network: Network) -> Result<String, Error>
wallet_opts,
subcommand: WalletSubCommand::OfflineWalletSubCommand(offline_subcommand),
} => {
let database = open_database(&wallet_opts);
let database = open_database(&wallet_opts)?;
let wallet = new_offline_wallet(network, &wallet_opts, database)?;
let result = bdk_cli::handle_offline_wallet_subcommand(
&wallet,
Expand All @@ -311,7 +316,7 @@ fn handle_command(cli_opts: CliOpts, network: Network) -> Result<String, Error>
}
#[cfg(feature = "repl")]
CliSubCommand::Repl { wallet_opts } => {
let database = open_database(&wallet_opts);
let database = open_database(&wallet_opts)?;

#[cfg(any(
feature = "electrum",
Expand Down Expand Up @@ -349,24 +354,17 @@ fn handle_command(cli_opts: CliOpts, network: Network) -> Result<String, Error>
let split_line: Vec<&str> = split_regex
.captures_iter(&line)
.map(|c| {
c.get(1)
Ok(c.get(1)
.or_else(|| c.get(2))
.or_else(|| c.get(3))
.unwrap()
.as_str()
.ok_or_else(|| Error::Generic("Invalid commands".to_string()))?
.as_str())
})
.collect();
let repl_subcommand: Result<ReplSubCommand, clap::Error> =
ReplSubCommand::from_iter_safe(split_line);
.collect::<Result<Vec<_>, Error>>()?;
let repl_subcommand = ReplSubCommand::from_iter_safe(split_line)
.map_err(|e| Error::Generic(e.to_string()))?;
debug!("repl_subcommand = {:?}", repl_subcommand);

if let Err(err) = repl_subcommand {
println!("{}", err.message);
continue;
}

let repl_subcommand = repl_subcommand.unwrap();

let result = match repl_subcommand {
#[cfg(any(
feature = "electrum",
Expand All @@ -390,10 +388,7 @@ fn handle_command(cli_opts: CliOpts, network: Network) -> Result<String, Error>
ReplSubCommand::Exit => break,
};

println!(
"{}",
serde_json::to_string_pretty(&result.unwrap()).unwrap()
);
println!("{}", serde_json::to_string_pretty(&result?)?);
}
Err(ReadlineError::Interrupted) => continue,
Err(ReadlineError::Eof) => break,
Expand All @@ -404,7 +399,6 @@ fn handle_command(cli_opts: CliOpts, network: Network) -> Result<String, Error>
}
}

// rl.save_history("history.txt").unwrap();
"Exiting REPL".to_string()
}
};
Expand Down
67 changes: 33 additions & 34 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -816,17 +816,10 @@ fn parse_recipient(s: &str) -> Result<(Script, u64), String> {
if parts.len() != 2 {
return Err("Invalid format".to_string());
}
let addr = Address::from_str(parts[0]).map_err(|e| e.to_string())?;
let val = u64::from_str(parts[1]).map_err(|e| e.to_string())?;

let addr = Address::from_str(parts[0]);
if let Err(e) = addr {
return Err(format!("{:?}", e));
}
let val = u64::from_str(parts[1]);
if let Err(e) = val {
return Err(format!("{:?}", e));
}

Ok((addr.unwrap().script_pubkey(), val.unwrap()))
Ok((addr.script_pubkey(), val))
}
#[cfg(any(
feature = "electrum",
Expand All @@ -847,7 +840,7 @@ fn parse_proxy_auth(s: &str) -> Result<(String, String), String> {
}

fn parse_outpoint(s: &str) -> Result<OutPoint, String> {
OutPoint::from_str(s).map_err(|e| format!("{:?}", e))
OutPoint::from_str(s).map_err(|e| e.to_string())
}

/// Execute an offline wallet sub-command
Expand Down Expand Up @@ -972,8 +965,8 @@ where
psbt,
assume_height,
} => {
let psbt = base64::decode(&psbt).unwrap();
let mut psbt: PartiallySignedTransaction = deserialize(&psbt).unwrap();
let psbt = base64::decode(&psbt).map_err(|e| Error::Generic(e.to_string()))?;
let mut psbt: PartiallySignedTransaction = deserialize(&psbt)?;
let signopt = SignOptions {
assume_height,
..Default::default()
Expand All @@ -988,16 +981,16 @@ where
}
}
ExtractPsbt { psbt } => {
let psbt = base64::decode(&psbt).unwrap();
let psbt: PartiallySignedTransaction = deserialize(&psbt).unwrap();
let psbt = base64::decode(&psbt).map_err(|e| Error::Generic(e.to_string()))?;
let psbt: PartiallySignedTransaction = deserialize(&psbt)?;
Ok(json!({"raw_tx": serialize_hex(&psbt.extract_tx()),}))
}
FinalizePsbt {
psbt,
assume_height,
} => {
let psbt = base64::decode(&psbt).unwrap();
let mut psbt: PartiallySignedTransaction = deserialize(&psbt).unwrap();
let psbt = base64::decode(&psbt).map_err(|e| Error::Generic(e.to_string()))?;
let mut psbt: PartiallySignedTransaction = deserialize(&psbt)?;

let signopt = SignOptions {
assume_height,
Expand All @@ -1016,13 +1009,15 @@ where
let mut psbts = psbt
.iter()
.map(|s| {
let psbt = base64::decode(&s).unwrap();
let psbt: PartiallySignedTransaction = deserialize(&psbt).unwrap();
psbt
let psbt = base64::decode(&s).map_err(|e| Error::Generic(e.to_string()))?;
let psbt: PartiallySignedTransaction = deserialize(&psbt)?;
Ok(psbt)
})
.collect::<Vec<_>>();
.collect::<Result<Vec<_>, Error>>()?;

let init_psbt = psbts.pop().unwrap();
let init_psbt = psbts
.pop()
.ok_or_else(|| Error::Generic("Invalid PSBT input".to_string()))?;
let final_psbt = psbts
.into_iter()
.try_fold::<_, _, Result<PartiallySignedTransaction, Error>>(
Expand Down Expand Up @@ -1064,11 +1059,11 @@ where
Broadcast { psbt, tx } => {
let tx = match (psbt, tx) {
(Some(psbt), None) => {
let psbt = base64::decode(&psbt).unwrap();
let psbt: PartiallySignedTransaction = deserialize(&psbt).unwrap();
let psbt = base64::decode(&psbt).map_err(|e| Error::Generic(e.to_string()))?;
let psbt: PartiallySignedTransaction = deserialize(&psbt)?;
psbt.extract_tx()
}
(None, Some(tx)) => deserialize(&Vec::<u8>::from_hex(&tx).unwrap()).unwrap(),
(None, Some(tx)) => deserialize(&Vec::<u8>::from_hex(&tx)?)?,
(Some(_), Some(_)) => panic!("Both `psbt` and `tx` options not allowed"),
(None, None) => panic!("Missing `psbt` and `tx` option"),
};
Expand Down Expand Up @@ -1149,11 +1144,13 @@ pub fn handle_key_subcommand(
_ => WordCount::Words24,
};
let mnemonic: GeneratedKey<_, miniscript::BareCtx> =
Mnemonic::generate((mnemonic_type, Language::English)).unwrap();
//.map_err(|e| KeyError::from(e.unwrap()))?;
Mnemonic::generate((mnemonic_type, Language::English))
.map_err(|_| Error::Generic("Mnemonic generation error".to_string()))?;
let mnemonic = mnemonic.into_key();
let xkey: ExtendedKey = (mnemonic.clone(), password).into_extended_key()?;
let xprv = xkey.into_xprv(network).unwrap();
let xprv = xkey.into_xprv(network).ok_or_else(|| {
Error::Generic("Privatekey info not found (should not happen)".to_string())
})?;
let fingerprint = xprv.fingerprint(&secp);
let phrase = mnemonic
.word_iter()
Expand All @@ -1165,12 +1162,12 @@ pub fn handle_key_subcommand(
)
}
KeySubCommand::Restore { mnemonic, password } => {
let mnemonic = Mnemonic::parse(mnemonic).unwrap();
// .map_err(|e| {
// KeyError::from(e.downcast::<bdk::keys::bip39::ErrorKind>().unwrap())
// })?;
let mnemonic = Mnemonic::parse_in(Language::English, mnemonic)
.map_err(|e| Error::Generic(e.to_string()))?;
let xkey: ExtendedKey = (mnemonic, password).into_extended_key()?;
let xprv = xkey.into_xprv(network).unwrap();
let xprv = xkey.into_xprv(network).ok_or_else(|| {
Error::Generic("Privatekey info not found (should not happen)".to_string())
})?;
let fingerprint = xprv.fingerprint(&secp);

Ok(json!({ "xprv": xprv.to_string(), "fingerprint": fingerprint.to_string() }))
Expand All @@ -1187,7 +1184,9 @@ pub fn handle_key_subcommand(
derived_xprv.into_descriptor_key(Some(origin), DerivationPath::default())?;

if let Secret(desc_seckey, _, _) = derived_xprv_desc_key {
let desc_pubkey = desc_seckey.as_public(&secp).unwrap();
let desc_pubkey = desc_seckey
.as_public(&secp)
.map_err(|e| Error::Generic(e.to_string()))?;
Ok(json!({"xpub": desc_pubkey.to_string(), "xprv": desc_seckey.to_string()}))
} else {
Err(Error::Key(Message("Invalid key variant".to_string())))
Expand Down

0 comments on commit 2be6cd9

Please sign in to comment.