Skip to content
This repository has been archived by the owner on Apr 9, 2024. It is now read-only.

Commit

Permalink
Merge branch 'master' into remove-unused-opcodes
Browse files Browse the repository at this point in the history
* master:
  feat(acir)!: Add predicate to MemoryOp (#503)
  chore(acvm)!: Remove unused arguments from `Backend` trait (#511)
  feat!: Assertion messages embedded in the circuit (#484)
  • Loading branch information
TomAFrench committed Aug 30, 2023
2 parents aa6a145 + ca9eebe commit 1470b5b
Show file tree
Hide file tree
Showing 21 changed files with 344 additions and 138 deletions.
10 changes: 8 additions & 2 deletions acir/src/circuit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::native_types::Witness;
pub use opcodes::Opcode;
use thiserror::Error;

use std::{io::prelude::*, num::ParseIntError, str::FromStr};
use std::{collections::BTreeMap, io::prelude::*, num::ParseIntError, str::FromStr};

use flate2::Compression;

Expand All @@ -30,6 +30,10 @@ pub struct Circuit {
pub public_parameters: PublicInputs,
/// The set of public inputs calculated within the circuit.
pub return_values: PublicInputs,
/// Maps opcode locations to failed assertion messages.
/// These messages are embedded in the circuit to provide useful feedback to users
/// when a constraint in the circuit is not satisfied.
pub assert_messages: BTreeMap<OpcodeLocation, String>,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
Expand Down Expand Up @@ -195,7 +199,7 @@ impl PublicInputs {

#[cfg(test)]
mod tests {
use std::collections::BTreeSet;
use std::collections::{BTreeMap, BTreeSet};

use super::{
opcodes::{BlackBoxFuncCall, FunctionInput},
Expand Down Expand Up @@ -225,6 +229,7 @@ mod tests {
private_parameters: BTreeSet::new(),
public_parameters: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(12)])),
return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(4), Witness(12)])),
assert_messages: BTreeMap::new(),
};

fn read_write(circuit: Circuit) -> (Circuit, Circuit) {
Expand Down Expand Up @@ -254,6 +259,7 @@ mod tests {
private_parameters: BTreeSet::new(),
public_parameters: PublicInputs(BTreeSet::from_iter(vec![Witness(2)])),
return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(2)])),
assert_messages: BTreeMap::new(),
};

