Skip to content

Commit 3bcc83d

Browse files
committed
Enhance error handling and improve messages
1 parent 2bbffb4 commit 3bcc83d

File tree

3 files changed

+73
-34
lines changed

3 files changed

+73
-34
lines changed

src/api/client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub async fn send_job_with_uploader_to_remote(
9797
// Check that PDA exists before sending job
9898
let genesis_hash = get_genesis_hash(connection)?;
9999
if genesis_hash != MAINNET_GENESIS_HASH {
100-
return Err(anyhow!("Remote verification only works with mainnet. Please omit the --remote flag to verify locally."));
100+
return Err(anyhow!("Remote verification service only supports mainnet. You're currently connected to a different network.\n\nTo use remote verification:\n• Connect to mainnet with: --url mainnet\n• Or remove the --remote flag to verify locally"));
101101
}
102102
get_program_pda(connection, program_id, Some(uploader.to_string()), None).await?;
103103

src/main.rs

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -604,11 +604,17 @@ fn get_commit_hash_from_remote(repo_url: &str) -> anyhow::Result<String> {
604604
.arg("--symref")
605605
.arg(repo_url)
606606
.output()
607-
.map_err(|e| anyhow::anyhow!("Failed to run git ls-remote: {}", e))?;
607+
.map_err(|e| {
608+
anyhow::anyhow!(
609+
"Failed to fetch repository information using git.\nError: {}",
610+
e
611+
)
612+
})?;
608613

609614
if !output.status.success() {
610615
return Err(anyhow::anyhow!(
611-
"Failed to fetch default branch information: {}",
616+
"Failed to fetch default branch information from repository '{}'.\nGit error: {}",
617+
repo_url,
612618
String::from_utf8_lossy(&output.stderr)
613619
));
614620
}
@@ -631,7 +637,7 @@ fn get_commit_hash_from_remote(repo_url: &str) -> anyhow::Result<String> {
631637
})
632638
.ok_or_else(|| {
633639
anyhow::anyhow!(
634-
"Unable to determine default branch from remote repository '{}'",
640+
"Unable to determine default branch from repository '{}'",
635641
repo_url
636642
)
637643
})?;
@@ -644,11 +650,13 @@ fn get_commit_hash_from_remote(repo_url: &str) -> anyhow::Result<String> {
644650
.arg(repo_url)
645651
.arg(&default_branch)
646652
.output()
647-
.map_err(|e| anyhow::anyhow!("Failed to fetch commit hash for default branch: {}", e))?;
653+
.map_err(|e| anyhow::anyhow!("Failed to fetch commit hash for default branch '{}' from repository '{}'.\nError: {}", default_branch, repo_url, e))?;
648654

649655
if !hash_output.status.success() {
650656
return Err(anyhow::anyhow!(
651-
"Failed to fetch commit hash: {}",
657+
"Failed to fetch commit hash for branch '{}' from repository '{}'.\nGit error: {}",
658+
default_branch,
659+
repo_url,
652660
String::from_utf8_lossy(&hash_output.stderr)
653661
));
654662
}
@@ -780,7 +788,7 @@ pub fn build(
780788
let lockfile = format!("{}/Cargo.lock", mount_path);
781789
if !std::path::Path::new(&lockfile).exists() {
782790
println!("Mount directory must contain a Cargo.lock file");
783-
return Err(anyhow!(format!("No lockfile found at {}", lockfile)));
791+
return Err(anyhow!("Missing Cargo.lock file at '{}'", lockfile));
784792
}
785793

786794
// Check if --offline flag is present in cargo_args
@@ -808,10 +816,12 @@ pub fn build(
808816
solana_version = Some(format!("v{}.{}.{}", major, minor, patch));
809817
format!("solanafoundation/solana-verifiable-build@{}", digest)
810818
} else {
811-
return Err(anyhow!(format!(
812-
"Unable to find docker image for Solana version {}.{}.{}",
813-
major, minor, patch
814-
)));
819+
return Err(anyhow!(
820+
"No compatible Docker image found for Solana version {}.{}.{}",
821+
major,
822+
minor,
823+
patch
824+
));
815825
}
816826
}
817827
};
@@ -848,15 +858,17 @@ pub fn build(
848858
}
849859
}
850860
}
851-
Err(anyhow!("No Cargo.toml files found"))
861+
Err(anyhow!(
862+
"No valid Cargo.toml files found in the project directory"
863+
))
852864
})
853865
.unwrap_or_else(|_| "".to_string());
854866

