Repository: Consensys/gnark-crypto

Issue:
bug: ...
Today I have updated our base code to gnark-crypto@master, and suddenly a previously working circuit for ElGamal decryption, stop working...

After digging for I while, I think I have found the issue.
 
When performing a scalar multiplication on the Identity point `(0, 1)` of a Twisted Edwards curve (specifically tested on BN254/BabyJubJub), the result is `(0, 0)` instead of `(0, 1)`.

The point `(0, 0)` is not a valid point on the twisted edwards curve equation. This issue seems to affects both the off-circuit `gnark-crypto` library and the in-circuit `gnark` standard library constraints.

## Reproduction Steps (gnark-crypto)

```go
package main

import (
	"fmt"
	"math/big"

	"github.com/consensys/gnark-crypto/ecc/bn254/twistededwards"
)

func main() {
	// 1. Initialize Identity Point (0, 1)
	p := &twistededwards.PointAffine{}
	p.X.SetZero()
	p.Y.SetOne()

	fmt.Printf("Original: X=%s Y=%s\n", p.X.String(), p.Y.String())

	// 2. Perform Scalar Multiplication by random scalar
	scalar := big.NewInt(12345)
	res := &twistededwards.PointAffine{}
	res.ScalarMultiplication(p, scalar)

	fmt.Printf("Result:   X=%s Y=%s\n", res.X.String(), res.Y.String())

	// 3. Check
	if res.X.IsZero() && res.Y.IsZero() {
		fmt.Println("FAIL: Result is (0,0) which is invalid.")
	} else if res.X.IsZero() && res.Y.IsOne() {
		fmt.Println("PASS: Result is Identity (0,1).")
	} else {
		fmt.Println("FAIL: Unexpected result.")
	}
}
```

Using the current master branch 

`go get github.com/consensys/gnark-crypto@master`

```
Original: X=0 Y=1
Result:   X=0 Y=0
FAIL: Result is (0,0) which is invalid.
```

However, using the @latest release, the result is correct.

---

The in-circuit `std/algebra/native/twistededwards` implementation also fails when `ScalarMul` is called as an Identity witness, triggering an assertion failure.

```go
package main

import (
	testing

	"github.com/consensys/gnark-crypto/ecc"
	"github.com/consensys/gnark/frontend"
	"github.com/consensys/gnark/std/algebra/native/twistededwards"
	"github.com/consensys/gnark/test"
)

type TestCircuit struct {
	PointX frontend.Variable
	PointY frontend.Variable
}

func (c *TestCircuit) Define(api frontend.API) error {
	curve, _ := twistededwards.NewEdCurve(api, ecc.BN254)
	p := twistededwards.Point{X: c.PointX, Y: c.PointY}

	// This fails with "assertIsEqual 0 == 1" inside the scalar mul logic
	_ = curve.ScalarMul(p, 12345)
	return nil
}

func TestIdentityScalarMult(t *testing.T) {
	assert := test.NewAssert(t)
	witness := TestCircuit{PointX: 0, PointY: 1} // Identity
	assert.CheckCircuit(&TestCircuit{}, test.WithValidAssignment(&witness))
}
```


Discussion:
@ivokub: Thanks for the issue. It is definitely a regression and we try to fix it soon.

cc @yelhousni @ivokub: I think it probably comes from https://github.com/Consensys/gnark-crypto/pull/743 - usually for affine coordinates we represent infinity point as `(0,0)`, interesting that it used to be `(0,1)` before. It was probably a bug before, but we still shouldn't do regressions

For your use case, is it possible to update the arithmetic to assume `(0,0)` being infinity point? Or it would require breaking changes on your side? In this case imo we can decide if we want to have some kind of backwards compatibility layer or not.@yelhousni: No the neutral point on twisted Edwards curves is the affine point `(0,1)`, contrary to Weierstrass curve where it is a point at infinity and we take conventionally `(0,0)` as a representation when this point is not on the curve. I am investigating the issue.@yelhousni: ok found the bug and fixed it. I will do a clean PR tomorrow with more tests, but here is the bug: In  https://github.com/ConsenSys/gnark-crypto/tree/2e354b07c43bc29e6f8b4d3aeddfd825f61b8dc5/ecc/bn254/twistededwards/point.go#L282 we use `MixedAdd(p,q)` which implements a dedicated addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.2). This gives an incorrect result when `p` or `q` are the neutral points or equal. We should have implemented the ScalarMul with unified addition from Sec. 3.1, this bug was introduced in https://github.com/Consensys/gnark-crypto/pull/743. See 
- fix 
https://github.com/ConsenSys/gnark-crypto/tree/57a6d084ea34296cc3066e2906c72fa4aa962098/ecc/bn254/twistededwards/point.go#L365
- test 
https://github.com/ConsenSys/gnark-crypto/tree/57a6d084ea34296cc3066e2906c72fa4aa962098/ecc/bn254/twistededwards/point_test.go#L38

Solution patch:
diff --git a/ecc/bls12-377/twistededwards/point.go b/ecc/bls12-377/twistededwards/point.go
index cb2518993..cf0455105 100644
--- a/ecc/bls12-377/twistededwards/point.go
+++ b/ecc/bls12-377/twistededwards/point.go
@@ -177,6 +177,8 @@ func (p *PointAffine) Neg(p1 *PointAffine) *PointAffine {
 
 // Add adds two points (x,y), (u,v) on a twisted Edwards curve with parameters a, d
 // modifies p
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 	initOnce.Do(initCurveParams)
@@ -209,6 +211,8 @@ func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 // Double doubles point (x,y) on a twisted Edwards curve with parameters a, d
 // modifies p
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
 func (p *PointAffine) Double(p1 *PointAffine) *PointAffine {
 
 	var A, B, C, D, E, F, G, H fr.Element
@@ -360,13 +364,15 @@ func (p *PointProj) FromAffine(p1 *PointAffine) *PointProj {
 	return p
 }
 
-// MixedAdd adds a point in projective to a point in affine coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
-func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
+// Add adds points in projective coordinates
+// Unified Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
+func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var B, C, D, E, F, G, H, I fr.Element
-	B.Square(&p1.Z)
+	var A, B, C, D, E, F, G, H, I fr.Element
+	A.Mul(&p1.Z, &p2.Z)
+	B.Square(&A)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -377,11 +383,12 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &p1.Z).
+		Mul(&p.X, &A).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	p.Y.Sub(&D, &C).
-		Mul(&p.Y, &p1.Z).
+	C.Neg(&C)
+	p.Y.Add(&D, &C).
+		Mul(&p.Y, &A).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -389,7 +396,8 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 }
 
 // Double adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/013.pdf
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
 func (p *PointProj) Double(p1 *PointProj) *PointProj {
 
 	var B, C, D, E, F, H, J fr.Element
@@ -411,14 +419,14 @@ func (p *PointProj) Double(p1 *PointProj) *PointProj {
 	return p
 }
 
-// Add adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
-func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
+// MixedAdd adds a point in projective to a point in affine coordinates
+// Mixed Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
+func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var A, B, C, D, E, F, G, H, I fr.Element
-	A.Mul(&p1.Z, &p2.Z)
-	B.Square(&A)
+	var B, C, D, E, F, G, H, I fr.Element
+	B.Square(&p1.Z)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -429,12 +437,11 @@ func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &A).
+		Mul(&p.X, &p1.Z).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	C.Neg(&C)
-	p.Y.Add(&D, &C).
-		Mul(&p.Y, &A).
+	p.Y.Sub(&D, &C).
+		Mul(&p.Y, &p1.Z).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -526,7 +533,8 @@ func (p *PointExtended) FromAffine(p1 *PointAffine) *PointExtended {
 }
 
 // Add adds points in extended coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	var A, B, C, D, E, F, G, H, tmp fr.Element
 	A.Mul(&p1.X, &p2.X)
@@ -552,37 +560,8 @@ func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedAdd adds a point in extended coordinates to a point in affine coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd-2
-func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
-	var A, B, C, D, E, F, G, H, tmp fr.Element
-
-	A.Mul(&p1.X, &p2.X)
-	B.Mul(&p1.Y, &p2.Y)
-	C.Mul(&p1.Z, &p2.X).
-		Mul(&C, &p2.Y)
-	D.Set(&p1.T)
-	E.Add(&D, &C)
-	tmp.Sub(&p1.X, &p1.Y)
-	F.Add(&p2.X, &p2.Y).
-		Mul(&F, &tmp).
-		Add(&F, &B).
-		Sub(&F, &A)
-	G.Set(&A)
-	mulByA(&G)
-	G.Add(&G, &B)
-	H.Sub(&D, &C)
-
-	p.X.Mul(&E, &F)
-	p.Y.Mul(&G, &H)
-	p.T.Mul(&E, &H)
-	p.Z.Mul(&F, &G)
-
-	return p
-}
-
 // Double adds points in extended coordinates
-// Dedicated doubling
+// (Dedicated) doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
 // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd
 func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 
@@ -610,32 +589,33 @@ func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedDouble adds points in extended coordinates
-// Dedicated mixed doubling
-// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-mdbl-2008-hwcd
-func (p *PointExtended) MixedDouble(p1 *PointExtended) *PointExtended {
-
-	var A, B, D, E, G, H, two fr.Element
-	two.SetUint64(2)
+// MixedAdd adds a point in extended coordinates to a point in affine coordinates
+// Unified Mixed Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd
+func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
+	initOnce.Do(initCurveParams)
+	var A, B, C, D, E, F, G, H, tmp fr.Element
 
-	A.Square(&p1.X)
-	B.Square(&p1.Y)
-	D.Set(&A)
-	mulByA(&D)
-	E.Add(&p1.X, &p1.Y).
-		Square(&E).
+	A.Mul(&p1.X, &p2.X)
+	B.Mul(&p1.Y, &p2.Y)
+	C.Mul(&p1.T, &p2.X).
+		Mul(&C, &p2.Y).
+		Mul(&C, &curveParams.D)
+	D.Set(&p1.Z)
+	tmp.Add(&p1.X, &p1.Y)
+	E.Add(&p2.X, &p2.Y).
+		Mul(&E, &tmp).
 		Sub(&E, &A).
 		Sub(&E, &B)
-	G.Add(&D, &B)
-	H.Sub(&D, &B)
-
-	p.X.Sub(&G, &two).
-		Mul(&p.X, &E)
+	F.Sub(&D, &C)
+	G.Add(&D, &C)
+	H.Set(&A)
+	mulByA(&H)
+	H.Sub(&B, &H)
+	p.X.Mul(&E, &F)
 	p.Y.Mul(&G, &H)
-	p.T.Mul(&H, &E)
-	p.Z.Square(&G).
-		Sub(&p.Z, &G).
-		Sub(&p.Z, &G)
+	p.T.Mul(&E, &H)
+	p.Z.Mul(&F, &G)
 
 	return p
 }
