Skip to content
This repository has been archived by the owner on Oct 31, 2023. It is now read-only.

feat!: Update to acvm 0.12.0 #165

Merged
merged 20 commits into from
May 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
289 changes: 112 additions & 177 deletions Cargo.lock

Large diffs are not rendered by default.

41 changes: 17 additions & 24 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,13 @@ license = "MIT OR Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
acvm = { version = "0.11.0", features = ["bn254"] }
acvm = { version = "0.12.0", features = ["bn254"] }
bincode = "1.3.3"
bytesize = "1.2"
reqwest = { version = "0.11.16", default-features = false, features = ["rustls-tls"] }
serde = { version = "1.0.136", features = ["derive"] }
thiserror = "1.0.21"

blake2 = "0.9.1"
dirs = { version = "3.0", optional = true }
reqwest = { version = "0.11.16", optional = true, default-features = false, features = [
"stream",
"rustls-tls",
] }
tokio = { version = "1.0", optional = true }
futures-util = { version = "0.3.14", optional = true }
indicatif = { version = "0.17.3", optional = true }

# Native
barretenberg-sys = { version = "0.1.2", optional = true }

Expand All @@ -38,15 +32,14 @@ getrandom = { version = "0.2", optional = true }
[build-dependencies]
pkg-config = "0.3"

[dev-dependencies]
blake2 = "0.10.6"
tokio = { version = "1.0", features = [ "macros" ] }

[features]
default = ["native"]
native = [
"dep:barretenberg-sys",
"dep:reqwest",
"dep:tokio",
"dep:futures-util",
"dep:dirs",
"dep:indicatif",
"dep:barretenberg-sys"
]
wasm = [
"wasmer",
Expand All @@ -56,11 +49,11 @@ wasm = [
"wasmer/cranelift",
"wasmer/default-compiler",
"wasmer/default-cranelift",
"wasmer/default-universal",
"dep:reqwest",
"dep:tokio",
"dep:futures-util",
"dep:dirs",
"dep:indicatif",
"wasmer/default-universal"
]
js = [
"wasmer",
"dep:rust-embed",
"dep:getrandom",
"wasmer/js-default"
]
js = ["wasmer", "dep:rust-embed", "dep:getrandom", "wasmer/js-default"]
3 changes: 2 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"envrc",
"subshell",
"thiserror",
"bincode",
// In Solidity
//
"addmod",
Expand All @@ -72,7 +73,7 @@
"acir",
"acvm",
"barretenberg",
"indicatif",
"bytesize",
"wasmer",
"getrandom"
]
Expand Down
41 changes: 35 additions & 6 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,6 @@
# Note: Setting this allows for consistent behavior across build and shells, but is mostly
# hidden from the developer - i.e. when they see the command being run via `nix flake check`
RUST_TEST_THREADS = "1";

# We provide `barretenberg-transcript00` from the overlay to the build.
# This is necessary because the Nix sandbox is read-only and downloading during tests would fail
BARRETENBERG_TRANSCRIPT = pkgs.barretenberg-transcript00;
};

nativeEnvironment = sharedEnvironment // {
Expand Down Expand Up @@ -153,6 +149,27 @@
buildInputs = [ ] ++ extraBuildInputs;
};

# The `port` is parameterized to support parallel test runs without colliding static servers
networkTestArgs = port: {
# We provide `barretenberg-transcript00` from the overlay to the tests as a URL hosted via a static server
# This is necessary because the Nix sandbox has no network access and downloading during tests would fail
TRANSCRIPT_URL = "http://0.0.0.0:${toString port}/${builtins.baseNameOf pkgs.barretenberg-transcript00}";

# This copies the `barretenberg-transcript00` from the Nix store into this sandbox
# which avoids exposing the entire Nix store to the static server it starts
# The static server is moved to the background and killed after checks are completed
preCheck = ''
cp ${pkgs.barretenberg-transcript00} .
echo "Starting simple static server"
${pkgs.simple-http-server}/bin/simple-http-server --port ${toString port} --silent &
HTTP_SERVER_PID=$!
'';

postCheck = ''
kill $HTTP_SERVER_PID
'';
};

