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

chore!: Remove manual serialization of Opcodes in favour of serde #286

Merged
merged 3 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
45 changes: 0 additions & 45 deletions acir/src/circuit/black_box_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,42 +31,6 @@ impl std::fmt::Display for BlackBoxFunc {
}

impl BlackBoxFunc {
pub fn to_u16(self) -> u16 {
match self {
BlackBoxFunc::AES => 0,
BlackBoxFunc::SHA256 => 1,
BlackBoxFunc::ComputeMerkleRoot => 2,
BlackBoxFunc::SchnorrVerify => 3,
BlackBoxFunc::Blake2s => 4,
BlackBoxFunc::Pedersen => 5,
BlackBoxFunc::HashToField128Security => 6,
BlackBoxFunc::EcdsaSecp256k1 => 7,
BlackBoxFunc::FixedBaseScalarMul => 8,
BlackBoxFunc::AND => 9,
BlackBoxFunc::XOR => 10,
BlackBoxFunc::RANGE => 11,
BlackBoxFunc::Keccak256 => 12,
}
}
pub fn from_u16(index: u16) -> Option<Self> {
let function = match index {
0 => BlackBoxFunc::AES,
1 => BlackBoxFunc::SHA256,
2 => BlackBoxFunc::ComputeMerkleRoot,
3 => BlackBoxFunc::SchnorrVerify,
4 => BlackBoxFunc::Blake2s,
5 => BlackBoxFunc::Pedersen,
6 => BlackBoxFunc::HashToField128Security,
7 => BlackBoxFunc::EcdsaSecp256k1,
8 => BlackBoxFunc::FixedBaseScalarMul,
9 => BlackBoxFunc::AND,
10 => BlackBoxFunc::XOR,
11 => BlackBoxFunc::RANGE,
12 => BlackBoxFunc::Keccak256,
_ => return None,
};
Some(function)
}
pub fn name(&self) -> &'static str {
match self {
BlackBoxFunc::AES => "aes",
Expand Down Expand Up @@ -125,13 +89,4 @@ mod test {
)
}
}
#[test]
fn consistent_index() {
for bb_func in BlackBoxFunc::iter() {
let func_index = bb_func.to_u16();
let got_bb_func =
BlackBoxFunc::from_u16(func_index).expect("blackbox function should have an index");
assert_eq!(got_bb_func, bb_func, "BlackBox function index lookup is inconsistent")
}
}
}
238 changes: 1 addition & 237 deletions acir/src/circuit/directives.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
use std::io::{Read, Write};

use crate::{
native_types::{Expression, Witness},
serialization::{read_bytes, read_n, read_u16, read_u32, write_bytes, write_u16, write_u32},
};
use crate::native_types::{Expression, Witness};
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
Expand Down Expand Up @@ -57,168 +52,6 @@ impl Directive {
Directive::Log { .. } => "log",
}
}
fn to_u16(&self) -> u16 {
match self {
Directive::Invert { .. } => 0,
Directive::Quotient { .. } => 1,
Directive::ToLeRadix { .. } => 2,
Directive::PermutationSort { .. } => 3,
Directive::Log { .. } => 4,
}
}

pub fn write<W: Write>(&self, mut writer: W) -> std::io::Result<()> {
write_u16(&mut writer, self.to_u16())?;
match self {
Directive::Invert { x, result } => {
write_u32(&mut writer, x.witness_index())?;
write_u32(&mut writer, result.witness_index())?;
}
Directive::Quotient(QuotientDirective { a, b, q, r, predicate }) => {
a.write(&mut writer)?;
b.write(&mut writer)?;
write_u32(&mut writer, q.witness_index())?;
write_u32(&mut writer, r.witness_index())?;

let predicate_is_some = vec![predicate.is_some() as u8];
write_bytes(&mut writer, &predicate_is_some)?;

if let Some(pred) = predicate {
pred.write(&mut writer)?;
}
}
Directive::ToLeRadix { a, b, radix } => {
a.write(&mut writer)?;
write_u32(&mut writer, b.len() as u32)?;
for bit in b {
write_u32(&mut writer, bit.witness_index())?;
}
write_u32(&mut writer, *radix)?;
}
Directive::PermutationSort { inputs: a, tuple, bits, sort_by } => {
write_u32(&mut writer, *tuple)?;
write_u32(&mut writer, a.len() as u32)?;
for e in a {
for i in 0..*tuple {
e[i as usize].write(&mut writer)?;
}
}
write_u32(&mut writer, bits.len() as u32)?;
for b in bits {
write_u32(&mut writer, b.witness_index())?;
}
write_u32(&mut writer, sort_by.len() as u32)?;
for i in sort_by {
write_u32(&mut writer, *i)?;
}
}
Directive::Log(info) => {
write_u16(&mut writer, info.to_u16())?;
match info {
LogInfo::FinalizedOutput(output_string) => {
write_u32(&mut writer, output_string.len() as u32)?;
write_bytes(&mut writer, output_string.as_bytes())?;
}
LogInfo::WitnessOutput(witnesses) => {
write_u32(&mut writer, witnesses.len() as u32)?;
for w in witnesses {
write_u32(&mut writer, w.witness_index())?;
}
}
}
}
};

Ok(())
}

