Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: two useful reductions, direct felt2var #1277

Merged
merged 3 commits into from
Aug 20, 2024
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
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
Loading