diff --git a/ecc/bls12-381/bandersnatch/point.go b/ecc/bls12-381/bandersnatch/point.go
index 547cb0e39..dfdb7c399 100644
--- a/ecc/bls12-381/bandersnatch/point.go
+++ b/ecc/bls12-381/bandersnatch/point.go
@@ -235,6 +235,8 @@ func (p *PointAffine) Neg(p1 *PointAffine) *PointAffine {
 
 // Add adds two points (x,y), (u,v) on a twisted Edwards curve with parameters a, d
 // modifies p
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 	initOnce.Do(initCurveParams)
@@ -267,6 +269,8 @@ func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 // Double doubles point (x,y) on a twisted Edwards curve with parameters a, d
 // modifies p
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
 func (p *PointAffine) Double(p1 *PointAffine) *PointAffine {
 
 	var A, B, C, D, E, F, G, H fr.Element
@@ -418,13 +422,15 @@ func (p *PointProj) FromAffine(p1 *PointAffine) *PointProj {
 	return p
 }
 
-// MixedAdd adds a point in projective to a point in affine coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
-func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
+// Add adds points in projective coordinates
+// Unified Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
+func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var B, C, D, E, F, G, H, I fr.Element
-	B.Square(&p1.Z)
+	var A, B, C, D, E, F, G, H, I fr.Element
+	A.Mul(&p1.Z, &p2.Z)
+	B.Square(&A)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -435,11 +441,12 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &p1.Z).
+		Mul(&p.X, &A).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	p.Y.Sub(&D, &C).
-		Mul(&p.Y, &p1.Z).
+	C.Neg(&C)
+	p.Y.Add(&D, &C).
+		Mul(&p.Y, &A).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -447,7 +454,8 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 }
 
 // Double adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/013.pdf
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
 func (p *PointProj) Double(p1 *PointProj) *PointProj {
 
 	var B, C, D, E, F, H, J fr.Element
@@ -469,14 +477,14 @@ func (p *PointProj) Double(p1 *PointProj) *PointProj {
 	return p
 }
 
-// Add adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
-func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
+// MixedAdd adds a point in projective to a point in affine coordinates
+// Mixed Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
+func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var A, B, C, D, E, F, G, H, I fr.Element
-	A.Mul(&p1.Z, &p2.Z)
-	B.Square(&A)
+	var B, C, D, E, F, G, H, I fr.Element
+	B.Square(&p1.Z)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -487,12 +495,11 @@ func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &A).
+		Mul(&p.X, &p1.Z).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	C.Neg(&C)
-	p.Y.Add(&D, &C).
-		Mul(&p.Y, &A).
+	p.Y.Sub(&D, &C).
+		Mul(&p.Y, &p1.Z).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -584,7 +591,8 @@ func (p *PointExtended) FromAffine(p1 *PointAffine) *PointExtended {
 }
 
 // Add adds points in extended coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	var A, B, C, D, E, F, G, H, tmp fr.Element
 	A.Mul(&p1.X, &p2.X)
@@ -610,37 +618,8 @@ func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedAdd adds a point in extended coordinates to a point in affine coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd-2
-func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
-	var A, B, C, D, E, F, G, H, tmp fr.Element
-
-	A.Mul(&p1.X, &p2.X)
-	B.Mul(&p1.Y, &p2.Y)
-	C.Mul(&p1.Z, &p2.X).
-		Mul(&C, &p2.Y)
-	D.Set(&p1.T)
-	E.Add(&D, &C)
-	tmp.Sub(&p1.X, &p1.Y)
-	F.Add(&p2.X, &p2.Y).
-		Mul(&F, &tmp).
-		Add(&F, &B).
-		Sub(&F, &A)
-	G.Set(&A)
-	mulByA(&G)
-	G.Add(&G, &B)
-	H.Sub(&D, &C)
-
-	p.X.Mul(&E, &F)
-	p.Y.Mul(&G, &H)
-	p.T.Mul(&E, &H)
-	p.Z.Mul(&F, &G)
-
-	return p
-}
-
 // Double adds points in extended coordinates
-// Dedicated doubling
+// (Dedicated) doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
 // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd
 func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 
@@ -668,32 +647,33 @@ func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedDouble adds points in extended coordinates
-// Dedicated mixed doubling
-// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-mdbl-2008-hwcd
-func (p *PointExtended) MixedDouble(p1 *PointExtended) *PointExtended {
-
-	var A, B, D, E, G, H, two fr.Element
-	two.SetUint64(2)
+// MixedAdd adds a point in extended coordinates to a point in affine coordinates
+// Unified Mixed Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd
+func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
+	initOnce.Do(initCurveParams)
+	var A, B, C, D, E, F, G, H, tmp fr.Element
 
-	A.Square(&p1.X)
-	B.Square(&p1.Y)
-	D.Set(&A)
-	mulByA(&D)
-	E.Add(&p1.X, &p1.Y).
-		Square(&E).
+	A.Mul(&p1.X, &p2.X)
+	B.Mul(&p1.Y, &p2.Y)
+	C.Mul(&p1.T, &p2.X).
+		Mul(&C, &p2.Y).
+		Mul(&C, &curveParams.D)
+	D.Set(&p1.Z)
+	tmp.Add(&p1.X, &p1.Y)
+	E.Add(&p2.X, &p2.Y).
+		Mul(&E, &tmp).
 		Sub(&E, &A).
 		Sub(&E, &B)
-	G.Add(&D, &B)
-	H.Sub(&D, &B)
-
-	p.X.Sub(&G, &two).
-		Mul(&p.X, &E)
+	F.Sub(&D, &C)
+	G.Add(&D, &C)
+	H.Set(&A)
+	mulByA(&H)
+	H.Sub(&B, &H)
+	p.X.Mul(&E, &F)
 	p.Y.Mul(&G, &H)
-	p.T.Mul(&H, &E)
-	p.Z.Square(&G).
-		Sub(&p.Z, &G).
-		Sub(&p.Z, &G)
+	p.T.Mul(&E, &H)
+	p.Z.Mul(&F, &G)
 
 	return p
 }
diff --git a/ecc/bls12-381/twistededwards/point.go b/ecc/bls12-381/twistededwards/point.go
index 978862412..88da15de7 100644
--- a/ecc/bls12-381/twistededwards/point.go
+++ b/ecc/bls12-381/twistededwards/point.go
@@ -177,6 +177,8 @@ func (p *PointAffine) Neg(p1 *PointAffine) *PointAffine {
 
 // Add adds two points (x,y), (u,v) on a twisted Edwards curve with parameters a, d
 // modifies p
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 	initOnce.Do(initCurveParams)
@@ -209,6 +211,8 @@ func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 // Double doubles point (x,y) on a twisted Edwards curve with parameters a, d
 // modifies p
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
 func (p *PointAffine) Double(p1 *PointAffine) *PointAffine {
 
 	var A, B, C, D, E, F, G, H fr.Element
@@ -360,13 +364,15 @@ func (p *PointProj) FromAffine(p1 *PointAffine) *PointProj {
 	return p
 }
 
-// MixedAdd adds a point in projective to a point in affine coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
-func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
+// Add adds points in projective coordinates
+// Unified Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
+func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var B, C, D, E, F, G, H, I fr.Element
-	B.Square(&p1.Z)
+	var A, B, C, D, E, F, G, H, I fr.Element
+	A.Mul(&p1.Z, &p2.Z)
+	B.Square(&A)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -377,11 +383,12 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &p1.Z).
+		Mul(&p.X, &A).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	p.Y.Sub(&D, &C).
-		Mul(&p.Y, &p1.Z).
+	C.Neg(&C)
+	p.Y.Add(&D, &C).
+		Mul(&p.Y, &A).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -389,7 +396,8 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 }
 
 // Double adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/013.pdf
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
 func (p *PointProj) Double(p1 *PointProj) *PointProj {
 
 	var B, C, D, E, F, H, J fr.Element
@@ -411,14 +419,14 @@ func (p *PointProj) Double(p1 *PointProj) *PointProj {
 	return p
 }
 
-// Add adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
-func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
+// MixedAdd adds a point in projective to a point in affine coordinates
+// Mixed Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
+func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var A, B, C, D, E, F, G, H, I fr.Element
-	A.Mul(&p1.Z, &p2.Z)
-	B.Square(&A)
+	var B, C, D, E, F, G, H, I fr.Element
+	B.Square(&p1.Z)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -429,12 +437,11 @@ func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &A).
+		Mul(&p.X, &p1.Z).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	C.Neg(&C)
-	p.Y.Add(&D, &C).
-		Mul(&p.Y, &A).
+	p.Y.Sub(&D, &C).
+		Mul(&p.Y, &p1.Z).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -526,7 +533,8 @@ func (p *PointExtended) FromAffine(p1 *PointAffine) *PointExtended {
 }
 
 // Add adds points in extended coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	var A, B, C, D, E, F, G, H, tmp fr.Element
 	A.Mul(&p1.X, &p2.X)