855867
let workdir = std::process::Command::new("docker")
856868
.args(["run", "--rm", &image, "pwd"])
857869
.stderr(Stdio::inherit())
858870
.output()
859-
.map_err(|e| anyhow::format_err!("Failed to get workdir: {}", e.to_string()))
871+
.map_err(|e| anyhow::format_err!("Failed to get working directory : {}", e.to_string()))
860872
.and_then(parse_output)?;
861873

862874
println!("Workdir: {}", workdir);
@@ -894,7 +906,7 @@ pub fn build(
894906
let output = cmd
895907
.args([&image, "bash"])
896908
.output()
897-
.map_err(|e| anyhow!("Docker build failed: {}", e.to_string()))?;
909+
.map_err(|e| anyhow!("Failed to start Docker container : {}", e.to_string()))?;
898910

899911
parse_output(output)?
900912
};
@@ -1000,7 +1012,7 @@ pub fn verify_from_image(
10001012
.args(["run", "--rm", &image, "pwd"])
10011013
.stderr(Stdio::inherit())
10021014
.output()
1003-
.map_err(|e| anyhow::format_err!("Failed to get workdir: {}", e.to_string()))
1015+
.map_err(|e| anyhow::format_err!("Failed to get working directory : {}", e.to_string()))
10041016
.and_then(parse_output)?;
10051017

10061018
println!("Workdir: {}", workdir);
@@ -1020,7 +1032,7 @@ pub fn verify_from_image(
10201032
let output = cmd
10211033
.args([&image])
10221034
.output()
1023-
.map_err(|e| anyhow!("Docker build failed: {}", e.to_string()))?;
1035+
.map_err(|e| anyhow!("Failed to start Docker container : {}", e.to_string()))?;
10241036
parse_output(output)?
10251037
};
10261038

@@ -1120,7 +1132,7 @@ fn build_args(
11201132
)
11211133
})
11221134
.and_then(|output| {
1123-
ensure!(output.status.success(), "Failed to find Cargo.toml files in root directory");
1135+
ensure!(output.status.success(), "Failed to search for Cargo.toml in root directory");
11241136
let mut options = vec![];
11251137
for path in String::from_utf8(output.stdout)?.split("\n") {
11261138
match get_lib_name_from_cargo_toml(path) {
@@ -1141,7 +1153,8 @@ fn build_args(
11411153
"Please explicitly specify the target with the --library-name <name> option",
11421154
);
11431155
Err(anyhow::format_err!(
1144-
"Failed to find unique Cargo.toml file in root directory"
1156+
"Multiple library targets found: {:?}",
1157+
options
11451158
))
11461159
} else {
11471160
Ok(options[0].clone())
@@ -1204,15 +1217,16 @@ fn clone_repo_and_checkout(
12041217
.output()?;
12051218
ensure!(
12061219
output.status.success(),
1207-
"Failed to git clone the repository"
1220+
"Failed to clone repository '{}'",
1221+
repo_url
12081222
);
12091223

12101224
if let Some(commit_hash) = commit_hash.as_ref() {
12111225
let output = std::process::Command::new("git")
12121226
.args(["-C", &verify_tmp_root_path])
12131227
.args(["checkout", commit_hash])
12141228
.output()
1215-
.map_err(|e| anyhow!("Failed to checkout commit hash: {:?}", e))?;
1229+
.map_err(|e| anyhow!("Failed to checkout commit hash '{}' : {:?}", commit_hash, e))?;
12161230
if output.status.success() {
12171231
println!("Checked out commit hash: {}", commit_hash);
12181232
} else {
@@ -1221,10 +1235,13 @@ fn clone_repo_and_checkout(
12211235
.output()?;
12221236
ensure!(
12231237
output.status.success(),
1224-
"Failed to delete the verifiable build directory"
1238+
"Failed to clean up temporary directory"
12251239
);
12261240

1227-
Err(anyhow!("Encountered error in git setup"))?;
1241+
Err(anyhow!(
1242+
"Git checkout failed for commit hash '{}'",
1243+
commit_hash
1244+
))?;
12281245
}
12291246
}
12301247

@@ -1235,7 +1252,13 @@ fn get_basename(repo_url: &str) -> anyhow::Result<String> {
12351252
let base_name = std::process::Command::new("basename")
12361253
.arg(repo_url)
12371254
.output()
1238-
.map_err(|e| anyhow!("Failed to get basename of repo_url: {:?}", e))
1255+
.map_err(|e| {
1256+
anyhow!(
1257+
"Failed to extract repository name from URL '{}' : {:?}",
1258+
repo_url,
1259+
e
1260+
)
1261+
})
12391262
.and_then(parse_output)?;
12401263
Ok(base_name)
12411264
}

src/solana_program.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ fn create_ix_data(params: &InputParams, ix: &OtterVerifyInstructions) -> Vec<u8>
9595

9696
fn get_keypair_from_path(path: &str) -> anyhow::Result<Keypair> {
9797
solana_clap_utils::keypair::keypair_from_path(&Default::default(), path, "keypair", false)
98-
.map_err(|err| anyhow!("Unable to get signer from path: {}", err))
98+
.map_err(|err| anyhow!("Failed to load keypair from path '{}'. Please check that the file exists and contains a valid Solana keypair.\nError: {}", path, err))
9999
}
100100

101101
fn get_user_config_with_path(config_path: Option<String>) -> anyhow::Result<(Keypair, RpcClient)> {
@@ -104,7 +104,7 @@ fn get_user_config_with_path(config_path: Option<String>) -> anyhow::Result<(Key
104104
None => {
105105
let config_file = solana_cli_config::CONFIG_FILE
106106
.as_ref()
107-
.ok_or_else(|| anyhow!("Unable to get config file path"))?;
107+
.ok_or_else(|| anyhow!("Could not find Solana CLI configuration file. Please run 'solana config set --url <rpc-url>' to set up your configuration, or specify a custom config file with --config."))?;
108108
Config::load(config_file)?
109109
}
110110
};
@@ -194,7 +194,7 @@ fn process_otter_verify_ixs(
194194
.send_and_confirm_transaction_with_spinner(&tx)
195195
.map_err(|err| {
196196
println!("{:?}", err);
197-
anyhow!("Failed to send transaction to the network.")
197+
anyhow!("Failed to send verification transaction to the blockchain.")
198198
})?;
199199
println!("Program uploaded successfully. Transaction ID: {}", tx_id);
200200
Ok(())
@@ -264,7 +264,13 @@ pub async fn upload_program_verification_data(
264264

265265
let last_deployed_slot = get_last_deployed_slot(connection, &program_address.to_string())
266266
.await
267-
.map_err(|err| anyhow!("Unable to get last deployed slot: {}", err))?;
267+
.map_err(|err| {
268+
anyhow!(
269+
"Failed to retrieve deployment information for program {}.\nError: {}",
270+
program_address.to_string(),
271+
err
272+
)
273+
})?;
268274

269275
let input_params = InputParams {
270276
version: env!("CARGO_PKG_VERSION").to_string(),
@@ -347,7 +353,13 @@ pub async fn process_close(
347353

348354
let last_deployed_slot = get_last_deployed_slot(connection, &program_address.to_string())
349355
.await
350-
.map_err(|err| anyhow!("Unable to get last deployed slot: {}", err))?;
356+
.map_err(|err| {
357+
anyhow!(
358+
"Failed to retrieve deployment information for program {}.\nError: {}",
359+
program_address.to_string(),
360+
err
361+
)
362+
})?;
351363

352364
let pda_account = find_build_params_pda(&program_address, &signer_pubkey).0;
353365

@@ -370,10 +382,9 @@ pub async fn process_close(
370382
)?;
371383
} else {
372384
return Err(anyhow!(
373-
"No PDA found for signer {:?} and program address {:?}. Make sure you are providing the program address, not the PDA address. Check that a signer exists for the program by running `solana-verify list-program-pdas --program-id {:?}`",
374-
signer_pubkey,
385+
"No verification data found for program {} with signer {}",
375386
program_address,
376-
program_address
387+
signer_pubkey
377388
));
378389
}
379390

@@ -404,12 +415,17 @@ pub async fn get_program_pda(
404415
if let Some(account) = account.value {
405416
Ok((
406417
pda,
407-
OtterBuildParams::try_from_slice(&account.data[8..])
408-
.map_err(|err| anyhow!("Unable to parse build params: {}", err))?,
418+
OtterBuildParams::try_from_slice(&account.data[8..]).map_err(|err| {
419+
anyhow!(
420+
"Failed to parse verification data for program {} : {}",
421+
program_id,
422+
err
423+
)
424+
})?,
409425
))
410426
} else {
411427
Err(anyhow!(
412-
"PDA not found for {:?} and uploader {:?}. Make sure you've uploaded the PDA to mainnet.",
428+
"Verification PDA not found for {:?} and uploader {:?}. Make sure you've uploaded the PDA to mainnet.",
413429
program_id,
414430
signer_pubkey
415431
))

0 commit comments

Comments
 (0)