let json = serde_json::to_string_pretty(&circuit).unwrap();
Expand Down
8 changes: 7 additions & 1 deletion acir/src/circuit/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub enum Opcode {
MemoryOp {
block_id: BlockId,
op: MemOp,
/// Predicate of the memory operation - indicates if it should be skipped
predicate: Option<Expression>,
},
MemoryInit {
block_id: BlockId,
Expand Down Expand Up @@ -146,8 +148,12 @@ impl std::fmt::Display for Opcode {
writeln!(f, "outputs: {:?}", brillig.outputs)?;
writeln!(f, "{:?}", brillig.bytecode)
}
Opcode::MemoryOp { block_id, op } => {
Opcode::MemoryOp { block_id, op, predicate } => {
write!(f, "MEM ")?;
if let Some(pred) = predicate {
writeln!(f, "PREDICATE = {pred}")?;
}

let is_read = op.operation.is_zero();
let is_write = op.operation == Expression::one();
if is_read {
Expand Down
119 changes: 77 additions & 42 deletions acir/tests/test_program_serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::collections::BTreeSet;
use acir::{
circuit::{
brillig::{Brillig, BrilligInputs, BrilligOutputs},
opcodes::{BlackBoxFuncCall, FunctionInput},
opcodes::{BlackBoxFuncCall, BlockId, FunctionInput, MemOp},
Circuit, Opcode, PublicInputs,
},
native_types::{Expression, Witness},
Expand All @@ -38,20 +38,20 @@ fn addition_circuit() {
current_witness_index: 4,
opcodes: vec![addition],
private_parameters: BTreeSet::from([Witness(1), Witness(2)]),
public_parameters: PublicInputs::default(),
return_values: PublicInputs([Witness(3)].into()),
..Circuit::default()
};

let mut bytes = Vec::new();
circuit.write(&mut bytes).unwrap();

let expected_serialization: Vec<u8> = vec![
31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 187, 13, 192, 32, 12, 68, 249, 100, 32, 27,
219, 96, 119, 89, 37, 40, 176, 255, 8, 81, 36, 23, 72, 41, 195, 53, 215, 61, 221, 189, 35,
132, 16, 195, 55, 217, 251, 244, 134, 127, 193, 184, 145, 149, 22, 22, 65, 101, 30, 173,
12, 36, 188, 160, 88, 87, 1, 150, 94, 21, 21, 69, 229, 46, 74, 52, 148, 181, 89, 183, 6,
134, 76, 3, 167, 24, 77, 135, 229, 125, 187, 32, 57, 231, 253, 154, 22, 151, 113, 113, 250,
0, 123, 50, 20, 220, 112, 1, 0, 0,
219, 96, 119, 89, 37, 40, 176, 255, 8, 17, 18, 5, 74, 202, 240, 154, 235, 158, 238, 238,
112, 206, 121, 247, 37, 206, 60, 103, 194, 63, 208, 111, 116, 133, 197, 69, 144, 153, 91,
73, 13, 9, 47, 72, 86, 85, 128, 165, 102, 69, 69, 81, 185, 147, 18, 53, 101, 45, 86, 173,
128, 33, 83, 195, 46, 70, 125, 202, 226, 190, 94, 16, 166, 103, 108, 13, 203, 151, 254,
245, 233, 224, 1, 1, 52, 166, 127, 120, 1, 0, 0,
];

assert_eq!(bytes, expected_serialization)
Expand All @@ -68,17 +68,17 @@ fn fixed_base_scalar_mul_circuit() {
current_witness_index: 4,
opcodes: vec![fixed_base_scalar_mul],
private_parameters: BTreeSet::from([Witness(1)]),
public_parameters: PublicInputs::default(),
return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(3)])),
..Circuit::default()
};

let mut bytes = Vec::new();
circuit.write(&mut bytes).unwrap();

let expected_serialization: Vec<u8> = vec![
31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 138, 201, 9, 0, 0, 8, 195, 234, 241, 114, 255, 121,
69, 69, 5, 49, 16, 242, 104, 21, 0, 161, 169, 218, 212, 83, 78, 229, 237, 11, 159, 214, 39,
0, 55, 132, 28, 78, 72, 0, 0, 0,
31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 137, 91, 10, 0, 0, 4, 4, 215, 227, 203, 253, 207,
43, 132, 146, 169, 105, 106, 87, 1, 16, 154, 170, 77, 61, 229, 84, 222, 191, 240, 169, 156,
61, 0, 36, 111, 164, 5, 80, 0, 0, 0,
];

assert_eq!(bytes, expected_serialization)
Expand All @@ -96,17 +96,17 @@ fn pedersen_circuit() {
current_witness_index: 4,
opcodes: vec![pedersen],
private_parameters: BTreeSet::from([Witness(1)]),
public_parameters: PublicInputs::default(),
return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(3)])),
..Circuit::default()
};

let mut bytes = Vec::new();
circuit.write(&mut bytes).unwrap();

let expected_serialization: Vec<u8> = vec![
31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 138, 65, 10, 0, 64, 8, 2, 103, 183, 232, 255, 47,
142, 138, 58, 68, 130, 168, 140, 10, 60, 90, 149, 118, 182, 79, 255, 105, 57, 140, 197,
246, 39, 0, 246, 174, 71, 87, 84, 0, 0, 0,
31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 138, 9, 10, 0, 64, 8, 2, 103, 15, 250, 255, 139,
163, 162, 130, 72, 16, 149, 241, 3, 135, 84, 164, 172, 173, 213, 175, 251, 45, 198, 96,
243, 211, 50, 152, 67, 220, 211, 92, 0, 0, 0,
];

assert_eq!(bytes, expected_serialization)
Expand Down Expand Up @@ -138,30 +138,30 @@ fn schnorr_verify_circuit() {
current_witness_index: 100,
opcodes: vec![schnorr],
private_parameters: BTreeSet::from_iter((1..=last_input).map(Witness)),
public_parameters: PublicInputs::default(),
return_values: PublicInputs(BTreeSet::from([output])),
..Circuit::default()
};