@@ -552,37 +560,8 @@ func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedAdd adds a point in extended coordinates to a point in affine coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd-2
-func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
-	var A, B, C, D, E, F, G, H, tmp fr.Element
-
-	A.Mul(&p1.X, &p2.X)
-	B.Mul(&p1.Y, &p2.Y)
-	C.Mul(&p1.Z, &p2.X).
-		Mul(&C, &p2.Y)
-	D.Set(&p1.T)
-	E.Add(&D, &C)
-	tmp.Sub(&p1.X, &p1.Y)
-	F.Add(&p2.X, &p2.Y).
-		Mul(&F, &tmp).
-		Add(&F, &B).
-		Sub(&F, &A)
-	G.Set(&A)
-	mulByA(&G)
-	G.Add(&G, &B)
-	H.Sub(&D, &C)
-
-	p.X.Mul(&E, &F)
-	p.Y.Mul(&G, &H)
-	p.T.Mul(&E, &H)
-	p.Z.Mul(&F, &G)
-
-	return p
-}
-
 // Double adds points in extended coordinates
-// Dedicated doubling
+// (Dedicated) doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
 // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd
 func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 
@@ -610,32 +589,33 @@ func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedDouble adds points in extended coordinates
-// Dedicated mixed doubling
-// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-mdbl-2008-hwcd
-func (p *PointExtended) MixedDouble(p1 *PointExtended) *PointExtended {
-
-	var A, B, D, E, G, H, two fr.Element
-	two.SetUint64(2)
+// MixedAdd adds a point in extended coordinates to a point in affine coordinates
+// Unified Mixed Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd
+func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
+	initOnce.Do(initCurveParams)
+	var A, B, C, D, E, F, G, H, tmp fr.Element
 
-	A.Square(&p1.X)
-	B.Square(&p1.Y)
-	D.Set(&A)
-	mulByA(&D)
-	E.Add(&p1.X, &p1.Y).
-		Square(&E).
+	A.Mul(&p1.X, &p2.X)
+	B.Mul(&p1.Y, &p2.Y)
+	C.Mul(&p1.T, &p2.X).
+		Mul(&C, &p2.Y).
+		Mul(&C, &curveParams.D)
+	D.Set(&p1.Z)
+	tmp.Add(&p1.X, &p1.Y)
+	E.Add(&p2.X, &p2.Y).
+		Mul(&E, &tmp).
 		Sub(&E, &A).
 		Sub(&E, &B)
-	G.Add(&D, &B)
-	H.Sub(&D, &B)
-
-	p.X.Sub(&G, &two).
-		Mul(&p.X, &E)
+	F.Sub(&D, &C)
+	G.Add(&D, &C)
+	H.Set(&A)
+	mulByA(&H)
+	H.Sub(&B, &H)
+	p.X.Mul(&E, &F)
 	p.Y.Mul(&G, &H)
-	p.T.Mul(&H, &E)
-	p.Z.Square(&G).
-		Sub(&p.Z, &G).
-		Sub(&p.Z, &G)
+	p.T.Mul(&E, &H)
+	p.Z.Mul(&F, &G)
 
 	return p
 }
diff --git a/ecc/bls24-315/twistededwards/point.go b/ecc/bls24-315/twistededwards/point.go
index 7832ef5ce..d282a0e30 100644
--- a/ecc/bls24-315/twistededwards/point.go
+++ b/ecc/bls24-315/twistededwards/point.go
@@ -177,6 +177,8 @@ func (p *PointAffine) Neg(p1 *PointAffine) *PointAffine {
 
 // Add adds two points (x,y), (u,v) on a twisted Edwards curve with parameters a, d
 // modifies p
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 	initOnce.Do(initCurveParams)
@@ -209,6 +211,8 @@ func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 // Double doubles point (x,y) on a twisted Edwards curve with parameters a, d
 // modifies p
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
 func (p *PointAffine) Double(p1 *PointAffine) *PointAffine {
 
 	var A, B, C, D, E, F, G, H fr.Element
@@ -360,13 +364,15 @@ func (p *PointProj) FromAffine(p1 *PointAffine) *PointProj {
 	return p
 }
 
-// MixedAdd adds a point in projective to a point in affine coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
-func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
+// Add adds points in projective coordinates
+// Unified Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
+func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var B, C, D, E, F, G, H, I fr.Element
-	B.Square(&p1.Z)
+	var A, B, C, D, E, F, G, H, I fr.Element
+	A.Mul(&p1.Z, &p2.Z)
+	B.Square(&A)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -377,11 +383,12 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &p1.Z).
+		Mul(&p.X, &A).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	p.Y.Sub(&D, &C).
-		Mul(&p.Y, &p1.Z).
+	C.Neg(&C)
+	p.Y.Add(&D, &C).
+		Mul(&p.Y, &A).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -389,7 +396,8 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 }
 
 // Double adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/013.pdf
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
 func (p *PointProj) Double(p1 *PointProj) *PointProj {
 
 	var B, C, D, E, F, H, J fr.Element
@@ -411,14 +419,14 @@ func (p *PointProj) Double(p1 *PointProj) *PointProj {
 	return p
 }
 
-// Add adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
-func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
+// MixedAdd adds a point in projective to a point in affine coordinates
+// Mixed Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
+func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var A, B, C, D, E, F, G, H, I fr.Element
-	A.Mul(&p1.Z, &p2.Z)
-	B.Square(&A)
+	var B, C, D, E, F, G, H, I fr.Element
+	B.Square(&p1.Z)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -429,12 +437,11 @@ func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &A).
+		Mul(&p.X, &p1.Z).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	C.Neg(&C)
-	p.Y.Add(&D, &C).
-		Mul(&p.Y, &A).
+	p.Y.Sub(&D, &C).
+		Mul(&p.Y, &p1.Z).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -526,7 +533,8 @@ func (p *PointExtended) FromAffine(p1 *PointAffine) *PointExtended {
 }
 
 // Add adds points in extended coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	var A, B, C, D, E, F, G, H, tmp fr.Element
 	A.Mul(&p1.X, &p2.X)
@@ -552,37 +560,8 @@ func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedAdd adds a point in extended coordinates to a point in affine coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd-2
-func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
-	var A, B, C, D, E, F, G, H, tmp fr.Element
-
-	A.Mul(&p1.X, &p2.X)
-	B.Mul(&p1.Y, &p2.Y)
-	C.Mul(&p1.Z, &p2.X).
-		Mul(&C, &p2.Y)
-	D.Set(&p1.T)
-	E.Add(&D, &C)
-	tmp.Sub(&p1.X, &p1.Y)
-	F.Add(&p2.X, &p2.Y).
-		Mul(&F, &tmp).
-		Add(&F, &B).
-		Sub(&F, &A)
-	G.Set(&A)
-	mulByA(&G)
-	G.Add(&G, &B)
-	H.Sub(&D, &C)
-
-	p.X.Mul(&E, &F)
-	p.Y.Mul(&G, &H)
-	p.T.Mul(&E, &H)
-	p.Z.Mul(&F, &G)
-
-	return p
-}
-
 // Double adds points in extended coordinates
-// Dedicated doubling
+// (Dedicated) doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
 // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd
 func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 
@@ -610,32 +589,33 @@ func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedDouble adds points in extended coordinates
-// Dedicated mixed doubling
-// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-mdbl-2008-hwcd
-func (p *PointExtended) MixedDouble(p1 *PointExtended) *PointExtended {
-
-	var A, B, D, E, G, H, two fr.Element
-	two.SetUint64(2)
+// MixedAdd adds a point in extended coordinates to a point in affine coordinates
+// Unified Mixed Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd
+func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
+	initOnce.Do(initCurveParams)
+	var A, B, C, D, E, F, G, H, tmp fr.Element
 
-	A.Square(&p1.X)
-	B.Square(&p1.Y)
-	D.Set(&A)
-	mulByA(&D)
-	E.Add(&p1.X, &p1.Y).
-		Square(&E).
+	A.Mul(&p1.X, &p2.X)
+	B.Mul(&p1.Y, &p2.Y)
+	C.Mul(&p1.T, &p2.X).
+		Mul(&C, &p2.Y).
+		Mul(&C, &curveParams.D)
+	D.Set(&p1.Z)
+	tmp.Add(&p1.X, &p1.Y)
+	E.Add(&p2.X, &p2.Y).
+		Mul(&E, &tmp).
 		Sub(&E, &A).
 		Sub(&E, &B)
-	G.Add(&D, &B)
-	H.Sub(&D, &B)
-
-	p.X.Sub(&G, &two).
-		Mul(&p.X, &E)
+	F.Sub(&D, &C)
+	G.Add(&D, &C)
+	H.Set(&A)
+	mulByA(&H)
+	H.Sub(&B, &H)
+	p.X.Mul(&E, &F)
 	p.Y.Mul(&G, &H)
-	p.T.Mul(&H, &E)
-	p.Z.Square(&G).
-		Sub(&p.Z, &G).
-		Sub(&p.Z, &G)
+	p.T.Mul(&E, &H)
+	p.Z.Mul(&F, &G)
 
 	return p
 }
