Skip to content

Commit

Permalink
fix: JointScalarMulBase without GLV (for ecdsa package)
Browse files Browse the repository at this point in the history
  • Loading branch information
yelhousni committed Mar 6, 2024
1 parent 64299a1 commit c759df0
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 2 deletions.
36 changes: 34 additions & 2 deletions std/algebra/emulated/sw_emulated/point.go
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,39 @@ func (c *Curve[B, S]) scalarMulBaseGeneric(s *emulated.Element[S], opts ...algop
return res
}

// JointScalarMulBase computes [s]G + [t]Q and returns it, where G is the
// JointScalarMulBase computes [s]G + [t]Q and returns it, where G is the
// fixed generator. It doesn't modify Q, s and t.
//
// This function doesn't check that the Q is on the curve. See AssertIsOnCurve.
//
// JointScalarMulBase calls jointScalarMulGeneric or jointScalarMulBaseGLV depending on whether an efficient endomorphism is available.
func (c *Curve[B, S]) JointScalarMulBase(Q *AffinePoint[B], s, t *emulated.Element[S], opts ...algopts.AlgebraOption) *AffinePoint[B] {
if c.params.Eigenvalue != nil && c.params.ThirdRootOne != nil {
return c.jointScalarMulBaseGLV(Q, s, t, opts...)

} else {
return c.jointScalarMulGeneric(c.Generator(), Q, t, s, opts...)

}

}

func (c *Curve[B, S]) jointScalarMulBaseGLV(Q *AffinePoint[B], s, t *emulated.Element[S], opts ...algopts.AlgebraOption) *AffinePoint[B] {
cfg, err := algopts.NewConfig(opts...)
if err != nil {
panic(fmt.Sprintf("parse opts: %v", err))
}
if cfg.CompleteArithmetic {
// TODO @yelhousni: optimize
res1 := c.ScalarMulBase(s, opts...)
res2 := c.scalarMulGLV(Q, t, opts...)
return c.AddUnified(res1, res2)
} else {
return c.jointScalarMulBaseGLVUnsafe(Q, s, t)
}
}

// JointScalarMulBaseGLVUnsafe computes [s]G + [t]Q using an endomorphism and returns it, where G is the
// fixed generator. It doesn't modify Q, s and t.
//
// ⚠️ Q must NOT be (0,0).
Expand All @@ -1161,7 +1193,7 @@ func (c *Curve[B, S]) scalarMulBaseGeneric(s *emulated.Element[S], opts ...algop
//
// The [EVM] specifies these checks, wich are performed on the zkEVM
// arithmetization side before calling the circuit that uses this method.
func (c *Curve[B, S]) JointScalarMulBase(Q *AffinePoint[B], s, t *emulated.Element[S], opts ...algopts.AlgebraOption) *AffinePoint[B] {
func (c *Curve[B, S]) jointScalarMulBaseGLVUnsafe(Q *AffinePoint[B], s, t *emulated.Element[S]) *AffinePoint[B] {
var st S
frModulus := c.scalarApi.Modulus()
sd, err := c.scalarApi.NewHint(decomposeScalarG1, 7, s, c.eigenvalue, frModulus)
Expand Down
29 changes: 29 additions & 0 deletions std/algebra/emulated/sw_emulated/point_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1001,6 +1001,35 @@ func TestJointScalarMulBase(t *testing.T) {
assert.NoError(err)
}

func TestJointScalarMulBase4(t *testing.T) {
assert := test.NewAssert(t)
p256 := elliptic.P256()
s1, err := rand.Int(rand.Reader, p256.Params().N)
assert.NoError(err)
s2, err := rand.Int(rand.Reader, p256.Params().N)
assert.NoError(err)
p1x, p1y := p256.ScalarBaseMult(s1.Bytes())
resx, resy := p256.ScalarMult(p1x, p1y, s1.Bytes())
tmpx, tmpy := p256.ScalarBaseMult(s2.Bytes())
resx, resy = p256.Add(resx, resy, tmpx, tmpy)

circuit := JointScalarMulBaseTest[emulated.P256Fp, emulated.P256Fr]{}
witness := JointScalarMulBaseTest[emulated.P256Fp, emulated.P256Fr]{
S1: emulated.ValueOf[emulated.P256Fr](s2),
S2: emulated.ValueOf[emulated.P256Fr](s1),
P: AffinePoint[emulated.P256Fp]{
X: emulated.ValueOf[emulated.P256Fp](p1x),
Y: emulated.ValueOf[emulated.P256Fp](p1y),
},
Q: AffinePoint[emulated.P256Fp]{
X: emulated.ValueOf[emulated.P256Fp](resx),
Y: emulated.ValueOf[emulated.P256Fp](resy),
},
}
err = test.IsSolved(&circuit, &witness, testCurve.ScalarField())
assert.NoError(err)
}

type MultiScalarMulEdgeCasesTest[T, S emulated.FieldParams] struct {
Points []AffinePoint[T]
Scalars []emulated.Element[S]
Expand Down

0 comments on commit c759df0

Please sign in to comment.