Skip to content

Commit

Permalink
implement to_radix (#587)
Browse files Browse the repository at this point in the history
* implement to_radix

* fix clippy

* clippy fix

* clippy fix...

* clippy fix....

* clippy fix.....

* update backend commit

* Code review

* merge from master

* Fix the build

* try_range_constraint

Co-authored-by: kevaundray <[email protected]>
  • Loading branch information
guipublic and kevaundray authored Jan 11, 2023
1 parent 2f6f760 commit 67dd7cd
Show file tree
Hide file tree
Showing 13 changed files with 360 additions and 261 deletions.
36 changes: 10 additions & 26 deletions crates/acir/src/circuit/gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ impl Gate {
Gate::Directive(Directive::Truncate { .. }) => "truncate",
Gate::Directive(Directive::Quotient { .. }) => "quotient",
Gate::Directive(Directive::Oddrange { .. }) => "odd_range",
Gate::Directive(Directive::Split { .. }) => "split",
Gate::Directive(Directive::ToBytes { .. }) => "to_bytes",
Gate::Directive(Directive::ToRadix { .. }) => "to_radix",
Gate::GadgetCall(g) => g.name.name(),
}
}
Expand Down Expand Up @@ -78,9 +77,9 @@ impl std::fmt::Debug for Gate {
Gate::Directive(Directive::Truncate { a, b, c: _c, bit_size }) => {
write!(
f,
"Truncate: x{} is x{} truncated to {} bits",
"Truncate: x{} is {} truncated to {} bits",
b.witness_index(),
a.witness_index(),
a,
bit_size
)
}
Expand Down Expand Up @@ -120,20 +119,12 @@ impl std::fmt::Debug for Gate {
Gate::And(g) => write!(f, "{:?}", g),
Gate::Xor(g) => write!(f, "{:?}", g),
Gate::GadgetCall(g) => write!(f, "{:?}", g),
Gate::Directive(Directive::Split { a, b, bit_size: _ }) => {
write!(
f,
"Split: {} into x{}...x{}",
a,
b.first().unwrap().witness_index(),
b.last().unwrap().witness_index(),
)
}
Gate::Directive(Directive::ToBytes { a, b, byte_size: _ }) => {
Gate::Directive(Directive::ToRadix { a, b, radix }) => {
write!(
f,
"To Bytes: {} into x{}...x{}",
"To Radix: {} into base {}; x{}...x{}",
a,
radix,
b.first().unwrap().witness_index(),
b.last().unwrap().witness_index(),
)
Expand Down Expand Up @@ -162,7 +153,7 @@ pub enum Directive {

//Reduces the value of a modulo 2^bit_size and stores the result in b: a= c*2^bit_size + b
Truncate {
a: Witness,
a: Expression,
b: Witness,
c: Witness,
bit_size: u32,
Expand All @@ -176,18 +167,11 @@ pub enum Directive {
bit_size: u32,
},

//bit decomposition of a: a=\sum b[i]*2^i
Split {
a: Expression,
b: Vec<Witness>,
bit_size: u32,
},

//byte decomposition of a: a=\sum b[i]*2^i where b is a byte array
ToBytes {
//decomposition of a: a=\sum b[i]*radix^i where b is an array of witnesses < radix
ToRadix {
a: Expression,
b: Vec<Witness>,
byte_size: u32,
radix: u32,
},
}

Expand Down
6 changes: 5 additions & 1 deletion crates/acir/src/fallback/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ pub fn split(
g.linear_combinations.push((-two_pow, w));
two_pow = FieldElement::from(2_i128) * two_pow;
}
new_gates.push(Gate::Directive(Directive::Split { a: gate, b: bit_vector.clone(), bit_size }));
new_gates.push(Gate::Directive(Directive::ToRadix {
a: gate,
b: bit_vector.clone(),
radix: 2,
}));
new_gates.extend(intermediate_gates);
g.sort();
new_gates.push(Gate::Arithmetic(g));
Expand Down
18 changes: 0 additions & 18 deletions crates/acir/src/opcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ pub enum OPCODE {
HashToField,
EcdsaSecp256k1,
FixedBaseScalarMul,
ToBits,
ToBytes,
}

impl std::fmt::Display for OPCODE {
Expand All @@ -35,8 +33,6 @@ impl OPCODE {
OPCODE::HashToField => 6,
OPCODE::EcdsaSecp256k1 => 7,
OPCODE::FixedBaseScalarMul => 8,
OPCODE::ToBits => 9,
OPCODE::ToBytes => 10,
}
}
pub fn name(&self) -> &str {
Expand All @@ -50,8 +46,6 @@ impl OPCODE {
OPCODE::HashToField => "hash_to_field",
OPCODE::EcdsaSecp256k1 => "ecdsa_secp256k1",
OPCODE::FixedBaseScalarMul => "fixed_base_scalar_mul",
OPCODE::ToBits => "to_bits",
OPCODE::ToBytes => "to_bytes",
}
}
pub fn lookup(op_name: &str) -> Option<OPCODE> {
Expand All @@ -64,8 +58,6 @@ impl OPCODE {
"hash_to_field" => Some(OPCODE::HashToField),
"ecdsa_secp256k1" => Some(OPCODE::EcdsaSecp256k1),
"fixed_base_scalar_mul" => Some(OPCODE::FixedBaseScalarMul),
"to_bits" => Some(OPCODE::ToBits),
"to_bytes" => Some(OPCODE::ToBytes),
_ => None,
}
}
Expand Down Expand Up @@ -118,16 +110,6 @@ impl OPCODE {
input_size: InputSize::Fixed(1),
output_size: OutputSize(2),
},
OPCODE::ToBits => GadgetDefinition {
name: self.name().into(),
input_size: InputSize::Fixed(2),
output_size: OutputSize(1),
},
OPCODE::ToBytes => GadgetDefinition {
name: self.name().into(),
input_size: InputSize::Fixed(2),
output_size: OutputSize(1),
},
}
}
}
Expand Down
75 changes: 28 additions & 47 deletions crates/acvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,62 +133,43 @@ pub trait PartialWitnessGenerator {
_ => true,
}
}
Directive::Truncate { a, b, c, bit_size } => match initial_witness.get(a) {
Some(val_a) => {
let pow: BigUint = BigUint::one() << bit_size;

let int_a = BigUint::from_bytes_be(&val_a.to_bytes());
let int_b: BigUint = &int_a % &pow;
let int_c: BigUint = (&int_a - &int_b) / &pow;

initial_witness.insert(
*b,
FieldElement::from_be_bytes_reduce(&int_b.to_bytes_be()),
);
initial_witness.insert(
*c,
FieldElement::from_be_bytes_reduce(&int_c.to_bytes_be()),
);
false
}
_ => true,
},
Directive::Split { a, b, bit_size } => {
Directive::Truncate { a, b, c, bit_size } => {
match Self::get_value(a, initial_witness) {
Some(val_a) => {
let a_big = BigUint::from_bytes_be(&val_a.to_bytes());
for i in 0..*bit_size {
let j = i as usize;
let v = if a_big.bit(j as u64) {
FieldElement::one()
} else {
FieldElement::zero()
};
match initial_witness.entry(b[j]) {
std::collections::btree_map::Entry::Vacant(e) => {
e.insert(v);
}
std::collections::btree_map::Entry::Occupied(e) => {
if e.get() != &v {
return GateResolution::UnsatisfiedConstrain;
}
}
}
}
let pow: BigUint = BigUint::one() << bit_size;

let int_a = BigUint::from_bytes_be(&val_a.to_bytes());
let int_b: BigUint = &int_a % &pow;
let int_c: BigUint = (&int_a - &int_b) / &pow;

initial_witness.insert(
*b,
FieldElement::from_be_bytes_reduce(&int_b.to_bytes_be()),
);
initial_witness.insert(
*c,
FieldElement::from_be_bytes_reduce(&int_c.to_bytes_be()),
);
false
}
_ => true,
}
}
Directive::ToBytes { a, b, byte_size } => {
Directive::ToRadix { a, b, radix } => {
match Self::get_value(a, initial_witness) {
Some(val_a) => {
let mut a_bytes = val_a.to_bytes();
a_bytes.reverse();
for i in 0..*byte_size {
let i_usize = i as usize;
let v = FieldElement::from_be_bytes_reduce(&[a_bytes[i_usize]]);
match initial_witness.entry(b[i_usize]) {
let a_big = BigUint::from_bytes_be(&val_a.to_bytes());
let a_dec = a_big.to_radix_le(*radix);
if b.len() < a_dec.len() {
return GateResolution::UnsatisfiedConstrain;
}
for i in 0..b.len() {
let v = if i < a_dec.len() {
FieldElement::from_be_bytes_reduce(&[a_dec[i]])
} else {
FieldElement::zero()
};
match initial_witness.entry(b[i]) {
std::collections::btree_map::Entry::Vacant(e) => {
e.insert(v);
}
Expand Down
Loading

0 comments on commit 67dd7cd

Please sign in to comment.