let mut bytes = Vec::new();
circuit.write(&mut bytes).unwrap();

let expected_serialization: Vec<u8> = vec![
31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 233, 50, 66, 1, 24, 199, 225, 99, 223, 247,
125, 15, 73, 146, 36, 73, 146, 36, 73, 194, 93, 184, 255, 75, 48, 122, 167, 167, 25, 103,
230, 204, 83, 211, 151, 230, 253, 255, 126, 146, 36, 25, 73, 6, 79, 56, 193, 223, 254, 59,
202, 166, 223, 199, 250, 239, 116, 255, 29, 231, 4, 39, 57, 197, 225, 59, 195, 89, 206,
113, 158, 11, 92, 228, 18, 151, 185, 194, 85, 174, 113, 157, 27, 220, 228, 22, 183, 185,
195, 93, 238, 113, 159, 7, 60, 228, 17, 83, 60, 230, 9, 79, 153, 230, 25, 51, 60, 103, 150,
23, 204, 241, 146, 121, 94, 177, 192, 107, 22, 121, 195, 18, 111, 89, 230, 29, 43, 188,
103, 149, 15, 172, 241, 145, 117, 62, 177, 193, 103, 54, 249, 194, 214, 191, 29, 227, 121,
245, 189, 205, 55, 118, 248, 206, 46, 63, 216, 227, 39, 191, 248, 237, 115, 60, 209, 94,
116, 23, 173, 69, 103, 209, 88, 244, 53, 108, 107, 198, 255, 136, 150, 162, 163, 104, 40,
250, 137, 118, 162, 155, 104, 38, 122, 137, 86, 162, 147, 104, 36, 250, 136, 54, 162, 139,
104, 34, 122, 136, 22, 162, 131, 104, 32, 246, 143, 237, 83, 201, 96, 243, 216, 59, 182,
78, 219, 56, 99, 219, 172, 77, 115, 182, 204, 219, 176, 96, 187, 162, 205, 74, 182, 42,
219, 168, 98, 155, 170, 77, 106, 182, 168, 219, 160, 225, 246, 77, 55, 111, 185, 113, 219,
109, 59, 110, 218, 117, 203, 158, 27, 14, 111, 54, 188, 91, 226, 150, 127, 214, 93, 14,
165, 212, 3, 0, 0,
31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 87, 78, 2, 1, 20, 134, 209, 177, 247, 222, 123,
71, 68, 68, 68, 68, 68, 68, 68, 68, 68, 221, 133, 251, 95, 130, 145, 27, 206, 36, 78, 50,
57, 16, 94, 200, 253, 191, 159, 36, 73, 134, 146, 193, 19, 142, 241, 183, 255, 14, 179,
233, 247, 145, 254, 59, 217, 127, 71, 57, 198, 113, 78, 48, 125, 167, 56, 205, 25, 206,
114, 142, 243, 92, 224, 34, 151, 184, 204, 21, 174, 114, 141, 235, 220, 224, 38, 183, 184,
205, 29, 238, 114, 143, 251, 60, 224, 33, 143, 120, 204, 19, 158, 242, 140, 25, 158, 51,
203, 11, 230, 120, 201, 60, 175, 88, 224, 53, 139, 188, 97, 137, 183, 44, 243, 142, 21,
222, 179, 202, 7, 214, 248, 200, 58, 159, 216, 224, 51, 155, 124, 97, 235, 223, 142, 241,
188, 250, 222, 230, 27, 59, 124, 103, 151, 31, 236, 241, 147, 95, 252, 246, 57, 158, 104,
47, 186, 139, 214, 162, 179, 104, 44, 250, 74, 219, 154, 242, 63, 162, 165, 232, 40, 26,
138, 126, 162, 157, 232, 38, 154, 137, 94, 162, 149, 232, 36, 26, 137, 62, 162, 141, 232,
34, 154, 136, 30, 162, 133, 232, 32, 26, 136, 253, 99, 251, 195, 100, 176, 121, 236, 29,
91, 159, 218, 56, 99, 219, 172, 77, 115, 182, 204, 219, 176, 96, 187, 162, 205, 74, 182,
42, 219, 168, 98, 155, 170, 77, 106, 182, 168, 219, 160, 225, 246, 77, 55, 111, 185, 113,
219, 109, 59, 110, 218, 117, 203, 158, 27, 166, 55, 75, 239, 150, 184, 101, 250, 252, 1,
19, 89, 159, 101, 220, 3, 0, 0,
];