diff --git a/ecc/bls24-317/twistededwards/point.go b/ecc/bls24-317/twistededwards/point.go
index 149ac740a..53834ae92 100644
--- a/ecc/bls24-317/twistededwards/point.go
+++ b/ecc/bls24-317/twistededwards/point.go
@@ -177,6 +177,8 @@ func (p *PointAffine) Neg(p1 *PointAffine) *PointAffine {
 
 // Add adds two points (x,y), (u,v) on a twisted Edwards curve with parameters a, d
 // modifies p
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 	initOnce.Do(initCurveParams)
@@ -209,6 +211,8 @@ func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 // Double doubles point (x,y) on a twisted Edwards curve with parameters a, d
 // modifies p
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
 func (p *PointAffine) Double(p1 *PointAffine) *PointAffine {
 
 	var A, B, C, D, E, F, G, H fr.Element
@@ -360,13 +364,15 @@ func (p *PointProj) FromAffine(p1 *PointAffine) *PointProj {
 	return p
 }
 
-// MixedAdd adds a point in projective to a point in affine coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
-func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
+// Add adds points in projective coordinates
+// Unified Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
+func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var B, C, D, E, F, G, H, I fr.Element
-	B.Square(&p1.Z)
+	var A, B, C, D, E, F, G, H, I fr.Element
+	A.Mul(&p1.Z, &p2.Z)
+	B.Square(&A)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -377,11 +383,12 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &p1.Z).
+		Mul(&p.X, &A).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	p.Y.Sub(&D, &C).
-		Mul(&p.Y, &p1.Z).
+	C.Neg(&C)
+	p.Y.Add(&D, &C).
+		Mul(&p.Y, &A).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -389,7 +396,8 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 }
 
 // Double adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/013.pdf
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
 func (p *PointProj) Double(p1 *PointProj) *PointProj {
 
 	var B, C, D, E, F, H, J fr.Element
@@ -411,14 +419,14 @@ func (p *PointProj) Double(p1 *PointProj) *PointProj {
 	return p
 }
 
-// Add adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
-func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
+// MixedAdd adds a point in projective to a point in affine coordinates
+// Mixed Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
+func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var A, B, C, D, E, F, G, H, I fr.Element
-	A.Mul(&p1.Z, &p2.Z)
-	B.Square(&A)
+	var B, C, D, E, F, G, H, I fr.Element
+	B.Square(&p1.Z)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -429,12 +437,11 @@ func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &A).
+		Mul(&p.X, &p1.Z).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	C.Neg(&C)
-	p.Y.Add(&D, &C).
-		Mul(&p.Y, &A).
+	p.Y.Sub(&D, &C).
+		Mul(&p.Y, &p1.Z).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -526,7 +533,8 @@ func (p *PointExtended) FromAffine(p1 *PointAffine) *PointExtended {
 }
 
 // Add adds points in extended coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	var A, B, C, D, E, F, G, H, tmp fr.Element
 	A.Mul(&p1.X, &p2.X)
@@ -552,37 +560,8 @@ func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedAdd adds a point in extended coordinates to a point in affine coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd-2
-func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
-	var A, B, C, D, E, F, G, H, tmp fr.Element
-
-	A.Mul(&p1.X, &p2.X)
-	B.Mul(&p1.Y, &p2.Y)
-	C.Mul(&p1.Z, &p2.X).
-		Mul(&C, &p2.Y)
-	D.Set(&p1.T)
-	E.Add(&D, &C)
-	tmp.Sub(&p1.X, &p1.Y)
-	F.Add(&p2.X, &p2.Y).
-		Mul(&F, &tmp).
-		Add(&F, &B).
-		Sub(&F, &A)
-	G.Set(&A)
-	mulByA(&G)
-	G.Add(&G, &B)
-	H.Sub(&D, &C)
-
-	p.X.Mul(&E, &F)
-	p.Y.Mul(&G, &H)
-	p.T.Mul(&E, &H)
-	p.Z.Mul(&F, &G)
-
-	return p
-}
-
 // Double adds points in extended coordinates
-// Dedicated doubling
+// (Dedicated) doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
 // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd
 func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 
@@ -610,32 +589,33 @@ func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedDouble adds points in extended coordinates
-// Dedicated mixed doubling
-// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-mdbl-2008-hwcd
-func (p *PointExtended) MixedDouble(p1 *PointExtended) *PointExtended {
-
-	var A, B, D, E, G, H, two fr.Element
-	two.SetUint64(2)
+// MixedAdd adds a point in extended coordinates to a point in affine coordinates
+// Unified Mixed Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd
+func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
+	initOnce.Do(initCurveParams)
+	var A, B, C, D, E, F, G, H, tmp fr.Element
 
-	A.Square(&p1.X)
-	B.Square(&p1.Y)
-	D.Set(&A)
-	mulByA(&D)
-	E.Add(&p1.X, &p1.Y).
-		Square(&E).
+	A.Mul(&p1.X, &p2.X)
+	B.Mul(&p1.Y, &p2.Y)
+	C.Mul(&p1.T, &p2.X).
+		Mul(&C, &p2.Y).
+		Mul(&C, &curveParams.D)
+	D.Set(&p1.Z)
+	tmp.Add(&p1.X, &p1.Y)
+	E.Add(&p2.X, &p2.Y).
+		Mul(&E, &tmp).
 		Sub(&E, &A).
 		Sub(&E, &B)
-	G.Add(&D, &B)
-	H.Sub(&D, &B)
-
-	p.X.Sub(&G, &two).
-		Mul(&p.X, &E)
+	F.Sub(&D, &C)
+	G.Add(&D, &C)
+	H.Set(&A)
+	mulByA(&H)
+	H.Sub(&B, &H)
+	p.X.Mul(&E, &F)
 	p.Y.Mul(&G, &H)
-	p.T.Mul(&H, &E)
-	p.Z.Square(&G).
-		Sub(&p.Z, &G).
-		Sub(&p.Z, &G)
+	p.T.Mul(&E, &H)
+	p.Z.Mul(&F, &G)
 
 	return p
 }
diff --git a/ecc/bn254/twistededwards/point.go b/ecc/bn254/twistededwards/point.go
index 423615494..1cbf3d1c9 100644
--- a/ecc/bn254/twistededwards/point.go
+++ b/ecc/bn254/twistededwards/point.go
@@ -177,6 +177,8 @@ func (p *PointAffine) Neg(p1 *PointAffine) *PointAffine {
 
 // Add adds two points (x,y), (u,v) on a twisted Edwards curve with parameters a, d
 // modifies p
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 	initOnce.Do(initCurveParams)
@@ -209,6 +211,8 @@ func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 // Double doubles point (x,y) on a twisted Edwards curve with parameters a, d
 // modifies p
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
 func (p *PointAffine) Double(p1 *PointAffine) *PointAffine {
 
 	var A, B, C, D, E, F, G, H fr.Element
@@ -360,13 +364,15 @@ func (p *PointProj) FromAffine(p1 *PointAffine) *PointProj {
 	return p
 }
 
-// MixedAdd adds a point in projective to a point in affine coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
-func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
+// Add adds points in projective coordinates
+// Unified Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
+func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var B, C, D, E, F, G, H, I fr.Element
-	B.Square(&p1.Z)
+	var A, B, C, D, E, F, G, H, I fr.Element
+	A.Mul(&p1.Z, &p2.Z)
+	B.Square(&A)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -377,11 +383,12 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &p1.Z).
+		Mul(&p.X, &A).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	p.Y.Sub(&D, &C).
-		Mul(&p.Y, &p1.Z).
+	C.Neg(&C)
+	p.Y.Add(&D, &C).
+		Mul(&p.Y, &A).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -389,7 +396,8 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 }
 
 // Double adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/013.pdf
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
 func (p *PointProj) Double(p1 *PointProj) *PointProj {
 
 	var B, C, D, E, F, H, J fr.Element
@@ -411,14 +419,14 @@ func (p *PointProj) Double(p1 *PointProj) *PointProj {
 	return p
 }
 
-// Add adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
-func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
+// MixedAdd adds a point in projective to a point in affine coordinates
+// Mixed Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
+func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var A, B, C, D, E, F, G, H, I fr.Element
-	A.Mul(&p1.Z, &p2.Z)
-	B.Square(&A)
+	var B, C, D, E, F, G, H, I fr.Element
+	B.Square(&p1.Z)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -429,12 +437,11 @@ func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &A).
+		Mul(&p.X, &p1.Z).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	C.Neg(&C)
-	p.Y.Add(&D, &C).
-		Mul(&p.Y, &A).
+	p.Y.Sub(&D, &C).
+		Mul(&p.Y, &p1.Z).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -526,7 +533,8 @@ func (p *PointExtended) FromAffine(p1 *PointAffine) *PointExtended {
 }
 
 // Add adds points in extended coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	var A, B, C, D, E, F, G, H, tmp fr.Element
 	A.Mul(&p1.X, &p2.X)
@@ -552,37 +560,8 @@ func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedAdd adds a point in extended coordinates to a point in affine coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd-2
-func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
-	var A, B, C, D, E, F, G, H, tmp fr.Element
-
-	A.Mul(&p1.X, &p2.X)
-	B.Mul(&p1.Y, &p2.Y)
-	C.Mul(&p1.Z, &p2.X).
-		Mul(&C, &p2.Y)
-	D.Set(&p1.T)
-	E.Add(&D, &C)
-	tmp.Sub(&p1.X, &p1.Y)
-	F.Add(&p2.X, &p2.Y).
-		Mul(&F, &tmp).
-		Add(&F, &B).
-		Sub(&F, &A)
-	G.Set(&A)
-	mulByA(&G)
-	G.Add(&G, &B)
-	H.Sub(&D, &C)
-
-	p.X.Mul(&E, &F)
-	p.Y.Mul(&G, &H)
-	p.T.Mul(&E, &H)
-	p.Z.Mul(&F, &G)
-
-	return p
-}
-
 // Double adds points in extended coordinates
-// Dedicated doubling
+// (Dedicated) doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
 // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd
 func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 
