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

Commit

Permalink
chore(acir)!: Remove unused Directive opcodes (#510)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench authored Aug 30, 2023
1 parent ca9eebe commit cfd8cbf
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 218 deletions.
19 changes: 0 additions & 19 deletions acir/src/circuit/directives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ pub struct QuotientDirective {
/// You can think of them as opcodes that allow one to use non-determinism
/// In the future, this can be replaced with asm non-determinism blocks
pub enum Directive {
//Inverts the value of x and stores it in the result variable
Invert {
x: Witness,
result: Witness,
},

//Performs euclidian division of a / b (as integers) and stores the quotient in q and the rest in r
Quotient(QuotientDirective),

Expand All @@ -39,27 +33,14 @@ pub enum Directive {
bits: Vec<Witness>, // control bits of the network which permutes the inputs into its sorted version
sort_by: Vec<u32>, // specify primary index to sort by, then the secondary,... For instance, if tuple is 2 and sort_by is [1,0], then a=[(a0,b0),..] is sorted by bi and then ai.
},
Log(LogInfo),
}

impl Directive {
pub fn name(&self) -> &str {
match self {
Directive::Invert { .. } => "invert",
Directive::Quotient(_) => "quotient",
Directive::ToLeRadix { .. } => "to_le_radix",
Directive::PermutationSort { .. } => "permutation_sort",
Directive::Log { .. } => "log",
}
}
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
// If values are compile time and/or known during
// evaluation, we can form an output string during ACIR generation.
// Otherwise, we must store witnesses whose values will
// be fetched during the PWG stage.
pub enum LogInfo {
FinalizedOutput(String),
WitnessOutput(Vec<Witness>),
}
8 changes: 1 addition & 7 deletions acir/src/circuit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,6 @@ mod tests {
use crate::native_types::Witness;
use acir_field::FieldElement;

fn directive_opcode() -> Opcode {
Opcode::Directive(super::directives::Directive::Invert {
x: Witness(0),
result: Witness(1),
})
}
fn and_opcode() -> Opcode {
Opcode::BlackBoxFuncCall(BlackBoxFuncCall::AND {
lhs: FunctionInput { witness: Witness(1), num_bits: 4 },
Expand All @@ -231,7 +225,7 @@ mod tests {
fn serialization_roundtrip() {
let circuit = Circuit {
current_witness_index: 5,
opcodes: vec![and_opcode(), range_opcode(), directive_opcode()],
opcodes: vec![and_opcode(), range_opcode()],
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)])),
Expand Down
16 changes: 2 additions & 14 deletions acir/src/circuit/opcodes.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{
brillig::Brillig,
directives::{Directive, LogInfo, QuotientDirective},
directives::{Directive, QuotientDirective},
};
use crate::native_types::{Expression, Witness};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -100,10 +100,6 @@ impl std::fmt::Display for Opcode {

write!(f, " ]")
}
Opcode::Directive(Directive::Invert { x, result: r }) => {
write!(f, "DIR::INVERT ")?;
write!(f, "(_{}, out: _{}) ", x.witness_index(), r.witness_index())
}
Opcode::Directive(Directive::Quotient(QuotientDirective { a, b, q, r, predicate })) => {
write!(f, "DIR::QUOTIENT ")?;
if let Some(pred) = predicate {
Expand Down Expand Up @@ -145,15 +141,7 @@ impl std::fmt::Display for Opcode {
bits.last().unwrap().witness_index(),
)
}
Opcode::Directive(Directive::Log(info)) => match info {
LogInfo::FinalizedOutput(output_string) => write!(f, "Log: {output_string}"),
LogInfo::WitnessOutput(witnesses) => write!(
f,
"Log: _{}..._{}",
witnesses.first().unwrap().witness_index(),
witnesses.last().unwrap().witness_index()
),
},

Opcode::Brillig(brillig) => {
write!(f, "BRILLIG: ")?;
writeln!(f, "inputs: {:?}", brillig.inputs)?;
Expand Down
88 changes: 19 additions & 69 deletions acir/tests/test_program_serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@ use std::collections::BTreeSet;
use acir::{
circuit::{
brillig::{Brillig, BrilligInputs, BrilligOutputs},
directives::Directive,
opcodes::{BlackBoxFuncCall, BlockId, FunctionInput, MemOp},
Circuit, Opcode, PublicInputs,
},
native_types::{Expression, Witness},
};
use acir_field::FieldElement;
use brillig::{BinaryFieldOp, HeapArray, RegisterIndex, RegisterOrMemory};
use brillig::{HeapArray, RegisterIndex, RegisterOrMemory};

#[test]
fn addition_circuit() {
Expand Down Expand Up @@ -170,72 +169,28 @@ fn schnorr_verify_circuit() {

#[test]
fn simple_brillig_foreign_call() {
let fe_0 = FieldElement::zero();
let fe_1 = FieldElement::one();
let w_x = Witness(1);
let w_y = Witness(2);
let w_oracle = Witness(3);
let w_z = Witness(4);
let w_z_inverse = Witness(5);
let w_x_plus_y = Witness(6);
let w_equal_res = Witness(7);

let equal_opcode = brillig::Opcode::BinaryFieldOp {
op: BinaryFieldOp::Equals,
lhs: RegisterIndex::from(0),
rhs: RegisterIndex::from(1),
destination: RegisterIndex::from(2),
};
let w_input = Witness(1);
let w_inverted = Witness(2);

let brillig_data = Brillig {
inputs: vec![
BrilligInputs::Single(Expression {
// Input Register 0
mul_terms: vec![],
linear_combinations: vec![(fe_1, w_x), (fe_1, w_y)],
q_c: fe_0,
}),
BrilligInputs::Single(Expression::default()), // Input Register 1
BrilligInputs::Single(w_input.into()), // Input Register 0,
],
// This tells the BrilligSolver which witnesses its output registers correspond to
outputs: vec![
BrilligOutputs::Simple(w_x_plus_y), // Output Register 0 - from input
BrilligOutputs::Simple(w_oracle), // Output Register 1
BrilligOutputs::Simple(w_equal_res), // Output Register 2
BrilligOutputs::Simple(w_inverted), // Output Register 1
],
// stack of foreign call/oracle resolutions, starts empty
foreign_call_results: vec![],
bytecode: vec![
equal_opcode,
// Oracles are named 'foreign calls' in brillig
brillig::Opcode::ForeignCall {
function: "invert".into(),
destinations: vec![RegisterOrMemory::RegisterIndex(RegisterIndex::from(1))],
inputs: vec![RegisterOrMemory::RegisterIndex(RegisterIndex::from(0))],
},
],
bytecode: vec![brillig::Opcode::ForeignCall {
function: "invert".into(),
destinations: vec![RegisterOrMemory::RegisterIndex(RegisterIndex::from(0))],
inputs: vec![RegisterOrMemory::RegisterIndex(RegisterIndex::from(0))],
}],
predicate: None,
};

let opcodes = vec![
Opcode::Brillig(brillig_data),
Opcode::Arithmetic(Expression {
mul_terms: vec![],
linear_combinations: vec![(fe_1, w_x), (fe_1, w_y), (-fe_1, w_z)],
q_c: fe_0,
}),
Opcode::Directive(Directive::Invert { x: w_z, result: w_z_inverse }),
Opcode::Arithmetic(Expression {
mul_terms: vec![(fe_1, w_z, w_z_inverse)],
linear_combinations: vec![],
q_c: -fe_1,
}),
Opcode::Arithmetic(Expression {
mul_terms: vec![],
linear_combinations: vec![(-fe_1, w_oracle), (fe_1, w_z_inverse)],
q_c: fe_0,
}),
];
let opcodes = vec![Opcode::Brillig(brillig_data)];
let circuit = Circuit {
current_witness_index: 8,
opcodes,
Expand All @@ -247,16 +202,11 @@ fn simple_brillig_foreign_call() {
circuit.write(&mut bytes).unwrap();

let expected_serialization: Vec<u8> = vec![
31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 181, 148, 209, 10, 195, 32, 12, 69, 99, 109, 183, 126,
78, 82, 181, 141, 111, 251, 149, 201, 44, 236, 101, 15, 99, 236, 251, 183, 49, 11, 161,
245, 173, 233, 5, 137, 4, 57, 120, 111, 208, 30, 0, 58, 248, 203, 126, 87, 3, 91, 45, 189,
75, 169, 184, 79, 100, 20, 89, 141, 30, 11, 43, 214, 213, 216, 86, 48, 79, 34, 239, 159,
206, 149, 172, 229, 190, 21, 61, 83, 106, 47, 56, 247, 199, 59, 63, 95, 166, 114, 74, 246,
170, 178, 186, 54, 15, 27, 173, 195, 209, 251, 60, 13, 153, 28, 93, 113, 136, 137, 3, 250,
144, 70, 38, 166, 192, 225, 54, 176, 115, 153, 61, 79, 49, 197, 9, 35, 121, 151, 105, 14,
209, 205, 5, 214, 234, 221, 11, 229, 88, 186, 85, 208, 90, 222, 37, 27, 20, 115, 16, 200,
205, 179, 222, 203, 182, 138, 254, 187, 3, 230, 101, 160, 254, 189, 45, 250, 0, 87, 206,
28, 176, 11, 5, 0, 0,
31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 81, 10, 0, 16, 16, 68, 199, 42, 57, 14, 55,
112, 25, 31, 126, 124, 72, 206, 79, 161, 86, 225, 135, 87, 219, 78, 187, 53, 205, 104, 0,
2, 29, 201, 52, 103, 222, 220, 216, 230, 13, 43, 254, 121, 25, 158, 151, 54, 153, 117, 27,
53, 116, 136, 197, 167, 124, 107, 184, 64, 236, 73, 56, 83, 1, 18, 139, 122, 157, 67, 1, 0,
0,
];

assert_eq!(bytes, expected_serialization)
Expand All @@ -280,9 +230,9 @@ fn complex_brillig_foreign_call() {
inputs: vec![
// Input Register 0
BrilligInputs::Array(vec![
Expression { mul_terms: vec![], linear_combinations: vec![(fe_1, a)], q_c: fe_0 },
Expression { mul_terms: vec![], linear_combinations: vec![(fe_1, b)], q_c: fe_0 },
Expression { mul_terms: vec![], linear_combinations: vec![(fe_1, c)], q_c: fe_0 },
Expression::from(a),
Expression::from(b),
Expression::from(c),
]),
// Input Register 1
BrilligInputs::Single(Expression {
Expand Down
4 changes: 0 additions & 4 deletions acvm/src/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,6 @@ pub fn compile(
}
Opcode::Directive(directive) => {
match directive {
Directive::Invert { result, .. } => {
transformer.mark_solvable(*result);
}
Directive::Quotient(quotient_directive) => {
transformer.mark_solvable(quotient_directive.q);
transformer.mark_solvable(quotient_directive.r);
Expand All @@ -229,7 +226,6 @@ pub fn compile(
transformer.mark_solvable(*witness);
}
}
Directive::Log(_) => (),
}
new_acir_opcode_positions.push(acir_opcode_positions[index]);
transformed_opcodes.push(opcode.clone());
Expand Down
57 changes: 2 additions & 55 deletions acvm/src/pwg/directives/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::cmp::Ordering;

use acir::{
circuit::directives::{Directive, LogInfo, QuotientDirective},
circuit::directives::{Directive, QuotientDirective},
native_types::WitnessMap,
FieldElement,
};
Expand All @@ -10,7 +10,7 @@ use num_traits::Zero;

use crate::OpcodeResolutionError;

use super::{get_value, insert_value, witness_to_value, ErrorLocation};
use super::{get_value, insert_value, ErrorLocation};

mod sorting;

Expand All @@ -25,11 +25,6 @@ pub(super) fn solve_directives(
directive: &Directive,
) -> Result<(), OpcodeResolutionError> {
match directive {
Directive::Invert { x, result } => {
let val = witness_to_value(initial_witness, *x)?;
insert_value(result, val.inverse(), initial_witness)?;
Ok(())
}
Directive::Quotient(QuotientDirective { a, b, q, r, predicate }) => {
let val_a = get_value(a, initial_witness)?;
let val_b = get_value(b, initial_witness)?;
Expand Down Expand Up @@ -123,55 +118,7 @@ pub(super) fn solve_directives(
}
Ok(())
}
Directive::Log(info) => {
let witnesses = match info {
LogInfo::FinalizedOutput(output_string) => {
println!("{output_string}");
return Ok(());
}
LogInfo::WitnessOutput(witnesses) => witnesses,
};

if witnesses.len() == 1 {
let witness = &witnesses[0];
let log_value = witness_to_value(initial_witness, *witness)?;
println!("{}", format_field_string(*log_value));
return Ok(());
}

// If multiple witnesses are to be fetched for a log directive,
// it assumed that an array is meant to be printed to standard output
//
// Collect all field element values corresponding to the given witness indices
// and convert them to hex strings.
let mut elements_as_hex = Vec::with_capacity(witnesses.len());
for witness in witnesses {
let element = witness_to_value(initial_witness, *witness)?;
elements_as_hex.push(format_field_string(*element));
}

// Join all of the hex strings using a comma
let comma_separated_elements = elements_as_hex.join(", ");

let output_witnesses_string = "[".to_owned() + &comma_separated_elements + "]";

println!("{output_witnesses_string}");

Ok(())
}
}
}

/// This trims any leading zeroes.
/// A singular '0' will be prepended as well if the trimmed string has an odd length.
/// A hex string's length needs to be even to decode into bytes, as two digits correspond to
/// one byte.
fn format_field_string(field: FieldElement) -> String {
let mut trimmed_field = field.to_hex().trim_start_matches('0').to_owned();
if trimmed_field.len() % 2 != 0 {
trimmed_field = "0".to_owned() + &trimmed_field
}
"0x".to_owned() + &trimmed_field
}

#[cfg(test)]
Expand Down
Loading

0 comments on commit cfd8cbf

Please sign in to comment.