Skip to content

Commit 2d76977

Browse files
authored
Add Builtin trait and refactor all builtin functions to use it (#244)
Refactor builtin function to Builtin trait
1 parent 99c3935 commit 2d76977

File tree

4 files changed

+281
-227
lines changed

4 files changed

+281
-227
lines changed

src/stdlib/bits.rs

+81-70
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ use crate::{
1212
var::{ConstOrCell, Value, Var},
1313
};
1414

15-
use super::{FnInfoType, Module};
16-
17-
const NTH_BIT_FN: &str = "nth_bit(val: Field, const nth: Field) -> Field";
18-
const CHECK_FIELD_SIZE_FN: &str = "check_field_size(cmp: Field)";
15+
use super::{builtins::Builtin, FnInfoType, Module};
1916

2017
pub struct BitsLib {}
2118

@@ -24,81 +21,95 @@ impl Module for BitsLib {
2421

2522
fn get_fns<B: Backend>() -> Vec<(&'static str, FnInfoType<B>, bool)> {
2623
vec![
27-
(NTH_BIT_FN, nth_bit, false),
28-
(CHECK_FIELD_SIZE_FN, check_field_size, false),
24+
(NthBitFn::SIGNATURE, NthBitFn::builtin, false),
25+
(
26+
CheckFieldSizeFn::SIGNATURE,
27+
CheckFieldSizeFn::builtin,
28+
false,
29+
),
2930
]
3031
}
3132
}
3233

33-
fn nth_bit<B: Backend>(
34-
compiler: &mut CircuitWriter<B>,
35-
_generics: &GenericParameters,
36-
vars: &[VarInfo<B::Field, B::Var>],
37-
span: Span,
38-
) -> Result<Option<Var<B::Field, B::Var>>> {
39-
// should be two input vars
40-
assert_eq!(vars.len(), 2);
41-
42-
// these should be type checked already, unless it is called by other low level functions
43-
// eg. builtins
44-
let var_info = &vars[0];
45-
let val = &var_info.var;
46-
assert_eq!(val.len(), 1);
47-
48-
let var_info = &vars[1];
49-
let nth = &var_info.var;
50-
assert_eq!(nth.len(), 1);
51-
52-
let nth: usize = match &nth[0] {
53-
ConstOrCell::Cell(_) => unreachable!("nth should be a constant"),
54-
ConstOrCell::Const(cst) => cst.to_u64() as usize,
55-
};
56-
57-
let val = match &val[0] {
58-
ConstOrCell::Cell(cvar) => cvar.clone(),
59-
ConstOrCell::Const(cst) => {
60-
// directly return the nth bit without adding symbolic value as it doesn't depend on a cell var
61-
let bit = cst.to_bits();
62-
return Ok(Some(Var::new_cvar(
63-
ConstOrCell::Const(B::Field::from(bit[nth])),
64-
span,
65-
)));
66-
}
67-
};
34+
struct NthBitFn {}
35+
struct CheckFieldSizeFn {}
36+
37+
impl Builtin for NthBitFn {
38+
const SIGNATURE: &'static str = "nth_bit(val: Field, const nth: Field) -> Field";
39+
40+
fn builtin<B: Backend>(
41+
compiler: &mut CircuitWriter<B>,
42+
_generics: &GenericParameters,
43+
vars: &[VarInfo<B::Field, B::Var>],
44+
span: Span,
45+
) -> Result<Option<Var<B::Field, B::Var>>> {
46+
// should be two input vars
47+
assert_eq!(vars.len(), 2);
48+
49+
// these should be type checked already, unless it is called by other low level functions
50+
// eg. builtins
51+
let var_info = &vars[0];
52+
let val = &var_info.var;
53+
assert_eq!(val.len(), 1);
54+
55+
let var_info = &vars[1];
56+
let nth = &var_info.var;
57+
assert_eq!(nth.len(), 1);
58+
59+
let nth: usize = match &nth[0] {
60+
ConstOrCell::Cell(_) => unreachable!("nth should be a constant"),
61+
ConstOrCell::Const(cst) => cst.to_u64() as usize,
62+
};
63+
64+
let val = match &val[0] {
65+
ConstOrCell::Cell(cvar) => cvar.clone(),
66+
ConstOrCell::Const(cst) => {
67+
// directly return the nth bit without adding symbolic value as it doesn't depend on a cell var
68+
let bit = cst.to_bits();
69+
return Ok(Some(Var::new_cvar(
70+
ConstOrCell::Const(B::Field::from(bit[nth])),
71+
span,
72+
)));
73+
}
74+
};
6875

69-
let bit = compiler
70-
.backend
71-
.new_internal_var(Value::NthBit(val.clone(), nth), span);
76+
let bit = compiler
77+
.backend
78+
.new_internal_var(Value::NthBit(val.clone(), nth), span);
7279

73-
Ok(Some(Var::new(vec![ConstOrCell::Cell(bit)], span)))
80+
Ok(Some(Var::new(vec![ConstOrCell::Cell(bit)], span)))
81+
}
7482
}
7583

76-
// Ensure that the field size is not exceeded
77-
fn check_field_size<B: Backend>(
78-
_compiler: &mut CircuitWriter<B>,
79-
_generics: &GenericParameters,
80-
vars: &[VarInfo<B::Field, B::Var>],
81-
span: Span,
82-
) -> Result<Option<Var<B::Field, B::Var>>> {
83-
let var = &vars[0].var[0];
84-
let bit_len = B::Field::MODULUS_BIT_SIZE as u64;
85-
86-
match var {
87-
ConstOrCell::Const(cst) => {
88-
let to_cmp = cst.to_u64();
89-
if to_cmp >= bit_len {
90-
return Err(Error::new(
91-
"constraint-generation",
92-
ErrorKind::AssertionFailed,
93-
span,
94-
));
84+
impl Builtin for CheckFieldSizeFn {
85+
const SIGNATURE: &'static str = "check_field_size(cmp: Field)";
86+
87+
fn builtin<B: Backend>(
88+
_compiler: &mut CircuitWriter<B>,
89+
_generics: &GenericParameters,
90+
vars: &[VarInfo<B::Field, B::Var>],
91+
span: Span,
92+
) -> Result<Option<Var<B::Field, B::Var>>> {
93+
let var = &vars[0].var[0];
94+
let bit_len = B::Field::MODULUS_BIT_SIZE as u64;
95+
96+
match var {
97+
ConstOrCell::Const(cst) => {
98+
let to_cmp = cst.to_u64();
99+
if to_cmp >= bit_len {
100+
return Err(Error::new(
101+
"constraint-generation",
102+
ErrorKind::AssertionFailed,
103+
span,
104+
));
105+
}
106+
Ok(None)
95107
}
96-
Ok(None)
108+
ConstOrCell::Cell(_) => Err(Error::new(
109+
"constraint-generation",
110+
ErrorKind::ExpectedConstant,
111+
span,
112+
)),
97113
}
98-
ConstOrCell::Cell(_) => Err(Error::new(
99-
"constraint-generation",
100-
ErrorKind::ExpectedConstant,
101-
span,
102-
)),
103114
}
104115
}

0 commit comments

Comments
 (0)