# Build *just* the cargo dependencies, so we can reuse all of that work between runs
native-cargo-artifacts = craneLib.buildDepsOnly nativeArgs;
wasm-cargo-artifacts = craneLib.buildDepsOnly wasmArgs;
Expand All @@ -167,25 +184,37 @@
rec {
checks = {
cargo-clippy-native = craneLib.cargoClippy (nativeArgs // {
# Crane appends "clippy"
pname = "native";

cargoArtifacts = native-cargo-artifacts;

cargoClippyExtraArgs = "--all-targets -- -D warnings";
});

cargo-test-native = craneLib.cargoTest (nativeArgs // {
cargo-test-native = craneLib.cargoTest (nativeArgs // (networkTestArgs 8000) // {
# Crane appends "test"
pname = "native";

cargoArtifacts = native-cargo-artifacts;

# It's unclear why doCheck needs to be enabled for tests to run but not clippy
doCheck = true;
});

cargo-clippy-wasm = craneLib.cargoClippy (wasmArgs // {
# Crane appends "clippy"
pname = "wasm";

cargoArtifacts = wasm-cargo-artifacts;

cargoClippyExtraArgs = "--all-targets -- -D warnings";
});

cargo-test-wasm = craneLib.cargoTest (wasmArgs // {
cargo-test-wasm = craneLib.cargoTest (wasmArgs // (networkTestArgs 8001) // {
# Crane appends "test"
pname = "wasm";

cargoArtifacts = wasm-cargo-artifacts;

# It's unclear why doCheck needs to be enabled for tests to run but not clippy
Expand Down
34 changes: 34 additions & 0 deletions src/acvm_interop/common_reference_string.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use acvm::{acir::circuit::Circuit, async_trait, CommonReferenceString};

use crate::{composer::Composer, BackendError, Barretenberg};

// TODO(#185): Ensure CRS download works in JS
#[async_trait]
impl CommonReferenceString for Barretenberg {
type Error = BackendError;

async fn generate_common_reference_string(
&self,
circuit: &Circuit,
) -> Result<Vec<u8>, Self::Error> {
let constraint_system = &circuit.try_into()?;
let common_reference_string = self.get_crs(constraint_system).await?.try_into()?;
// Separated to have nicer coercion on error types
Ok(common_reference_string)
}

async fn update_common_reference_string(
&self,
common_reference_string: Vec<u8>,
circuit: &Circuit,
) -> Result<Vec<u8>, Self::Error> {
let mut crs = common_reference_string.try_into()?;
let constraint_system = &circuit.try_into()?;
let common_reference_string = self
.update_crs(&mut crs, constraint_system)
.await?
.try_into()?;
// Separated to have nicer coercion on error types
Ok(common_reference_string)
}
}
1 change: 1 addition & 0 deletions src/acvm_interop/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::Barretenberg;

mod common_reference_string;
mod proof_system;
mod pwg;
mod smart_contract;
Expand Down
78 changes: 46 additions & 32 deletions src/acvm_interop/proof_system.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
use acvm::acir::{circuit::Circuit, native_types::Witness, BlackBoxFunc};
use acvm::acir::circuit::Opcode;
use acvm::acir::{circuit::Circuit, native_types::WitnessMap, BlackBoxFunc};
use acvm::FieldElement;
use acvm::{Language, ProofSystemCompiler};
use std::collections::BTreeMap;

use crate::barretenberg_structures::Assignments;
use crate::composer::Composer;
use crate::{BackendError, Barretenberg};
use crate::{barretenberg_structures::Assignments, composer::Composer, BackendError, Barretenberg};

impl ProofSystemCompiler for Barretenberg {
type Error = BackendError;
Expand All @@ -21,58 +19,77 @@ impl ProofSystemCompiler for Barretenberg {
)?)
}

fn black_box_function_supported(&self, opcode: &BlackBoxFunc) -> bool {
fn supports_opcode(&self, opcode: &Opcode) -> bool {
match opcode {
BlackBoxFunc::AND
| BlackBoxFunc::XOR
| BlackBoxFunc::RANGE
| BlackBoxFunc::SHA256
| BlackBoxFunc::Blake2s
| BlackBoxFunc::Keccak256
| BlackBoxFunc::ComputeMerkleRoot
| BlackBoxFunc::SchnorrVerify
| BlackBoxFunc::Pedersen
| BlackBoxFunc::HashToField128Security
| BlackBoxFunc::EcdsaSecp256k1
| BlackBoxFunc::FixedBaseScalarMul => true,

BlackBoxFunc::AES => false,
Opcode::Arithmetic(_) => true,
Opcode::Directive(_) => true,
Opcode::Block(_) => false,
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
Opcode::ROM(_) => true,
Opcode::RAM(_) => true,
Opcode::Oracle(_) => true,
Opcode::BlackBoxFuncCall(func) => match func.get_black_box_func() {
BlackBoxFunc::AND
| BlackBoxFunc::XOR
| BlackBoxFunc::RANGE
| BlackBoxFunc::SHA256
| BlackBoxFunc::Blake2s
| BlackBoxFunc::Keccak256
| BlackBoxFunc::ComputeMerkleRoot
| BlackBoxFunc::SchnorrVerify
| BlackBoxFunc::Pedersen
| BlackBoxFunc::HashToField128Security
| BlackBoxFunc::EcdsaSecp256k1
| BlackBoxFunc::FixedBaseScalarMul => true,

BlackBoxFunc::AES => false,
},
}
}

fn preprocess(&self, circuit: &Circuit) -> Result<(Vec<u8>, Vec<u8>), Self::Error> {
fn preprocess(
&self,
common_reference_string: &[u8],
circuit: &Circuit,
) -> Result<(Vec<u8>, Vec<u8>), Self::Error> {
let crs = common_reference_string.try_into()?;
let constraint_system = &circuit.try_into()?;

let proving_key = self.compute_proving_key(constraint_system)?;
let verification_key = self.compute_verification_key(constraint_system, &proving_key)?;
let verification_key = self.compute_verification_key(&crs, &proving_key)?;

Ok((proving_key, verification_key))
}

fn prove_with_pk(
&self,
common_reference_string: &[u8],
circuit: &Circuit,
witness_values: BTreeMap<Witness, FieldElement>,
witness_values: WitnessMap,
proving_key: &[u8],
) -> Result<Vec<u8>, Self::Error> {
let crs = common_reference_string.try_into()?;
let assignments = flatten_witness_map(circuit, witness_values);

Ok(self.create_proof_with_pk(&circuit.try_into()?, assignments, proving_key)?)
Ok(self.create_proof_with_pk(&crs, &circuit.try_into()?, assignments, proving_key)?)
}

fn verify_with_vk(
&self,
common_reference_string: &[u8],
proof: &[u8],
public_inputs: BTreeMap<Witness, FieldElement>,
public_inputs: WitnessMap,
circuit: &Circuit,
verification_key: &[u8],
) -> Result<bool, Self::Error> {
let crs = common_reference_string.try_into()?;
// 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_values().collect();
let flattened_public_inputs: Vec<FieldElement> =
public_inputs.into_iter().map(|(_, el)| el).collect();

Ok(Composer::verify_with_vk(
self,
&crs,
&circuit.try_into()?,
proof,
flattened_public_inputs.into(),
Expand All @@ -82,10 +99,7 @@ impl ProofSystemCompiler for Barretenberg {
}

/// Flatten a witness map into a vector of witness assignments.
fn flatten_witness_map(
circuit: &Circuit,
witness_values: BTreeMap<Witness, FieldElement>,
) -> Assignments {
fn flatten_witness_map(circuit: &Circuit, witness_values: WitnessMap) -> Assignments {
let num_witnesses = circuit.num_vars();

// Note: The witnesses are sorted via their witness index
Expand All @@ -94,10 +108,10 @@ fn flatten_witness_map(
.map(|witness_index| {
// Get the value if it exists. If i does not, then we fill it with the zero value
witness_values
.get(&Witness(witness_index))
.get_index(witness_index)
.map_or(FieldElement::zero(), |field| *field)
})
.collect();

Assignments::from(witness_assignments)
witness_assignments.into()
}
Loading