diff --git a/tooling/backend_interface/src/cli/contract.rs b/tooling/backend_interface/src/cli/contract.rs index 6301431d0f3..47ad1e4cc5b 100644 --- a/tooling/backend_interface/src/cli/contract.rs +++ b/tooling/backend_interface/src/cli/contract.rs @@ -2,6 +2,8 @@ use std::path::{Path, PathBuf}; use crate::BackendError; +use super::string_from_stderr; + /// VerifyCommand will call the barretenberg binary /// to return a solidity library with the verification key /// that can be used to verify proofs on-chain. @@ -31,9 +33,9 @@ impl ContractCommand { if output.status.success() { String::from_utf8(output.stdout) - .map_err(|error| BackendError::MalformedResponse(error.into_bytes())) + .map_err(|error| BackendError::InvalidUTF8Vector(error.into_bytes())) } else { - Err(BackendError::CommandFailed(output.stderr)) + Err(BackendError::CommandFailed(string_from_stderr(&output.stderr))) } } } diff --git a/tooling/backend_interface/src/cli/gates.rs b/tooling/backend_interface/src/cli/gates.rs index 446c6eee817..aca05f0232a 100644 --- a/tooling/backend_interface/src/cli/gates.rs +++ b/tooling/backend_interface/src/cli/gates.rs @@ -2,6 +2,8 @@ use std::path::{Path, PathBuf}; use crate::BackendError; +use super::string_from_stderr; + /// GatesCommand will call the barretenberg binary /// to return the number of gates needed to create a proof /// for the given bytecode. @@ -21,13 +23,16 @@ impl GatesCommand { .output()?; if !output.status.success() { - return Err(BackendError::CommandFailed(output.stderr)); + return Err(BackendError::CommandFailed(string_from_stderr(&output.stderr))); } // Note: barretenberg includes the newline, so that subsequent prints to stdout // are not on the same line as the gates output. - let gates_bytes: [u8; 8] = - output.stdout.try_into().map_err(BackendError::MalformedResponse)?; + const EXPECTED_BYTES: usize = 8; + let gates_bytes: [u8; EXPECTED_BYTES] = + output.stdout.as_slice().try_into().map_err(|_| { + BackendError::UnexpectedNumberOfBytes(EXPECTED_BYTES, output.stdout.clone()) + })?; // Convert bytes to u64 in little-endian format let value = u64::from_le_bytes(gates_bytes); diff --git a/tooling/backend_interface/src/cli/info.rs b/tooling/backend_interface/src/cli/info.rs index d015284e704..d3fd89bd2bc 100644 --- a/tooling/backend_interface/src/cli/info.rs +++ b/tooling/backend_interface/src/cli/info.rs @@ -5,6 +5,8 @@ use std::path::{Path, PathBuf}; use crate::{BackendError, BackendOpcodeSupport}; +use super::string_from_stderr; + pub(crate) struct InfoCommand { pub(crate) crs_path: PathBuf, } @@ -43,7 +45,7 @@ impl InfoCommand { let output = command.output()?; if !output.status.success() { - return Err(BackendError::CommandFailed(output.stderr)); + return Err(BackendError::CommandFailed(string_from_stderr(&output.stderr))); } let backend_info: InfoResponse = diff --git a/tooling/backend_interface/src/cli/mod.rs b/tooling/backend_interface/src/cli/mod.rs index 5018def4160..848c5e11e81 100644 --- a/tooling/backend_interface/src/cli/mod.rs +++ b/tooling/backend_interface/src/cli/mod.rs @@ -22,9 +22,14 @@ fn no_command_provided_works() -> Result<(), crate::BackendError> { let output = std::process::Command::new(backend.binary_path()).output()?; - let stderr = String::from_utf8_lossy(&output.stderr); + let stderr = string_from_stderr(&output.stderr); // Assert help message is printed due to no command being provided. assert!(stderr.contains("Usage: mock_backend ")); Ok(()) } + +// Converts a stderr byte array to a string (including invalid characters) +fn string_from_stderr(stderr: &[u8]) -> String { + String::from_utf8_lossy(stderr).to_string() +} diff --git a/tooling/backend_interface/src/cli/prove.rs b/tooling/backend_interface/src/cli/prove.rs index a229506a3dc..c12e516db57 100644 --- a/tooling/backend_interface/src/cli/prove.rs +++ b/tooling/backend_interface/src/cli/prove.rs @@ -2,6 +2,8 @@ use std::path::{Path, PathBuf}; use crate::BackendError; +use super::string_from_stderr; + /// ProveCommand will call the barretenberg binary /// to create a proof, given the witness and the bytecode. /// @@ -39,7 +41,7 @@ impl ProveCommand { if output.status.success() { Ok(output.stdout) } else { - Err(BackendError::CommandFailed(output.stderr)) + Err(BackendError::CommandFailed(string_from_stderr(&output.stderr))) } } } diff --git a/tooling/backend_interface/src/cli/write_vk.rs b/tooling/backend_interface/src/cli/write_vk.rs index 05db7e47388..987dac7cf8d 100644 --- a/tooling/backend_interface/src/cli/write_vk.rs +++ b/tooling/backend_interface/src/cli/write_vk.rs @@ -1,5 +1,6 @@ use std::path::{Path, PathBuf}; +use super::string_from_stderr; use crate::BackendError; /// WriteCommand will call the barretenberg binary @@ -32,7 +33,7 @@ impl WriteVkCommand { if output.status.success() { Ok(()) } else { - Err(BackendError::CommandFailed(output.stderr)) + Err(BackendError::CommandFailed(string_from_stderr(&output.stderr))) } } } diff --git a/tooling/backend_interface/src/lib.rs b/tooling/backend_interface/src/lib.rs index 6d18b6b6ead..d6a9cd0d293 100644 --- a/tooling/backend_interface/src/lib.rs +++ b/tooling/backend_interface/src/lib.rs @@ -40,11 +40,16 @@ pub enum BackendError { #[error("Backend binary does not exist")] MissingBinary, - #[error("The backend responded with malformed data: {0:?}")] - MalformedResponse(Vec), + #[error("The backend responded with a malformed UTF8 byte vector: {0:?}")] + InvalidUTF8Vector(Vec), - #[error("The backend encountered an error")] - CommandFailed(Vec), + #[error( + "The backend responded with a unexpected number of bytes. Expected: {0} but got {} ({1:?})", .1.len() + )] + UnexpectedNumberOfBytes(usize, Vec), + + #[error("The backend encountered an error: {0:?}")] + CommandFailed(String), } #[derive(Debug)]