Skip to content

Commit

Permalink
perf: two useful reductions, direct felt2var (#1277)
Browse files Browse the repository at this point in the history
  • Loading branch information
erabinov authored Aug 20, 2024
1 parent bce178c commit 2ec1165
Show file tree
Hide file tree
Showing 8 changed files with 34 additions and 4 deletions.
3 changes: 1 addition & 2 deletions crates/recursion/circuit/src/challenger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ pub fn reduce_32<C: Config>(builder: &mut Builder<C>, vals: &[Felt<C::F>]) -> Va
let mut power = C::N::one();
let result: Var<C::N> = builder.eval(C::N::zero());
for val in vals.iter() {
let bits = builder.num2bits_f_circuit(*val);
let val = builder.bits2num_v_circuit(&bits);
let val = builder.felt2var_circuit(*val);
builder.assign(result, result + val * power);
power *= C::N::from_canonical_u64(1u64 << 32);
}
Expand Down
4 changes: 4 additions & 0 deletions crates/recursion/circuit/src/fri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ pub fn verify_query<C: Config>(
let index_sibling: Var<_> = builder.eval(one - index_bits.clone()[offset]);
let index_pair = &index_bits[(offset + 1)..];

// Reduce folded_eval (mod the BabyBear prime) since it gets used multiple times below and
// the reductions will be repeated.
builder.reduce_e(folded_eval);

let evals_ext = [
builder.select_ef(index_sibling, folded_eval, step.sibling_value),
builder.select_ef(index_sibling, step.sibling_value, folded_eval),
Expand Down
4 changes: 4 additions & 0 deletions crates/recursion/compiler/src/constraints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,10 @@ impl<C: Config + Debug> ConstraintCompiler<C> {
opcode: ConstraintOpcode::ReduceE,
args: vec![vec![a.id()]],
}),
DslIr::CircuitFelt2Var(a, b) => constraints.push(Constraint {
opcode: ConstraintOpcode::CircuitFelt2Var,
args: vec![vec![b.id()], vec![a.id()]],
}),
_ => panic!("unsupported {:?}", instruction),
};
}
Expand Down
1 change: 1 addition & 0 deletions crates/recursion/compiler/src/constraints/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub enum ConstraintOpcode {
CommitVkeyHash,
CommitCommitedValuesDigest,
CircuitFelts2Ext,
CircuitFelt2Var,
PermuteBabyBear,
ReduceE,
}
6 changes: 6 additions & 0 deletions crates/recursion/compiler/src/ir/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,12 @@ impl<C: Config> Builder<C> {
self.operations.push(DslIr::ReduceE(ext));
}

pub fn felt2var_circuit(&mut self, felt: Felt<C::F>) -> Var<C::N> {
let var = self.uninit();
self.operations.push(DslIr::CircuitFelt2Var(felt, var));
var
}

pub fn cycle_tracker(&mut self, name: &str) {
self.operations.push(DslIr::CycleTracker(name.to_string()));
}
Expand Down
2 changes: 2 additions & 0 deletions crates/recursion/compiler/src/ir/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ pub enum DslIr<C: Config> {
/// Decompose a field element into bits (bits = num2bits(felt)). Should only be used when
/// target is a gnark circuit.
CircuitNum2BitsF(Felt<C::F>, Vec<Var<C::N>>),
/// Convert a Felt to a Var in a circuit. Avoids decomposing to bits and then reconstructing.
CircuitFelt2Var(Felt<C::F>, Var<C::N>),

// Hashing.
/// Permutes an array of baby bear elements using Poseidon2 (output = p2_permute(array)).
Expand Down
16 changes: 14 additions & 2 deletions crates/recursion/gnark-ffi/go/sp1/babybear/babybear.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,19 @@ func Zero() Variable {
}
}

func One() Variable {
return Variable{
Value: frontend.Variable("1"),
NbBits: 1,
}
}

func NewF(value string) Variable {
if value == "0" {
return Zero()
} else if value == "1" {
return One()
}
return Variable{
Value: frontend.Variable(value),
NbBits: 31,
Expand Down Expand Up @@ -105,7 +117,7 @@ func (c *Chip) MulFConst(a Variable, b int) Variable {
}

func (c *Chip) negF(a Variable) Variable {
if a.NbBits == 31 {
if a.NbBits <= 31 {
return Variable{Value: c.api.Sub(modulus, a.Value), NbBits: 31}
}

Expand Down Expand Up @@ -283,7 +295,7 @@ func (p *Chip) reduceFast(x Variable) Variable {
}

func (p *Chip) ReduceSlow(x Variable) Variable {
if x.NbBits == 31 {
if x.NbBits <= 31 {
return x
}
return Variable{
Expand Down
2 changes: 2 additions & 0 deletions crates/recursion/gnark-ffi/go/sp1/sp1.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ func (circuit *Circuit) Define(api frontend.API) error {
api.AssertIsEqual(circuit.CommitedValuesDigest, element)
case "CircuitFelts2Ext":
exts[cs.Args[0][0]] = babybear.Felts2Ext(felts[cs.Args[1][0]], felts[cs.Args[2][0]], felts[cs.Args[3][0]], felts[cs.Args[4][0]])
case "CircuitFelt2Var":
vars[cs.Args[0][0]] = fieldAPI.ReduceSlow(felts[cs.Args[1][0]]).Value
case "ReduceE":
exts[cs.Args[0][0]] = fieldAPI.ReduceE(exts[cs.Args[0][0]])
default:
Expand Down

0 comments on commit 2ec1165

Please sign in to comment.