Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
ivokub committed Nov 24, 2021
1 parent 0805908 commit 34221a9
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 73 deletions.
56 changes: 56 additions & 0 deletions std/algebra/sw/companions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package sw

import (
"fmt"
"math/big"
"sync"

"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/frontend"
)

func init() {
companionsOnce.Do(func() {
bls12377lambda := new(big.Int).SetBytes([]byte{0x45, 0x22, 0x17, 0xcc, 0x90, 0x00, 0x00, 0x01, 0x0a, 0x11, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00})
bls12377thirdRootOne := new(big.Int).SetBytes([]byte{
0x09, 0xb3, 0xaf, 0x05, 0xdd, 0x14, 0xf6, 0xec, 0x61, 0x9a, 0xaf, 0x7d, 0x34, 0x59,
0x4a, 0xab, 0xc5, 0xed, 0x13, 0x47, 0x97, 0x0d, 0xec, 0x00, 0x45, 0x22, 0x17, 0xcc,
0x90, 0x00, 0x00, 0x00, 0x85, 0x08, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01})
bls12377glvBasis := new(ecc.Lattice)
ecc.PrecomputeLattice(ecc.BLS12_377.Info().Fp.Modulus(), bls12377lambda, bls12377glvBasis)
companionCurves[ecc.BW6_761] = &companionConfig{
thirdRootOne: bls12377thirdRootOne,
glvBasis: bls12377glvBasis,
lambda: bls12377lambda,
fp: ecc.BLS12_377.Info().Fp.Modulus(),
fr: ecc.BLS12_377.Info().Fr.Modulus(),
}
})
}

var companionsOnce sync.Once

type companionConfig struct {
thirdRootOne *big.Int
glvBasis *ecc.Lattice
lambda *big.Int
fr *big.Int
fp *big.Int
}

var companionCurves = make(map[ecc.ID]*companionConfig)

func (cc *companionConfig) phi(api frontend.API, res, P *G1Affine) *G1Affine {
res.X = api.Mul(P.X, cc.thirdRootOne)
res.Y = P.Y
return res
}

// companionCurve returns the configuration of the companion elliptic curve
// which can be defined on the scalars of main curve.
func companionCurve(main ecc.ID) *companionConfig {
if cc, ok := companionCurves[main]; ok {
return cc
}
panic(fmt.Sprintf("curve %s does not have a companion curve", main.String()))
}
93 changes: 35 additions & 58 deletions std/algebra/sw/g1.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@ package sw
import (
"fmt"
"math/big"
"sync"

"github.com/consensys/gnark-crypto/ecc"
bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377"
bls12377fr "github.com/consensys/gnark-crypto/ecc/bls12-377/fr"
"github.com/consensys/gnark-crypto/ecc/bw6-761/fr"
"github.com/consensys/gnark/backend/hint"
"github.com/consensys/gnark/frontend"
Expand Down Expand Up @@ -258,52 +256,32 @@ func (P *G1Affine) ScalarMul(api frontend.API, Q G1Affine, s interface{}) *G1Aff
}
}