@@ -610,32 +589,33 @@ func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedDouble adds points in extended coordinates
-// Dedicated mixed doubling
-// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-mdbl-2008-hwcd
-func (p *PointExtended) MixedDouble(p1 *PointExtended) *PointExtended {
-
-	var A, B, D, E, G, H, two fr.Element
-	two.SetUint64(2)
+// MixedAdd adds a point in extended coordinates to a point in affine coordinates
+// Unified Mixed Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd
+func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
+	initOnce.Do(initCurveParams)
+	var A, B, C, D, E, F, G, H, tmp fr.Element
 
-	A.Square(&p1.X)
-	B.Square(&p1.Y)
-	D.Set(&A)
-	mulByA(&D)
-	E.Add(&p1.X, &p1.Y).
-		Square(&E).
+	A.Mul(&p1.X, &p2.X)
+	B.Mul(&p1.Y, &p2.Y)
+	C.Mul(&p1.T, &p2.X).
+		Mul(&C, &p2.Y).
+		Mul(&C, &curveParams.D)
+	D.Set(&p1.Z)
+	tmp.Add(&p1.X, &p1.Y)
+	E.Add(&p2.X, &p2.Y).
+		Mul(&E, &tmp).
 		Sub(&E, &A).
 		Sub(&E, &B)
-	G.Add(&D, &B)
-	H.Sub(&D, &B)
-
-	p.X.Sub(&G, &two).
-		Mul(&p.X, &E)
+	F.Sub(&D, &C)
+	G.Add(&D, &C)
+	H.Set(&A)
+	mulByA(&H)
+	H.Sub(&B, &H)
+	p.X.Mul(&E, &F)
 	p.Y.Mul(&G, &H)
-	p.T.Mul(&H, &E)
-	p.Z.Square(&G).
-		Sub(&p.Z, &G).
-		Sub(&p.Z, &G)
+	p.T.Mul(&E, &H)
+	p.Z.Mul(&F, &G)
 
 	return p
 }
diff --git a/ecc/bw6-633/twistededwards/point.go b/ecc/bw6-633/twistededwards/point.go
index 08dbf485b..b53746909 100644
--- a/ecc/bw6-633/twistededwards/point.go
+++ b/ecc/bw6-633/twistededwards/point.go
@@ -177,6 +177,8 @@ func (p *PointAffine) Neg(p1 *PointAffine) *PointAffine {
 
 // Add adds two points (x,y), (u,v) on a twisted Edwards curve with parameters a, d
 // modifies p
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 	initOnce.Do(initCurveParams)
@@ -209,6 +211,8 @@ func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 // Double doubles point (x,y) on a twisted Edwards curve with parameters a, d
 // modifies p
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
 func (p *PointAffine) Double(p1 *PointAffine) *PointAffine {
 
 	var A, B, C, D, E, F, G, H fr.Element
@@ -360,13 +364,15 @@ func (p *PointProj) FromAffine(p1 *PointAffine) *PointProj {
 	return p
 }
 
-// MixedAdd adds a point in projective to a point in affine coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
-func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
+// Add adds points in projective coordinates
+// Unified Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
+func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var B, C, D, E, F, G, H, I fr.Element
-	B.Square(&p1.Z)
+	var A, B, C, D, E, F, G, H, I fr.Element
+	A.Mul(&p1.Z, &p2.Z)
+	B.Square(&A)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -377,11 +383,12 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &p1.Z).
+		Mul(&p.X, &A).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	p.Y.Sub(&D, &C).
-		Mul(&p.Y, &p1.Z).
+	C.Neg(&C)
+	p.Y.Add(&D, &C).
+		Mul(&p.Y, &A).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -389,7 +396,8 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 }
 
 // Double adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/013.pdf
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
 func (p *PointProj) Double(p1 *PointProj) *PointProj {
 
 	var B, C, D, E, F, H, J fr.Element
@@ -411,14 +419,14 @@ func (p *PointProj) Double(p1 *PointProj) *PointProj {
 	return p
 }
 
-// Add adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
-func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
+// MixedAdd adds a point in projective to a point in affine coordinates
+// Mixed Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
+func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var A, B, C, D, E, F, G, H, I fr.Element
-	A.Mul(&p1.Z, &p2.Z)
-	B.Square(&A)
+	var B, C, D, E, F, G, H, I fr.Element
+	B.Square(&p1.Z)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -429,12 +437,11 @@ func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &A).
+		Mul(&p.X, &p1.Z).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	C.Neg(&C)
-	p.Y.Add(&D, &C).
-		Mul(&p.Y, &A).
+	p.Y.Sub(&D, &C).
+		Mul(&p.Y, &p1.Z).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -526,7 +533,8 @@ func (p *PointExtended) FromAffine(p1 *PointAffine) *PointExtended {
 }
 
 // Add adds points in extended coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	var A, B, C, D, E, F, G, H, tmp fr.Element
 	A.Mul(&p1.X, &p2.X)
@@ -552,37 +560,8 @@ func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedAdd adds a point in extended coordinates to a point in affine coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd-2
-func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
-	var A, B, C, D, E, F, G, H, tmp fr.Element
-
-	A.Mul(&p1.X, &p2.X)
-	B.Mul(&p1.Y, &p2.Y)
-	C.Mul(&p1.Z, &p2.X).
-		Mul(&C, &p2.Y)
-	D.Set(&p1.T)
-	E.Add(&D, &C)
-	tmp.Sub(&p1.X, &p1.Y)
-	F.Add(&p2.X, &p2.Y).
-		Mul(&F, &tmp).
-		Add(&F, &B).
-		Sub(&F, &A)
-	G.Set(&A)
-	mulByA(&G)
-	G.Add(&G, &B)
-	H.Sub(&D, &C)
-
-	p.X.Mul(&E, &F)
-	p.Y.Mul(&G, &H)
-	p.T.Mul(&E, &H)
-	p.Z.Mul(&F, &G)
-
-	return p
-}
-
 // Double adds points in extended coordinates
-// Dedicated doubling
+// (Dedicated) doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
 // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd
 func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 
@@ -610,32 +589,33 @@ func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedDouble adds points in extended coordinates
-// Dedicated mixed doubling
-// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-mdbl-2008-hwcd
-func (p *PointExtended) MixedDouble(p1 *PointExtended) *PointExtended {
-
-	var A, B, D, E, G, H, two fr.Element
-	two.SetUint64(2)
+// MixedAdd adds a point in extended coordinates to a point in affine coordinates
+// Unified Mixed Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd
+func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
+	initOnce.Do(initCurveParams)
+	var A, B, C, D, E, F, G, H, tmp fr.Element
 
-	A.Square(&p1.X)
-	B.Square(&p1.Y)
-	D.Set(&A)
-	mulByA(&D)
-	E.Add(&p1.X, &p1.Y).
-		Square(&E).
+	A.Mul(&p1.X, &p2.X)
+	B.Mul(&p1.Y, &p2.Y)
+	C.Mul(&p1.T, &p2.X).
+		Mul(&C, &p2.Y).
+		Mul(&C, &curveParams.D)
+	D.Set(&p1.Z)
+	tmp.Add(&p1.X, &p1.Y)
+	E.Add(&p2.X, &p2.Y).
+		Mul(&E, &tmp).
 		Sub(&E, &A).
 		Sub(&E, &B)
-	G.Add(&D, &B)
-	H.Sub(&D, &B)
-
-	p.X.Sub(&G, &two).
-		Mul(&p.X, &E)
+	F.Sub(&D, &C)
+	G.Add(&D, &C)
+	H.Set(&A)
+	mulByA(&H)
+	H.Sub(&B, &H)
+	p.X.Mul(&E, &F)
 	p.Y.Mul(&G, &H)
-	p.T.Mul(&H, &E)
-	p.Z.Square(&G).
-		Sub(&p.Z, &G).
-		Sub(&p.Z, &G)
+	p.T.Mul(&E, &H)
+	p.Z.Mul(&F, &G)
 
 	return p
 }
diff --git a/ecc/bw6-761/twistededwards/point.go b/ecc/bw6-761/twistededwards/point.go
index e49d0f7f6..9f9483ae7 100644
--- a/ecc/bw6-761/twistededwards/point.go
+++ b/ecc/bw6-761/twistededwards/point.go
@@ -177,6 +177,8 @@ func (p *PointAffine) Neg(p1 *PointAffine) *PointAffine {
 
 // Add adds two points (x,y), (u,v) on a twisted Edwards curve with parameters a, d
 // modifies p
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 	initOnce.Do(initCurveParams)
@@ -209,6 +211,8 @@ func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 // Double doubles point (x,y) on a twisted Edwards curve with parameters a, d
 // modifies p
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
 func (p *PointAffine) Double(p1 *PointAffine) *PointAffine {
 
 	var A, B, C, D, E, F, G, H fr.Element
@@ -360,13 +364,15 @@ func (p *PointProj) FromAffine(p1 *PointAffine) *PointProj {
 	return p
 }
 
-// MixedAdd adds a point in projective to a point in affine coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
-func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
+// Add adds points in projective coordinates
+// Unified Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
+func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var B, C, D, E, F, G, H, I fr.Element
-	B.Square(&p1.Z)
+	var A, B, C, D, E, F, G, H, I fr.Element
+	A.Mul(&p1.Z, &p2.Z)
+	B.Square(&A)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -377,11 +383,12 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &p1.Z).
+		Mul(&p.X, &A).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	p.Y.Sub(&D, &C).
-		Mul(&p.Y, &p1.Z).
+	C.Neg(&C)
+	p.Y.Add(&D, &C).
+		Mul(&p.Y, &A).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -389,7 +396,8 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 }
 
 // Double adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/013.pdf
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
 func (p *PointProj) Double(p1 *PointProj) *PointProj {
 
 	var B, C, D, E, F, H, J fr.Element
@@ -411,14 +419,14 @@ func (p *PointProj) Double(p1 *PointProj) *PointProj {
 	return p
 }
 
-// Add adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
-func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
+// MixedAdd adds a point in projective to a point in affine coordinates
+// Mixed Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
+func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var A, B, C, D, E, F, G, H, I fr.Element
-	A.Mul(&p1.Z, &p2.Z)
-	B.Square(&A)
+	var B, C, D, E, F, G, H, I fr.Element
+	B.Square(&p1.Z)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -429,12 +437,11 @@ func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &A).
+		Mul(&p.X, &p1.Z).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	C.Neg(&C)
-	p.Y.Add(&D, &C).
-		Mul(&p.Y, &A).
+	p.Y.Sub(&D, &C).
+		Mul(&p.Y, &p1.Z).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -526,7 +533,8 @@ func (p *PointExtended) FromAffine(p1 *PointAffine) *PointExtended {
 }
 
 // Add adds points in extended coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	var A, B, C, D, E, F, G, H, tmp fr.Element
 	A.Mul(&p1.X, &p2.X)