assert_eq!(bytes, expected_serialization)
Expand Down Expand Up @@ -195,8 +195,7 @@ fn simple_brillig_foreign_call() {
current_witness_index: 8,
opcodes,
private_parameters: BTreeSet::from([Witness(1), Witness(2)]),
public_parameters: PublicInputs::default(),
return_values: PublicInputs::default(),
..Circuit::default()
};

let mut bytes = Vec::new();
Expand Down Expand Up @@ -273,21 +272,57 @@ fn complex_brillig_foreign_call() {
current_witness_index: 8,
opcodes,
private_parameters: BTreeSet::from([Witness(1), Witness(2), Witness(3)]),
public_parameters: PublicInputs::default(),
return_values: PublicInputs::default(),
..Circuit::default()
};

let mut bytes = Vec::new();
circuit.write(&mut bytes).unwrap();

let expected_serialization: Vec<u8> = vec![
31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 83, 219, 10, 128, 48, 8, 245, 210, 101, 159, 179,
254, 160, 127, 137, 222, 138, 122, 236, 243, 91, 228, 64, 44, 232, 33, 7, 117, 64, 156,
206, 201, 193, 51, 3, 0, 32, 156, 224, 100, 36, 103, 148, 88, 35, 215, 245, 226, 227, 59,
116, 232, 215, 43, 150, 226, 72, 63, 224, 200, 5, 56, 230, 255, 240, 81, 189, 61, 117, 113,
157, 31, 223, 236, 79, 149, 172, 78, 214, 72, 220, 138, 15, 106, 214, 168, 114, 249, 126,
88, 230, 117, 26, 55, 54, 37, 90, 26, 155, 39, 227, 31, 223, 232, 230, 4, 215, 157, 63,
176, 3, 89, 64, 134, 157, 36, 4, 0, 0,
254, 160, 127, 137, 222, 138, 122, 236, 243, 27, 228, 64, 44, 232, 33, 7, 237, 128, 56,
157, 147, 131, 103, 6, 0, 64, 184, 192, 201, 72, 206, 40, 177, 70, 174, 27, 197, 199, 111,
24, 208, 175, 87, 44, 197, 145, 42, 224, 200, 5, 56, 230, 255, 240, 83, 189, 61, 117, 113,
157, 31, 63, 236, 79, 147, 172, 77, 214, 73, 220, 139, 15, 106, 214, 168, 114, 249, 126,
218, 214, 125, 153, 15, 54, 37, 90, 26, 155, 39, 227, 95, 223, 232, 230, 4, 247, 157, 215,
56, 1, 153, 86, 63, 138, 44, 4, 0, 0,
];

assert_eq!(bytes, expected_serialization)
}

