Skip to content
Open
Show file tree
Hide file tree
Changes from 10 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
493 changes: 493 additions & 0 deletions std/algebra/emulated/sw_bls12381/fixedbase_g2.go

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions std/algebra/emulated/sw_bls12381/fixedbase_g2_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package sw_bls12381

import (
"math/big"
"testing"

"github.com/consensys/gnark-crypto/ecc"
bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
fr_bls "github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/frontend/cs/r1cs"
"github.com/consensys/gnark/std/math/emulated"
"github.com/consensys/gnark/test"
)

type g2FixedMulCircuit struct {
S Scalar
Q G2Affine
}

func (c *g2FixedMulCircuit) Define(api frontend.API) error {
g2, err := NewG2(api)
if err != nil {
return err
}
_, _, _, gen := bls12381.Generators()
P := NewG2Affine(gen)
res := g2.ScalarMul(&P, &c.S)
g2.AssertIsEqual(res, &c.Q)
return nil
}

func TestG2FixedMulCount(t *testing.T) {
if testing.Short() {
t.Skip()
}
assert := test.NewAssert(t)
circuit := g2FixedMulCircuit{}
ccs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
assert.NoError(err)
t.Log("emulated G2 ScalarMul (const gen) r1cs constraints =", ccs.GetNbConstraints())
}

func TestG2FixedMulCorrectness(t *testing.T) {
assert := test.NewAssert(t)
_, _, _, gen := bls12381.Generators()
r := fr_bls.Modulus()
scalars := []*big.Int{
big.NewInt(0),
big.NewInt(1),
big.NewInt(2),
big.NewInt(3),
new(big.Int).Sub(r, big.NewInt(1)),
new(big.Int).Sub(r, big.NewInt(2)),
new(big.Int).Lsh(big.NewInt(1), 128),
}
for i := 0; i < 2; i++ {
var rnd fr_bls.Element
_, _ = rnd.SetRandom()
scalars = append(scalars, rnd.BigInt(new(big.Int)))
}
for _, s := range scalars {
var S bls12381.G2Affine
S.ScalarMultiplication(&gen, s)
circuit := g2FixedMulCircuit{}
witness := g2FixedMulCircuit{
S: emulated.ValueOf[ScalarField](s),
Q: NewG2Affine(S),
}
err := test.IsSolved(&circuit, &witness, ecc.BN254.ScalarField())
assert.NoError(err, "s=%s", s.String())
}
}
8 changes: 8 additions & 0 deletions std/algebra/emulated/sw_bls12381/g2.go
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,14 @@ func (g2 *G2) scalarMulGeneric(p *G2Affine, s *Scalar, opts ...algopts.AlgebraOp
//
// [EEMP25]: https://eprint.iacr.org/2025/933
func (g2 *G2) ScalarMul(Q *G2Affine, s *Scalar, opts ...algopts.AlgebraOption) *G2Affine {
// when Q is a compile-time constant subgroup point (for example a fixed
// verification-key or SRS point), use the fixed-base comb method with
// precomputed tables (see fixedbase_g2.go). It uses complete arithmetic
// and handles the zero scalar; [algopts.WithIncompleteArithmetic] is a
// no-op on this path.
if d, ok := g2.g2CombTryConst(Q); ok {
return g2.scalarMulComb(d, s)
}
return g2.scalarMulGLVAndFakeGLV(Q, s, opts...)
}

Expand Down
2 changes: 2 additions & 0 deletions std/algebra/emulated/sw_bls12381/hints.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ func GetHints() []solver.Hint {
pairingCheckHint,
millerLoopAndCheckFinalExpHint,
scalarMulG2Hint,
g2CombRecodeHint,
g2CombChainLambdaHint,
rationalReconstructExtG2,
g1SqrtRatioHint,
g2SqrtRatioHint,
Expand Down
Loading
Loading