pub fn read<R: Read>(mut reader: R) -> std::io::Result<Self> {
let directive_index = read_u16(&mut reader)?;

match directive_index {
0 => {
let x = Witness(read_u32(&mut reader)?);
let result = Witness(read_u32(&mut reader)?);
Ok(Directive::Invert { x, result })
}
1 => {
let a = Expression::read(&mut reader)?;
let b = Expression::read(&mut reader)?;
let q = Witness(read_u32(&mut reader)?);
let r = Witness(read_u32(&mut reader)?);

// Read byte to figure out if there is a predicate
let predicate_is_some = read_n::<1, _>(&mut reader)?[0] != 0;
let predicate = match predicate_is_some {
true => Some(Expression::read(&mut reader)?),
false => None,
};

Ok(Directive::Quotient(QuotientDirective { a, b, q, r, predicate }))
}
2 => {
let a = Expression::read(&mut reader)?;
let b_len = read_u32(&mut reader)?;
let mut b = Vec::with_capacity(b_len as usize);
for _ in 0..b_len {
let witness = Witness(read_u32(&mut reader)?);
b.push(witness)
}

let radix = read_u32(&mut reader)?;

Ok(Directive::ToLeRadix { a, b, radix })
}
3 => {
let tuple = read_u32(&mut reader)?;
let a_len = read_u32(&mut reader)?;
let mut a = Vec::with_capacity(a_len as usize);
for _ in 0..a_len {
let mut element = Vec::new();
for _ in 0..tuple {
element.push(Expression::read(&mut reader)?);
}
a.push(element);
}

let bits_len = read_u32(&mut reader)?;
let mut bits = Vec::with_capacity(bits_len as usize);
for _ in 0..bits_len {
bits.push(Witness(read_u32(&mut reader)?));
}
let sort_by_len = read_u32(&mut reader)?;
let mut sort_by = Vec::with_capacity(sort_by_len as usize);
for _ in 0..sort_by_len {
sort_by.push(read_u32(&mut reader)?);
}
Ok(Directive::PermutationSort { inputs: a, tuple, bits, sort_by })
}
4 => {
let log_info_index = read_u16(&mut reader)?;
let output_len = read_u32(&mut reader)?;
let log_info = match log_info_index {
0 => {
let output_bytes = read_bytes(&mut reader, output_len as usize)?;
let output_string = String::from_utf8(output_bytes)
.or::<std::io::Error>(Err(std::io::ErrorKind::InvalidData.into()))?;
LogInfo::FinalizedOutput(output_string)
}
1 => {
let mut output_witnesses = Vec::with_capacity(output_len as usize);
for _ in 0..output_len {
let witness = Witness(read_u32(&mut reader)?);
output_witnesses.push(witness)
}
LogInfo::WitnessOutput(output_witnesses)
}
_ => return Err(std::io::ErrorKind::InvalidData.into()),
};
Ok(Directive::Log(log_info))
}

_ => Err(std::io::ErrorKind::InvalidData.into()),
}
}
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
Expand All @@ -230,72 +63,3 @@ pub enum LogInfo {
FinalizedOutput(String),
WitnessOutput(Vec<Witness>),
}

impl LogInfo {
fn to_u16(&self) -> u16 {
match self {
LogInfo::FinalizedOutput(_) => 0,
LogInfo::WitnessOutput(_) => 1,
}
}
}

#[test]
fn serialization_roundtrip() {
fn read_write(directive: Directive) -> (Directive, Directive) {
let mut bytes = Vec::new();
directive.write(&mut bytes).unwrap();
let got_dir = Directive::read(&*bytes).unwrap();

(directive, got_dir)
}
// TODO: Find a way to ensure that we include all of the variants
let invert = Directive::Invert { x: Witness(10), result: Witness(10) };

let quotient_none = Directive::Quotient(QuotientDirective {
a: Expression::default(),
b: Expression::default(),
q: Witness(1u32),
r: Witness(2u32),
predicate: None,
});
let quotient_predicate = Directive::Quotient(QuotientDirective {
a: Expression::default(),
b: Expression::default(),
q: Witness(1u32),
r: Witness(2u32),
predicate: Some(Expression::default()),
});

let to_le_radix = Directive::ToLeRadix {
a: Expression::default(),
b: vec![Witness(1u32), Witness(2u32), Witness(3u32), Witness(4u32)],
radix: 4,
};

let permutation_sort = Directive::PermutationSort {
inputs: vec![vec![Expression::default()], vec![Expression::default()]],
tuple: 1,
bits: vec![Witness(1u32), Witness(2u32)],
sort_by: vec![0, 1],
};

let log_string = Directive::Log(LogInfo::FinalizedOutput("test string to log".to_owned()));
let log_witnesses =
Directive::Log(LogInfo::WitnessOutput(vec![Witness(1u32), Witness(2u32), Witness(3u32)]));

let directives = vec![
invert,
quotient_none,
quotient_predicate,
to_le_radix,
log_string,
log_witnesses,
permutation_sort,
];

for directive in directives {
let (dir, got_dir) = read_write(directive);
assert_eq!(dir, got_dir);
}
}
Loading