func ProverOptions() []hint.Function {

lambdaGLV, _ := new(big.Int).SetString("91893752504881257701523279626832445440", 10) //(x**2-1)
_r := fr.Modulus()
var glvBasis ecc.Lattice
ecc.PrecomputeLattice(_r, lambdaGLV, &glvBasis)
var once sync.Once
var k [2]*big.Int
fn1 := func(_ ecc.ID, inputs []*big.Int, res *big.Int) error {
once.Do(func() {
sp := ecc.SplitScalar(inputs[0], &glvBasis)
k[0] = &(sp[0])
k[1] = &(sp[1])
if k[0].Sign() == -1 {
k[0].Neg(k[0])
}
if k[1].Sign() == -1 {
k[1].Neg(k[1])
}
})
//k := ecc.SplitScalar(inputs[0], &glvBasis)
res.Set(k[0])
fmt.Printf("k1 %s\n", res)
return nil
func scalarDecompositionHint(curve ecc.ID, inputs []*big.Int, res *big.Int, id int) error {
if len(inputs) != 1 {
return fmt.Errorf("hint takes 1 input, got %d", len(inputs))
}
fn2 := func(_ ecc.ID, inputs []*big.Int, res *big.Int) error {
once.Do(func() {
sp := ecc.SplitScalar(inputs[0], &glvBasis)
k[0] = &(sp[0])
k[1] = &(sp[1])
if k[0].Sign() == -1 {
k[0].Neg(k[0])
}
if k[1].Sign() == -1 {
k[1].Neg(k[1])
}
})
res.Set(k[1])
fmt.Printf("k2 %s\n", res)
return nil
}
return []hint.Function{fn1, fn2}
cc := companionCurve(curve)
sp := ecc.SplitScalar(inputs[0], cc.glvBasis)
res.Set(&(sp[id]))
return nil
}

func scalarHintFree(curve ecc.ID, inputs []*big.Int, res *big.Int) error {
return scalarDecompositionHint(curve, inputs, res, 0)
}

func scalarHintZeta(curve ecc.ID, inputs []*big.Int, res *big.Int) error {
return scalarDecompositionHint(curve, inputs, res, 1)
}

func Hints() []hint.Function {
// TODO: when registry implemented, then use that
return []hint.Function{scalarHintFree, scalarHintZeta}
}

// varScalarMul sets P = [s] Q and returns P.
func (P *G1Affine) varScalarMul(api frontend.API, Q G1Affine, s frontend.Variable) *G1Affine {
cc := companionCurve(api.CurveID())
// We use a slightly different algorithm than in
// https://github.com/zcash/zcash/issues/3924.
//
Expand Down Expand Up @@ -332,17 +310,23 @@ func (P *G1Affine) varScalarMul(api frontend.API, Q G1Affine, s frontend.Variabl
// only a single curve pair which has the cyclic property, but there may be
// more in the future.

var Acc, B, B2, negQ, phiQ, negPhiQ G1Affine
// precompute -Q for selecting in loop
negQ.Neg(api, Q)
// precompute phi(Q) for selecting in loop
cc.phi(api, &phiQ, &Q)
// precompute -phi(Q) for selecting in loop
negPhiQ.Neg(api, phiQ)

// Add modulus to have high bit set.
//scalar := api.Add(s, frontend.Variable(bls12377fr.Modulus()))
scalar := s
//bits := api.ToBinary(scalar)
nbits := bls12377fr.Bits / 2
nbits := cc.fr.BitLen() / 2

hintfns := ProverOptions()
s1 := api.NewHint(hintfns[0], scalar)
s2 := api.NewHint(hintfns[1], scalar)
lambdaGLV, _ := new(big.Int).SetString("91893752504881257701523279626832445440", 10) //(x**2-1)
api.AssertIsEqual(api.Add(s1, api.Mul(s2, frontend.Variable(lambdaGLV))), scalar)
s1 := api.NewHint(scalarHintFree, scalar)
s2 := api.NewHint(scalarHintZeta, scalar)
api.AssertIsEqual(api.Add(s1, api.Mul(s2, cc.lambda)), scalar)
s1bits := api.ToBinary(s1)
s2bits := api.ToBinary(s2)
// s3 := api.Mul(s2, s1)
Expand All @@ -351,15 +335,6 @@ func (P *G1Affine) varScalarMul(api frontend.API, Q G1Affine, s frontend.Variabl
// api.Println(s2)
//api.Println("s1 ", s1, " s2 ", s2)

var Acc, B, B2, negQ, phiQ, negPhiQ G1Affine
// precompute -Q for selecting in loop
negQ.Neg(api, Q)
// precompute phi(Q) for selecting in loop
zetap, _ := new(big.Int).SetString("80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945", 10)
phiQ = G1Affine{X: api.Mul(zetap, Q.X), Y: Q.Y}
// precompute -phi(Q) for selecting in loop
negPhiQ.Neg(api, phiQ)

// Acc = Q + phi(Q)
Acc = Q
Acc.AddAssign(api, phiQ)
Expand Down Expand Up @@ -420,6 +395,8 @@ func (P *G1Affine) varScalarMul(api frontend.API, Q G1Affine, s frontend.Variabl

// constScalarMul sets P = [s] Q and returns P.
func (P *G1Affine) constScalarMul(api frontend.API, Q G1Affine, s *big.Int) *G1Affine {
// cc := companionCurve(api.CurveID())
// k := ecc.SplitScalar(s, cc.glvBasis)
var Acc, negAcc, B, negQ G1Affine
// precompute -Q for selecting in loop
negQ.Neg(api, Q)
Expand Down
21 changes: 6 additions & 15 deletions std/algebra/sw/g1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ func TestConstantScalarMulG1(t *testing.T) {

assert := test.NewAssert(t)
assert.SolvingSucceeded(&circuit, &witness, test.WithCurves(ecc.BW6_761), test.WithBackends(backend.GROTH16))
r1cs, _ := frontend.Compile(ecc.BW6_761, backend.GROTH16, &circuit)
fmt.Println(r1cs.GetNbConstraints())
}

type g1varScalarMul struct {
Expand Down Expand Up @@ -439,17 +441,6 @@ func BenchmarkVarScalarMulG1(b *testing.B) {

}

func TestMy(t *testing.T) {
ss, _ := new(big.Int).SetString("2712146564853141361744338623186898499825103294874005243335821277317143300594", 10)
lambdaGLV, _ := new(big.Int).SetString("91893752504881257701523279626832445440", 10) //(x**2-1)
_r := fr.Modulus()
var glvBasis ecc.Lattice
ecc.PrecomputeLattice(_r, lambdaGLV, &glvBasis)
k := ecc.SplitScalar(ss, &glvBasis)
t.Logf("k0: %s, k1: %s", k[0].String(), k[1].String())
t.Logf("V: %s", &glvBasis.Det)
}

func TestMy2(t *testing.T) {
// sample random point
//_a := randomPointG1()
Expand Down Expand Up @@ -482,13 +473,13 @@ func TestMy2(t *testing.T) {
assert.NoError(err)
pk, vk, err := groth16.Setup(ccs)
assert.NoError(err)
hints := ProverOptions()
hints := Hints()
provopt := backend.WithHints(hints...)
proof, err := groth16.Prove(ccs, pk, &witness, provopt)
assert.NoError(err)
err = groth16.Verify(proof, vk, &witness)
assert.NoError(err)
// assert.SolvingSucceeded(&circuit, &witness, test.WithCurves(ecc.BW6_761), test.WithBackends(backend.GROTH16))
// r1cs, _ := frontend.Compile(ecc.BW6_761, backend.GROTH16, &circuit)
// fmt.Println(r1cs.GetNbConstraints())
assert.SolvingSucceeded(&circuit, &witness, test.WithCurves(ecc.BW6_761), test.WithBackends(backend.GROTH16), test.WithProverOpts(backend.WithHints(hints...)))
r1cs, _ := frontend.Compile(ecc.BW6_761, backend.GROTH16, &circuit)
fmt.Println(r1cs.GetNbConstraints())
}

0 comments on commit 34221a9

Please sign in to comment.