@@ -552,37 +560,8 @@ func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedAdd adds a point in extended coordinates to a point in affine coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd-2
-func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
-	var A, B, C, D, E, F, G, H, tmp fr.Element
-
-	A.Mul(&p1.X, &p2.X)
-	B.Mul(&p1.Y, &p2.Y)
-	C.Mul(&p1.Z, &p2.X).
-		Mul(&C, &p2.Y)
-	D.Set(&p1.T)
-	E.Add(&D, &C)
-	tmp.Sub(&p1.X, &p1.Y)
-	F.Add(&p2.X, &p2.Y).
-		Mul(&F, &tmp).
-		Add(&F, &B).
-		Sub(&F, &A)
-	G.Set(&A)
-	mulByA(&G)
-	G.Add(&G, &B)
-	H.Sub(&D, &C)
-
-	p.X.Mul(&E, &F)
-	p.Y.Mul(&G, &H)
-	p.T.Mul(&E, &H)
-	p.Z.Mul(&F, &G)
-
-	return p
-}
-
 // Double adds points in extended coordinates
-// Dedicated doubling
+// (Dedicated) doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
 // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd
 func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 
@@ -610,32 +589,33 @@ func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedDouble adds points in extended coordinates
-// Dedicated mixed doubling
-// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-mdbl-2008-hwcd
-func (p *PointExtended) MixedDouble(p1 *PointExtended) *PointExtended {
-
-	var A, B, D, E, G, H, two fr.Element
-	two.SetUint64(2)
+// MixedAdd adds a point in extended coordinates to a point in affine coordinates
+// Unified Mixed Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd
+func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
+	initOnce.Do(initCurveParams)
+	var A, B, C, D, E, F, G, H, tmp fr.Element
 
-	A.Square(&p1.X)
-	B.Square(&p1.Y)
-	D.Set(&A)
-	mulByA(&D)
-	E.Add(&p1.X, &p1.Y).
-		Square(&E).
+	A.Mul(&p1.X, &p2.X)
+	B.Mul(&p1.Y, &p2.Y)
+	C.Mul(&p1.T, &p2.X).
+		Mul(&C, &p2.Y).
+		Mul(&C, &curveParams.D)
+	D.Set(&p1.Z)
+	tmp.Add(&p1.X, &p1.Y)
+	E.Add(&p2.X, &p2.Y).
+		Mul(&E, &tmp).
 		Sub(&E, &A).
 		Sub(&E, &B)
-	G.Add(&D, &B)
-	H.Sub(&D, &B)
-
-	p.X.Sub(&G, &two).
-		Mul(&p.X, &E)
+	F.Sub(&D, &C)
+	G.Add(&D, &C)
+	H.Set(&A)
+	mulByA(&H)
+	H.Sub(&B, &H)
+	p.X.Mul(&E, &F)
 	p.Y.Mul(&G, &H)
-	p.T.Mul(&H, &E)
-	p.Z.Square(&G).
-		Sub(&p.Z, &G).
-		Sub(&p.Z, &G)
+	p.T.Mul(&E, &H)
+	p.Z.Mul(&F, &G)
 
 	return p
 }
diff --git a/internal/generator/edwards/template/point.go.tmpl b/internal/generator/edwards/template/point.go.tmpl
index 93a1fb175..17e6af9d5 100644
--- a/internal/generator/edwards/template/point.go.tmpl
+++ b/internal/generator/edwards/template/point.go.tmpl
@@ -232,6 +232,8 @@ func (p *PointAffine) Neg(p1 *PointAffine) *PointAffine {
 
 // Add adds two points (x,y), (u,v) on a twisted Edwards curve with parameters a, d
 // modifies p
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 	initOnce.Do(initCurveParams)
@@ -265,6 +267,8 @@ func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
 
 // Double doubles point (x,y) on a twisted Edwards curve with parameters a, d
 // modifies p
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
 func (p *PointAffine) Double(p1 *PointAffine) *PointAffine {
 
 	var A, B, C, D, E, F, G, H fr.Element
@@ -416,13 +420,15 @@ func (p *PointProj) FromAffine(p1 *PointAffine) *PointProj {
 	return p
 }
 
-// MixedAdd adds a point in projective to a point in affine coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
-func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
+// Add adds points in projective coordinates
+// Unified Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
+func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var B, C, D, E, F, G, H, I fr.Element
-	B.Square(&p1.Z)
+	var A, B, C, D, E, F, G, H, I fr.Element
+	A.Mul(&p1.Z, &p2.Z)
+	B.Square(&A)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -433,11 +439,12 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &p1.Z).
+		Mul(&p.X, &A).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	p.Y.Sub(&D, &C).
-		Mul(&p.Y, &p1.Z).
+	C.Neg(&C)
+	p.Y.Add(&D, &C).
+		Mul(&p.Y, &A).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -445,7 +452,8 @@ func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 }
 
 // Double adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
+// (Dedicated) Doubling from https://eprint.iacr.org/2008/013.pdf
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
 func (p *PointProj) Double(p1 *PointProj) *PointProj {
 
 	var B, C, D, E, F, H, J fr.Element
@@ -467,14 +475,14 @@ func (p *PointProj) Double(p1 *PointProj) *PointProj {
 	return p
 }
 
-// Add adds points in projective coordinates
-// cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
-func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
+// MixedAdd adds a point in projective to a point in affine coordinates
+// Mixed Addition from http://eprint.iacr.org/2008/013.pdf (Sec. 6)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
+func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
 	initOnce.Do(initCurveParams)
 
-	var A, B, C, D, E, F, G, H, I fr.Element
-	A.Mul(&p1.Z, &p2.Z)
-	B.Square(&A)
+	var B, C, D, E, F, G, H, I fr.Element
+	B.Square(&p1.Z)
 	C.Mul(&p1.X, &p2.X)
 	D.Mul(&p1.Y, &p2.Y)
 	E.Mul(&curveParams.D, &C).Mul(&E, &D)
@@ -485,12 +493,11 @@ func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
 	p.X.Mul(&H, &I).
 		Sub(&p.X, &C).
 		Sub(&p.X, &D).
-		Mul(&p.X, &A).
+		Mul(&p.X, &p1.Z).
 		Mul(&p.X, &F)
 	mulByA(&C)
-	C.Neg(&C)
-	p.Y.Add(&D, &C).
-		Mul(&p.Y, &A).
+	p.Y.Sub(&D, &C).
+		Mul(&p.Y, &p1.Z).
 		Mul(&p.Y, &G)
 	p.Z.Mul(&F, &G)
 
@@ -586,7 +593,8 @@ func (p *PointExtended) FromAffine(p1 *PointAffine) *PointExtended {
 }
 
 // Add adds points in extended coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
+// Unified Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
 func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	var A, B, C, D, E, F, G, H, tmp fr.Element
 	A.Mul(&p1.X, &p2.X)
@@ -612,37 +620,8 @@ func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedAdd adds a point in extended coordinates to a point in affine coordinates
-// See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd-2
-func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
-	var A, B, C, D, E, F, G, H, tmp fr.Element
-
-	A.Mul(&p1.X, &p2.X)
-	B.Mul(&p1.Y, &p2.Y)
-	C.Mul(&p1.Z, &p2.X).
-		Mul(&C, &p2.Y)
-	D.Set(&p1.T)
-	E.Add(&D, &C)
-	tmp.Sub(&p1.X, &p1.Y)
-	F.Add(&p2.X, &p2.Y).
-		Mul(&F, &tmp).
-		Add(&F, &B).
-		Sub(&F, &A)
-	G.Set(&A)
-	mulByA(&G)
-	G.Add(&G, &B)
-	H.Sub(&D, &C)
-
-	p.X.Mul(&E, &F)
-	p.Y.Mul(&G, &H)
-	p.T.Mul(&E, &H)
-	p.Z.Mul(&F, &G)
-
-	return p
-}
-
 // Double adds points in extended coordinates
-// Dedicated doubling
+// (Dedicated) doubling from https://eprint.iacr.org/2008/522.pdf (Sec. 3.3)
 // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd
 func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 
@@ -670,32 +649,33 @@ func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
 	return p
 }
 
-// MixedDouble adds points in extended coordinates
-// Dedicated mixed doubling
-// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-mdbl-2008-hwcd
-func (p *PointExtended) MixedDouble(p1 *PointExtended) *PointExtended {
-
-	var A, B, D, E, G, H, two fr.Element
-	two.SetUint64(2)
+// MixedAdd adds a point in extended coordinates to a point in affine coordinates
+// Unified Mixed Addition from https://eprint.iacr.org/2008/522.pdf (Sec. 3.1)
+// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd
+func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
+	initOnce.Do(initCurveParams)
+	var A, B, C, D, E, F, G, H, tmp fr.Element
 
-	A.Square(&p1.X)
-	B.Square(&p1.Y)
-	D.Set(&A)
-	mulByA(&D)
-	E.Add(&p1.X, &p1.Y).
-		Square(&E).
+	A.Mul(&p1.X, &p2.X)
+	B.Mul(&p1.Y, &p2.Y)
+	C.Mul(&p1.T, &p2.X).
+		Mul(&C, &p2.Y).
+		Mul(&C, &curveParams.D)
+	D.Set(&p1.Z)
+	tmp.Add(&p1.X, &p1.Y)
+	E.Add(&p2.X, &p2.Y).
+		Mul(&E, &tmp).
 		Sub(&E, &A).
 		Sub(&E, &B)
-	G.Add(&D, &B)
-	H.Sub(&D, &B)
-
-	p.X.Sub(&G, &two).
-		Mul(&p.X, &E)
+	F.Sub(&D, &C)
+	G.Add(&D, &C)
+	H.Set(&A)
+	mulByA(&H)
+	H.Sub(&B, &H)
+	p.X.Mul(&E, &F)
 	p.Y.Mul(&G, &H)
-	p.T.Mul(&H, &E)
-	p.Z.Square(&G).
-		Sub(&p.Z, &G).
-		Sub(&p.Z, &G)
+	p.T.Mul(&E, &H)
+	p.Z.Mul(&F, &G)
 
 	return p
 }



