Skip to content

Commit

Permalink
feat: add backend interface definition to convert proof/vk to fields
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench committed Oct 17, 2023
1 parent 6163a0d commit aad35f3
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 1 deletion.
4 changes: 4 additions & 0 deletions tooling/backend_interface/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
mod contract;
mod gates;
mod info;
mod proof_as_fields;
mod prove;
mod verify;
mod version;
mod vk_as_fields;
mod write_vk;

pub(crate) use contract::ContractCommand;
pub(crate) use gates::GatesCommand;
pub(crate) use info::InfoCommand;
pub(crate) use proof_as_fields::ProofAsFieldsCommand;
pub(crate) use prove::ProveCommand;
pub(crate) use verify::VerifyCommand;
pub(crate) use version::VersionCommand;
pub(crate) use vk_as_fields::VkAsFieldsCommand;
pub(crate) use write_vk::WriteVkCommand;

#[test]
Expand Down
38 changes: 38 additions & 0 deletions tooling/backend_interface/src/cli/proof_as_fields.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use std::path::{Path, PathBuf};

use acvm::FieldElement;

use crate::BackendError;

use super::string_from_stderr;

/// `ProofAsFieldsCommand` will call the barretenberg binary
/// to split a proof into a representation as [`FieldElement`]s.
pub(crate) struct ProofAsFieldsCommand {
pub(crate) proof_path: PathBuf,
pub(crate) vk_path: PathBuf,
}

impl ProofAsFieldsCommand {
pub(crate) fn run(self, binary_path: &Path) -> Result<Vec<FieldElement>, BackendError> {
let mut command = std::process::Command::new(binary_path);

command
.arg("proof_as_fields")
.arg("-p")
.arg(self.proof_path)
.arg("-k")
.arg(self.vk_path)
.arg("-o")
.arg("-");

let output = command.output()?;
if output.status.success() {
let string_output = String::from_utf8(output.stdout).unwrap();
serde_json::from_str(&string_output)
.map_err(|err| BackendError::CommandFailed(err.to_string()))
} else {
Err(BackendError::CommandFailed(string_from_stderr(&output.stderr)))
}
}
}
39 changes: 39 additions & 0 deletions tooling/backend_interface/src/cli/vk_as_fields.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::path::{Path, PathBuf};

use acvm::FieldElement;

use crate::BackendError;

use super::string_from_stderr;

/// VkAsFieldsCommand will call the barretenberg binary
/// to split a verification key into a representation as [`FieldElement`]s.
///
/// The hash of the verification key will also be returned.
pub(crate) struct VkAsFieldsCommand {
pub(crate) vk_path: PathBuf,
}

impl VkAsFieldsCommand {
pub(crate) fn run(
self,
binary_path: &Path,
) -> Result<(FieldElement, Vec<FieldElement>), BackendError> {
let mut command = std::process::Command::new(binary_path);

command.arg("vk_as_fields").arg("-k").arg(self.vk_path).arg("-o").arg("-");

let output = command.output()?;
if output.status.success() {
let string_output = String::from_utf8(output.stdout).unwrap();
let mut fields: Vec<FieldElement> = serde_json::from_str(&string_output)
.map_err(|err| BackendError::CommandFailed(err.to_string()))?;

// The first element of this vector is the hash of the verification key, we want to split that off.
let hash = fields.remove(0);
Ok((hash, fields))
} else {
Err(BackendError::CommandFailed(string_from_stderr(&output.stderr)))
}
}
}
56 changes: 55 additions & 1 deletion tooling/backend_interface/src/proof_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use acvm::FieldElement;
use acvm::Language;
use tempfile::tempdir;

use crate::cli::{GatesCommand, InfoCommand, ProveCommand, VerifyCommand, WriteVkCommand};
use crate::cli::{
GatesCommand, InfoCommand, ProofAsFieldsCommand, ProveCommand, VerifyCommand,
VkAsFieldsCommand, WriteVkCommand,
};
use crate::{Backend, BackendError, BackendOpcodeSupport};

impl Backend {
Expand Down Expand Up @@ -119,6 +122,57 @@ impl Backend {
VerifyCommand { crs_path: self.crs_directory(), is_recursive, proof_path, vk_path }
.run(binary_path)
}

pub fn get_intermediate_proof_artifacts(
&self,
circuit: &Circuit,
proof: &[u8],
public_inputs: WitnessMap,
) -> Result<(Vec<FieldElement>, FieldElement, Vec<FieldElement>), BackendError> {
let binary_path = self.assert_binary_exists()?;

let temp_directory = tempdir().expect("could not create a temporary directory");
let temp_directory = temp_directory.path().to_path_buf();

// Create a temporary file for the circuit
//
let bytecode_path = temp_directory.join("circuit").with_extension("bytecode");
let serialized_circuit = serialize_circuit(circuit);
write_to_file(&serialized_circuit, &bytecode_path);

// Create the verification key and write it to the specified path
let vk_path = temp_directory.join("vk");

WriteVkCommand {
crs_path: self.crs_directory(),
bytecode_path,
vk_path_output: vk_path.clone(),
}
.run(binary_path)?;

// Create a temporary file for the proof

// Unlike when proving, we omit any unassigned witnesses.
// Witness values should be ordered by their index but we skip over any indices without an assignment.
let flattened_public_inputs: Vec<FieldElement> =
public_inputs.into_iter().map(|(_, el)| el).collect();

let proof_with_public_inputs = bb_abstraction_leaks::prepend_public_inputs(
proof.to_vec(),
flattened_public_inputs.to_vec(),
);
let proof_path = temp_directory.join("proof").with_extension("proof");
write_to_file(&proof_with_public_inputs, &proof_path);

// Now ready to generate intermediate artifacts.

let proof_as_fields =
ProofAsFieldsCommand { proof_path, vk_path: vk_path.clone() }.run(binary_path)?;

let (vk_hash, vk_as_fields) = VkAsFieldsCommand { vk_path }.run(binary_path)?;

Ok((proof_as_fields, vk_hash, vk_as_fields))
}
}

pub(super) fn write_to_file(bytes: &[u8], path: &Path) -> String {
Expand Down

0 comments on commit aad35f3

Please sign in to comment.