#[test]
fn memory_op_circuit() {
let init = vec![Witness(1), Witness(2)];

let memory_init = Opcode::MemoryInit { block_id: BlockId(0), init };
let write = Opcode::MemoryOp {
block_id: BlockId(0),
op: MemOp::write_to_mem_index(FieldElement::from(1u128).into(), Witness(3).into()),
predicate: None,
};
let read = Opcode::MemoryOp {
block_id: BlockId(0),
op: MemOp::read_at_mem_index(FieldElement::one().into(), Witness(4)),
predicate: None,
};

let circuit = Circuit {
current_witness_index: 5,
opcodes: vec![memory_init, write, read],
private_parameters: BTreeSet::from([Witness(1), Witness(2), Witness(3)]),
return_values: PublicInputs([Witness(4)].into()),
..Circuit::default()
};
let mut bytes = Vec::new();
circuit.write(&mut bytes).unwrap();

let expected_serialization: Vec<u8> = vec![
31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 146, 49, 14, 0, 32, 8, 3, 139, 192, 127, 240, 7,
254, 255, 85, 198, 136, 9, 131, 155, 48, 216, 165, 76, 77, 57, 80, 0, 140, 45, 117, 111,
238, 228, 179, 224, 174, 225, 110, 111, 234, 213, 185, 148, 156, 203, 121, 89, 86, 13, 215,
126, 131, 43, 153, 187, 115, 40, 185, 62, 153, 3, 136, 83, 60, 30, 96, 2, 12, 235, 225,
124, 14, 3, 0, 0,
];

assert_eq!(bytes, expected_serialization)
Expand Down
26 changes: 22 additions & 4 deletions acvm/src/compiler/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::BTreeMap;

use acir::{
circuit::{
brillig::BrilligOutputs, directives::Directive, opcodes::UnsupportedMemoryOpcode, Circuit,
Expand Down Expand Up @@ -58,6 +60,19 @@ impl AcirTransformationMap {
}
}

fn transform_assert_messages(
assert_messages: BTreeMap<OpcodeLocation, String>,
map: &AcirTransformationMap,
) -> BTreeMap<OpcodeLocation, String> {
assert_messages
.into_iter()
.flat_map(|(location, message)| {
let new_locations = map.new_locations(location);
new_locations.into_iter().map(move |new_location| (new_location, message.clone()))
})
.collect()
}

/// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`].
pub fn compile(
acir: Circuit,
Expand Down Expand Up @@ -90,12 +105,14 @@ pub fn compile(

// Range optimization pass
let range_optimizer = RangeOptimizer::new(acir);
let (acir, acir_opcode_positions) =
let (mut acir, acir_opcode_positions) =
range_optimizer.replace_redundant_ranges(acir_opcode_positions);

let mut transformer = match &np_language {
crate::Language::R1CS => {
let transformation_map = AcirTransformationMap { acir_opcode_positions };
acir.assert_messages =
transform_assert_messages(acir.assert_messages, &transformation_map);
let transformer = R1CSTransformer::new(acir);
return Ok((transformer.transform(), transformation_map));
}
Expand Down Expand Up @@ -248,17 +265,18 @@ pub fn compile(

let current_witness_index = next_witness_index - 1;

let transformation_map =
AcirTransformationMap { acir_opcode_positions: new_acir_opcode_positions };

let acir = Circuit {
current_witness_index,
opcodes: transformed_opcodes,
// The optimizer does not add new public inputs
private_parameters: acir.private_parameters,
public_parameters: acir.public_parameters,
return_values: acir.return_values,
assert_messages: transform_assert_messages(acir.assert_messages, &transformation_map),
};

let transformation_map =
AcirTransformationMap { acir_opcode_positions: new_acir_opcode_positions };

Ok((acir, transformation_map))
}
7 changes: 3 additions & 4 deletions acvm/src/compiler/optimizers/redundant_range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,7 @@ impl RangeOptimizer {
Circuit {
current_witness_index: self.circuit.current_witness_index,
opcodes: optimized_opcodes,
private_parameters: self.circuit.private_parameters,
public_parameters: self.circuit.public_parameters,
return_values: self.circuit.return_values,
..self.circuit
},
new_order_list,
)
Expand All @@ -137,7 +135,7 @@ fn extract_range_opcode(opcode: &Opcode) -> Option<(Witness, u32)> {

#[cfg(test)]
mod tests {
use std::collections::BTreeSet;
use std::collections::{BTreeMap, BTreeSet};

use crate::compiler::optimizers::redundant_range::{extract_range_opcode, RangeOptimizer};
use acir::{
Expand Down Expand Up @@ -166,6 +164,7 @@ mod tests {
private_parameters: BTreeSet::new(),
public_parameters: PublicInputs::default(),
return_values: PublicInputs::default(),
assert_messages: BTreeMap::new(),
}
}

Expand Down
8 changes: 1 addition & 7 deletions acvm/src/compiler/transformers/fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,7 @@ impl FallbackTransformer {
}

Ok((
Circuit {
current_witness_index: witness_idx,
opcodes: acir_supported_opcodes,
private_parameters: acir.private_parameters,
public_parameters: acir.public_parameters,
return_values: acir.return_values,
},
Circuit { current_witness_index: witness_idx, opcodes: acir_supported_opcodes, ..acir },
new_opcode_positions,
))
}
Expand Down
Loading

0 comments on commit 1470b5b

Please sign in to comment.