Skip to content
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
20 changes: 10 additions & 10 deletions internal/stats/latest_stats.csv
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ math/emulated/secp256k1_64,bn254,groth16,1037,1890
math/emulated/secp256k1_64,bls12_377,groth16,1037,1890
math/emulated/secp256k1_64,bls12_381,groth16,1037,1890
math/emulated/secp256k1_64,bw6_761,groth16,1037,1890
math/emulated/secp256k1_64,bn254,plonk,4280,4178
math/emulated/secp256k1_64,bls12_377,plonk,4280,4178
math/emulated/secp256k1_64,bls12_381,plonk,4280,4178
math/emulated/secp256k1_64,bw6_761,plonk,4280,4178
math/emulated/secp256k1_64,bn254,plonk,4025,3923
math/emulated/secp256k1_64,bls12_377,plonk,4025,3923
math/emulated/secp256k1_64,bls12_381,plonk,4025,3923
math/emulated/secp256k1_64,bw6_761,plonk,4025,3923
pairing_bls12377,bn254,groth16,0,0
pairing_bls12377,bls12_377,groth16,0,0
pairing_bls12377,bls12_381,groth16,0,0
Expand All @@ -99,47 +99,47 @@ pairing_bls12381,bn254,groth16,946127,1565085
pairing_bls12381,bls12_377,groth16,0,0
pairing_bls12381,bls12_381,groth16,0,0
pairing_bls12381,bw6_761,groth16,0,0
pairing_bls12381,bn254,plonk,3249854,3113604
pairing_bls12381,bn254,plonk,3184319,3048069
pairing_bls12381,bls12_377,plonk,0,0
pairing_bls12381,bls12_381,plonk,0,0
pairing_bls12381,bw6_761,plonk,0,0
pairing_bn254,bn254,groth16,607339,995018
pairing_bn254,bls12_377,groth16,0,0
pairing_bn254,bls12_381,groth16,0,0
pairing_bn254,bw6_761,groth16,0,0
pairing_bn254,bn254,plonk,2053232,1971118
pairing_bn254,bn254,plonk,1987697,1905583
pairing_bn254,bls12_377,plonk,0,0
pairing_bn254,bls12_381,plonk,0,0
pairing_bn254,bw6_761,plonk,0,0
pairing_bw6761,bn254,groth16,1782130,2981326
pairing_bw6761,bls12_377,groth16,0,0
pairing_bw6761,bls12_381,groth16,0,0
pairing_bw6761,bw6_761,groth16,0,0
pairing_bw6761,bn254,plonk,6088164,5845211
pairing_bw6761,bn254,plonk,6022629,5779676
pairing_bw6761,bls12_377,plonk,0,0
pairing_bw6761,bls12_381,plonk,0,0
pairing_bw6761,bw6_761,plonk,0,0
scalar_mul_G1_bn254,bn254,groth16,55279,87825
scalar_mul_G1_bn254,bls12_377,groth16,0,0
scalar_mul_G1_bn254,bls12_381,groth16,0,0
scalar_mul_G1_bn254,bw6_761,groth16,0,0
scalar_mul_G1_bn254,bn254,plonk,201599,194727
scalar_mul_G1_bn254,bn254,plonk,199552,192680
scalar_mul_G1_bn254,bls12_377,plonk,0,0
scalar_mul_G1_bn254,bls12_381,plonk,0,0
scalar_mul_G1_bn254,bw6_761,plonk,0,0
scalar_mul_P256,bn254,groth16,75326,121582
scalar_mul_P256,bls12_377,groth16,0,0
scalar_mul_P256,bls12_381,groth16,0,0
scalar_mul_P256,bw6_761,groth16,0,0
scalar_mul_P256,bn254,plonk,270364,261074
scalar_mul_P256,bn254,plonk,262173,252883
scalar_mul_P256,bls12_377,plonk,0,0
scalar_mul_P256,bls12_381,plonk,0,0
scalar_mul_P256,bw6_761,plonk,0,0
scalar_mul_secp256k1,bn254,groth16,55961,88905
scalar_mul_secp256k1,bls12_377,groth16,0,0
scalar_mul_secp256k1,bls12_381,groth16,0,0
scalar_mul_secp256k1,bw6_761,groth16,0,0
scalar_mul_secp256k1,bn254,plonk,204108,197145
scalar_mul_secp256k1,bn254,plonk,202061,195098
scalar_mul_secp256k1,bls12_377,plonk,0,0
scalar_mul_secp256k1,bls12_381,plonk,0,0
scalar_mul_secp256k1,bw6_761,plonk,0,0
Expand Down
75 changes: 71 additions & 4 deletions std/internal/logderivarg/logderivarg.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func init() {

// GetHints returns all hints used in this package
func GetHints() []solver.Hint {
return []solver.Hint{countHint}
return []solver.Hint{countHint, batchDivBySubHint}
}

// Table is a vector of vectors.
Expand Down Expand Up @@ -122,9 +122,50 @@ func Build(api frontend.API, table Table, queries Table) error {
multicommit.WithCommitment(api, func(api frontend.API, commitment frontend.Variable) error {
rowCoeffs, challenge := randLinearCoefficients(api, nbRow, commitment)
var lp frontend.Variable = 0
for i := range table {
tmp := api.DivUnchecked(exps[i], api.Sub(challenge, randLinearCombination(api, rowCoeffs, table[i])))
lp = api.Add(lp, tmp)

// For constant single-column tables with PlonkAPI, merge Sub+DivUnchecked
// into a single PLONK gate per table entry (2 gates instead of 3).
plonkAPI, useOptimizedTable := api.(frontend.PlonkAPI)
if useOptimizedTable && constTable && nbRow == 1 {
// verify all constant values fit in int (required by AddPlonkConstraint)
for i := range table {
cv, _ := api.Compiler().ConstantValue(table[i][0])
if cv == nil || !cv.IsInt64() {
useOptimizedTable = false
break
}
}
} else {
useOptimizedTable = false
}

if useOptimizedTable {
n := len(table)
hintInputs := make([]frontend.Variable, 1+2*n)
hintInputs[0] = challenge
for i := range table {
hintInputs[1+i] = exps[i]
hintInputs[1+n+i] = table[i][0]
}
quotients, err := api.NewHint(batchDivBySubHint, n, hintInputs...)
if err != nil {
return fmt.Errorf("batch div hint: %w", err)
}
for i := range table {
constVal, _ := api.Compiler().ConstantValue(table[i][0])
c := int(constVal.Int64())
// Verify quotient[i] * (challenge - c) == exps[i] in one PLONK gate:
// qM*q*ch + qL*q + qR*ch + qO*exps + qC = 0
// 1*q*ch + (-c)*q + 0*ch + (-1)*exps + 0 = 0
// => q*(ch - c) = exps
plonkAPI.AddPlonkConstraint(quotients[i], challenge, exps[i], -c, 0, -1, 1, 0)
Comment thread
cursor[bot] marked this conversation as resolved.
lp = api.Add(lp, quotients[i])
}
} else {
for i := range table {
tmp := api.DivUnchecked(exps[i], api.Sub(challenge, randLinearCombination(api, rowCoeffs, table[i])))
lp = api.Add(lp, tmp)
}
}
var rp frontend.Variable = 0

Expand Down Expand Up @@ -245,6 +286,32 @@ func randLinearCombinationExt(extapi fieldextension.Field, rowCoeffs []fieldexte
return res
}

// batchDivBySubHint computes outputs[i] = inputs[1+i] / (inputs[0] - inputs[1+n+i])
// where n = len(outputs).
// inputs: [challenge, numerator_0, ..., numerator_{n-1}, denomOffset_0, ..., denomOffset_{n-1}]
// outputs: [quotient_0, ..., quotient_{n-1}]
func batchDivBySubHint(m *big.Int, inputs []*big.Int, outputs []*big.Int) error {
n := len(outputs)
if len(inputs) != 1+2*n {
return fmt.Errorf("expected %d inputs, got %d", 1+2*n, len(inputs))
}
challenge := inputs[0]
diff := new(big.Int)
for i := 0; i < n; i++ {
numerator := inputs[1+i]
tableVal := inputs[1+n+i]
diff.Sub(challenge, tableVal)
diff.Mod(diff, m)
diffInv := new(big.Int).ModInverse(diff, m)
if diffInv == nil {
return fmt.Errorf("no modular inverse at index %d", i)
}
outputs[i].Mul(numerator, diffInv)
outputs[i].Mod(outputs[i], m)
}
return nil
}

func countHint(m *big.Int, inputs []*big.Int, outputs []*big.Int) error {
if len(inputs) <= 2 {
return fmt.Errorf("at least two input required")
Expand Down