Test patch:
diff --git a/ecc/bls12-377/twistededwards/point_test.go b/ecc/bls12-377/twistededwards/point_test.go
index 30b0e8bbf..a0f09098e 100644
--- a/ecc/bls12-377/twistededwards/point_test.go
+++ b/ecc/bls12-377/twistededwards/point_test.go
@@ -430,6 +430,93 @@ func TestOps(t *testing.T) {
 		genS1,
 	))
 
+	properties.Property("(affine) [random](0,1) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.ScalarMultiplication(&p1, &s1)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [0](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			zero := big.NewInt(0)
+			p1.ScalarMultiplication(&p1, zero)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [1](x,y) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			one := big.NewInt(1)
+			p2.ScalarMultiplication(&p1, one)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](x,y) == Double(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			two := big.NewInt(2)
+			p2.ScalarMultiplication(&p1, two)
+			p1.Double(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [-1](x,y) == Neg(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			mone := big.NewInt(-1)
+			p2.ScalarMultiplication(&p1, mone)
+			p1.Neg(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](0,1) == (0,1)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.Double(&p1)
+
+			return p1.IsZero()
+		},
+	))
+
+	properties.Property("(affine) [order](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			p1.ScalarMultiplication(&p1, &curveParams.Order)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
 	// projective
 	properties.Property("(projective) 0+0=2*0=0", prop.ForAll(
 		func(s1 big.Int) bool {
@@ -620,6 +707,60 @@ func TestOps(t *testing.T) {
 	))
 
 	// mixed affine+projective
+	properties.Property("(affine/extended) (0,1)+(x,y,z,t) == (x,y,z,t)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.FromAffine(&params.Base)
+			p2.ScalarMultiplication(&p2, &s1)
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var p2Aff, resAff PointAffine
+			p2Aff.FromExtended(&p2)
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p2Aff)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (x,y)+(0,1,1,0) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p1)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (0,1)+(0,1,1,0) == (0,1,1,0)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.IsZero()
+		},
+	))
+
 	properties.Property("(mixed affine+proj) P+(-P)=O", prop.ForAll(
 		func(s big.Int) bool {
 
diff --git a/ecc/bls12-381/bandersnatch/point_test.go b/ecc/bls12-381/bandersnatch/point_test.go
index 5a957e21f..b55e8e9c2 100644
--- a/ecc/bls12-381/bandersnatch/point_test.go
+++ b/ecc/bls12-381/bandersnatch/point_test.go
@@ -430,6 +430,93 @@ func TestOps(t *testing.T) {
 		genS1,
 	))
 
+	properties.Property("(affine) [random](0,1) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.ScalarMultiplication(&p1, &s1)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [0](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			zero := big.NewInt(0)
+			p1.ScalarMultiplication(&p1, zero)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [1](x,y) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			one := big.NewInt(1)
+			p2.ScalarMultiplication(&p1, one)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](x,y) == Double(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			two := big.NewInt(2)
+			p2.ScalarMultiplication(&p1, two)
+			p1.Double(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [-1](x,y) == Neg(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			mone := big.NewInt(-1)
+			p2.ScalarMultiplication(&p1, mone)
+			p1.Neg(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](0,1) == (0,1)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.Double(&p1)
+
+			return p1.IsZero()
+		},
+	))
+
+	properties.Property("(affine) [order](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			p1.ScalarMultiplication(&p1, &curveParams.Order)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
 	// projective
 	properties.Property("(projective) 0+0=2*0=0", prop.ForAll(
 		func(s1 big.Int) bool {
@@ -652,6 +739,60 @@ func TestOps(t *testing.T) {
 	))
 
 	// mixed affine+projective
+	properties.Property("(affine/extended) (0,1)+(x,y,z,t) == (x,y,z,t)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.FromAffine(&params.Base)
+			p2.ScalarMultiplication(&p2, &s1)
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var p2Aff, resAff PointAffine
+			p2Aff.FromExtended(&p2)
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p2Aff)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (x,y)+(0,1,1,0) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p1)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (0,1)+(0,1,1,0) == (0,1,1,0)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.IsZero()
+		},
+	))
+
 	properties.Property("(mixed affine+proj) P+(-P)=O", prop.ForAll(
 		func(s big.Int) bool {
 
diff --git a/ecc/bls12-381/twistededwards/point_test.go b/ecc/bls12-381/twistededwards/point_test.go
index 48fd24908..7f9992169 100644
--- a/ecc/bls12-381/twistededwards/point_test.go
+++ b/ecc/bls12-381/twistededwards/point_test.go
@@ -430,6 +430,93 @@ func TestOps(t *testing.T) {
 		genS1,
 	))
 
+	properties.Property("(affine) [random](0,1) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.ScalarMultiplication(&p1, &s1)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [0](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			zero := big.NewInt(0)
+			p1.ScalarMultiplication(&p1, zero)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [1](x,y) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			one := big.NewInt(1)
+			p2.ScalarMultiplication(&p1, one)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](x,y) == Double(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			two := big.NewInt(2)
+			p2.ScalarMultiplication(&p1, two)
+			p1.Double(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [-1](x,y) == Neg(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			mone := big.NewInt(-1)
+			p2.ScalarMultiplication(&p1, mone)
+			p1.Neg(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](0,1) == (0,1)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.Double(&p1)
+
+			return p1.IsZero()
+		},
+	))
+
+	properties.Property("(affine) [order](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			p1.ScalarMultiplication(&p1, &curveParams.Order)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
 	// projective
 	properties.Property("(projective) 0+0=2*0=0", prop.ForAll(
 		func(s1 big.Int) bool {
@@ -620,6 +707,60 @@ func TestOps(t *testing.T) {
 	))
 
 	// mixed affine+projective
+	properties.Property("(affine/extended) (0,1)+(x,y,z,t) == (x,y,z,t)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.FromAffine(&params.Base)
+			p2.ScalarMultiplication(&p2, &s1)
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var p2Aff, resAff PointAffine
+			p2Aff.FromExtended(&p2)
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p2Aff)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (x,y)+(0,1,1,0) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p1)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (0,1)+(0,1,1,0) == (0,1,1,0)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.IsZero()
+		},
+	))
+
 	properties.Property("(mixed affine+proj) P+(-P)=O", prop.ForAll(
 		func(s big.Int) bool {
 
diff --git a/ecc/bls24-315/twistededwards/point_test.go b/ecc/bls24-315/twistededwards/point_test.go
index 8b04ea716..027bb18d4 100644
--- a/ecc/bls24-315/twistededwards/point_test.go
+++ b/ecc/bls24-315/twistededwards/point_test.go
@@ -430,6 +430,93 @@ func TestOps(t *testing.T) {
 		genS1,
 	))
 
+	properties.Property("(affine) [random](0,1) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.ScalarMultiplication(&p1, &s1)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [0](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			zero := big.NewInt(0)
+			p1.ScalarMultiplication(&p1, zero)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [1](x,y) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			one := big.NewInt(1)
+			p2.ScalarMultiplication(&p1, one)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](x,y) == Double(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			two := big.NewInt(2)
+			p2.ScalarMultiplication(&p1, two)
+			p1.Double(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [-1](x,y) == Neg(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			mone := big.NewInt(-1)
+			p2.ScalarMultiplication(&p1, mone)
+			p1.Neg(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](0,1) == (0,1)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.Double(&p1)
+
+			return p1.IsZero()
+		},
+	))
+
+	properties.Property("(affine) [order](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			p1.ScalarMultiplication(&p1, &curveParams.Order)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
 	// projective
 	properties.Property("(projective) 0+0=2*0=0", prop.ForAll(
 		func(s1 big.Int) bool {
@@ -620,6 +707,60 @@ func TestOps(t *testing.T) {
 	))
 
 	// mixed affine+projective
+	properties.Property("(affine/extended) (0,1)+(x,y,z,t) == (x,y,z,t)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.FromAffine(&params.Base)
+			p2.ScalarMultiplication(&p2, &s1)
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var p2Aff, resAff PointAffine
+			p2Aff.FromExtended(&p2)
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p2Aff)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (x,y)+(0,1,1,0) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p1)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (0,1)+(0,1,1,0) == (0,1,1,0)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.IsZero()
+		},
+	))
+
 	properties.Property("(mixed affine+proj) P+(-P)=O", prop.ForAll(
 		func(s big.Int) bool {
 
diff --git a/ecc/bls24-317/twistededwards/point_test.go b/ecc/bls24-317/twistededwards/point_test.go
index 37e474d07..1ea403716 100644
--- a/ecc/bls24-317/twistededwards/point_test.go
+++ b/ecc/bls24-317/twistededwards/point_test.go
@@ -430,6 +430,93 @@ func TestOps(t *testing.T) {
 		genS1,
 	))
 
+	properties.Property("(affine) [random](0,1) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.ScalarMultiplication(&p1, &s1)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [0](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			zero := big.NewInt(0)
+			p1.ScalarMultiplication(&p1, zero)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [1](x,y) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			one := big.NewInt(1)
+			p2.ScalarMultiplication(&p1, one)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](x,y) == Double(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			two := big.NewInt(2)
+			p2.ScalarMultiplication(&p1, two)
+			p1.Double(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [-1](x,y) == Neg(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			mone := big.NewInt(-1)
+			p2.ScalarMultiplication(&p1, mone)
+			p1.Neg(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](0,1) == (0,1)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.Double(&p1)
+
+			return p1.IsZero()
+		},
+	))
+
+	properties.Property("(affine) [order](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			p1.ScalarMultiplication(&p1, &curveParams.Order)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
 	// projective
 	properties.Property("(projective) 0+0=2*0=0", prop.ForAll(
 		func(s1 big.Int) bool {
@@ -620,6 +707,60 @@ func TestOps(t *testing.T) {
 	))
 
 	// mixed affine+projective
+	properties.Property("(affine/extended) (0,1)+(x,y,z,t) == (x,y,z,t)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.FromAffine(&params.Base)
+			p2.ScalarMultiplication(&p2, &s1)
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var p2Aff, resAff PointAffine
+			p2Aff.FromExtended(&p2)
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p2Aff)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (x,y)+(0,1,1,0) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p1)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (0,1)+(0,1,1,0) == (0,1,1,0)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.IsZero()
+		},
+	))
+
 	properties.Property("(mixed affine+proj) P+(-P)=O", prop.ForAll(
 		func(s big.Int) bool {
 
diff --git a/ecc/bn254/twistededwards/point_test.go b/ecc/bn254/twistededwards/point_test.go
index 8f4165800..1093eb3c6 100644
--- a/ecc/bn254/twistededwards/point_test.go
+++ b/ecc/bn254/twistededwards/point_test.go
@@ -430,6 +430,93 @@ func TestOps(t *testing.T) {
 		genS1,
 	))
 
+	properties.Property("(affine) [random](0,1) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.ScalarMultiplication(&p1, &s1)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [0](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			zero := big.NewInt(0)
+			p1.ScalarMultiplication(&p1, zero)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [1](x,y) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			one := big.NewInt(1)
+			p2.ScalarMultiplication(&p1, one)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](x,y) == Double(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			two := big.NewInt(2)
+			p2.ScalarMultiplication(&p1, two)
+			p1.Double(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [-1](x,y) == Neg(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			mone := big.NewInt(-1)
+			p2.ScalarMultiplication(&p1, mone)
+			p1.Neg(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](0,1) == (0,1)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.Double(&p1)
+
+			return p1.IsZero()
+		},
+	))
+
+	properties.Property("(affine) [order](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			p1.ScalarMultiplication(&p1, &curveParams.Order)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
 	// projective
 	properties.Property("(projective) 0+0=2*0=0", prop.ForAll(
 		func(s1 big.Int) bool {
@@ -620,6 +707,60 @@ func TestOps(t *testing.T) {
 	))
 
 	// mixed affine+projective
+	properties.Property("(affine/extended) (0,1)+(x,y,z,t) == (x,y,z,t)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.FromAffine(&params.Base)
+			p2.ScalarMultiplication(&p2, &s1)
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var p2Aff, resAff PointAffine
+			p2Aff.FromExtended(&p2)
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p2Aff)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (x,y)+(0,1,1,0) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p1)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (0,1)+(0,1,1,0) == (0,1,1,0)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.IsZero()
+		},
+	))
+
 	properties.Property("(mixed affine+proj) P+(-P)=O", prop.ForAll(
 		func(s big.Int) bool {
 
diff --git a/ecc/bw6-633/twistededwards/point_test.go b/ecc/bw6-633/twistededwards/point_test.go
index 7b19201c2..a12b04151 100644
--- a/ecc/bw6-633/twistededwards/point_test.go
+++ b/ecc/bw6-633/twistededwards/point_test.go
@@ -430,6 +430,93 @@ func TestOps(t *testing.T) {
 		genS1,
 	))
 
+	properties.Property("(affine) [random](0,1) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.ScalarMultiplication(&p1, &s1)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [0](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			zero := big.NewInt(0)
+			p1.ScalarMultiplication(&p1, zero)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [1](x,y) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			one := big.NewInt(1)
+			p2.ScalarMultiplication(&p1, one)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](x,y) == Double(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			two := big.NewInt(2)
+			p2.ScalarMultiplication(&p1, two)
+			p1.Double(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [-1](x,y) == Neg(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			mone := big.NewInt(-1)
+			p2.ScalarMultiplication(&p1, mone)
+			p1.Neg(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](0,1) == (0,1)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.Double(&p1)
+
+			return p1.IsZero()
+		},
+	))
+
+	properties.Property("(affine) [order](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			p1.ScalarMultiplication(&p1, &curveParams.Order)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
 	// projective
 	properties.Property("(projective) 0+0=2*0=0", prop.ForAll(
 		func(s1 big.Int) bool {
@@ -620,6 +707,60 @@ func TestOps(t *testing.T) {
 	))
 
 	// mixed affine+projective
+	properties.Property("(affine/extended) (0,1)+(x,y,z,t) == (x,y,z,t)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.FromAffine(&params.Base)
+			p2.ScalarMultiplication(&p2, &s1)
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var p2Aff, resAff PointAffine
+			p2Aff.FromExtended(&p2)
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p2Aff)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (x,y)+(0,1,1,0) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p1)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (0,1)+(0,1,1,0) == (0,1,1,0)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.IsZero()
+		},
+	))
+
 	properties.Property("(mixed affine+proj) P+(-P)=O", prop.ForAll(
 		func(s big.Int) bool {
 
diff --git a/ecc/bw6-761/twistededwards/point_test.go b/ecc/bw6-761/twistededwards/point_test.go
index 08cbc9372..1a06e7651 100644
--- a/ecc/bw6-761/twistededwards/point_test.go
+++ b/ecc/bw6-761/twistededwards/point_test.go
@@ -430,6 +430,93 @@ func TestOps(t *testing.T) {
 		genS1,
 	))
 
+	properties.Property("(affine) [random](0,1) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.ScalarMultiplication(&p1, &s1)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [0](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			zero := big.NewInt(0)
+			p1.ScalarMultiplication(&p1, zero)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [1](x,y) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			one := big.NewInt(1)
+			p2.ScalarMultiplication(&p1, one)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](x,y) == Double(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			two := big.NewInt(2)
+			p2.ScalarMultiplication(&p1, two)
+			p1.Double(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [-1](x,y) == Neg(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			mone := big.NewInt(-1)
+			p2.ScalarMultiplication(&p1, mone)
+			p1.Neg(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](0,1) == (0,1)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.Double(&p1)
+
+			return p1.IsZero()
+		},
+	))
+
+	properties.Property("(affine) [order](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			p1.ScalarMultiplication(&p1, &curveParams.Order)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
 	// projective
 	properties.Property("(projective) 0+0=2*0=0", prop.ForAll(
 		func(s1 big.Int) bool {
@@ -620,6 +707,60 @@ func TestOps(t *testing.T) {
 	))
 
 	// mixed affine+projective
+	properties.Property("(affine/extended) (0,1)+(x,y,z,t) == (x,y,z,t)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.FromAffine(&params.Base)
+			p2.ScalarMultiplication(&p2, &s1)
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var p2Aff, resAff PointAffine
+			p2Aff.FromExtended(&p2)
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p2Aff)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (x,y)+(0,1,1,0) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p1)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (0,1)+(0,1,1,0) == (0,1,1,0)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.IsZero()
+		},
+	))
+
 	properties.Property("(mixed affine+proj) P+(-P)=O", prop.ForAll(
 		func(s big.Int) bool {
 
diff --git a/internal/generator/edwards/template/tests/point.go.tmpl b/internal/generator/edwards/template/tests/point.go.tmpl
index 2f54af129..ca35079e7 100644
--- a/internal/generator/edwards/template/tests/point.go.tmpl
+++ b/internal/generator/edwards/template/tests/point.go.tmpl
@@ -423,6 +423,94 @@ func TestOps(t *testing.T) {
 		genS1,
 	))
 
+	properties.Property("(affine) [random](0,1) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.ScalarMultiplication(&p1, &s1)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [0](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			zero := big.NewInt(0)
+			p1.ScalarMultiplication(&p1, zero)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [1](x,y) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			one := big.NewInt(1)
+			p2.ScalarMultiplication(&p1, one)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](x,y) == Double(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			two := big.NewInt(2)
+			p2.ScalarMultiplication(&p1, two)
+			p1.Double(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [-1](x,y) == Neg(x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1, p2 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			mone := big.NewInt(-1)
+			p2.ScalarMultiplication(&p1, mone)
+			p1.Neg(&p1)
+
+			return p1.Equal(&p2)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine) [2](0,1) == (0,1)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			p1.Double(&p1)
+
+			return p1.IsZero()
+		},
+	))
+
+	properties.Property("(affine) [order](x,y) == (0,1)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			p1.ScalarMultiplication(&p1, &curveParams.Order)
+
+			return p1.IsZero()
+		},
+		genS1,
+	))
+
+
 	// projective
 	properties.Property("(projective) 0+0=2*0=0", prop.ForAll(
 		func(s1 big.Int) bool {
@@ -653,6 +741,60 @@ func TestOps(t *testing.T) {
 	))
 
 	// mixed affine+projective
+	properties.Property("(affine/extended) (0,1)+(x,y,z,t) == (x,y,z,t)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.FromAffine(&params.Base)
+			p2.ScalarMultiplication(&p2, &s1)
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var p2Aff, resAff PointAffine
+			p2Aff.FromExtended(&p2)
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p2Aff)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (x,y)+(0,1,1,0) == (x,y)", prop.ForAll(
+		func(s1 big.Int) bool {
+			params := GetEdwardsCurve()
+			var p1 PointAffine
+			p1.ScalarMultiplication(&params.Base, &s1)
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.Equal(&p1)
+		},
+		genS1,
+	))
+
+	properties.Property("(affine/extended) (0,1)+(0,1,1,0) == (0,1,1,0)", prop.ForAll(
+		func() bool {
+			var p1 PointAffine
+			p1.setInfinity()
+			var p2 PointExtended
+			p2.setInfinity()
+			var res PointExtended
+			res.MixedAdd(&p2, &p1)
+
+			var resAff PointAffine
+			resAff.FromExtended(&res)
+
+			return resAff.IsZero()
+		},
+	))
+
 	properties.Property("(mixed affine+proj) P+(-P)=O", prop.ForAll(
 		func(s big.Int) bool {