lambdaclass/zksync_era_precompiles

Reuse computation for detecting point doubling case

ilitteri opened this issue · 0 comments

Context: P256VERIFY.yul#L463

Description:

In projectiveAdd() the case P + P = 2P must be handled separately. To detect if P == Q the computations from the generic case P1 + P2 = P3:

$$ t = y_p * z_q - y_q * z_p,\ u = x_p * z_q - x_q * z_p $$

The condition for $P = Q$ is $t = 0 \wedge u = 0$ i.e. iszero(or(t, u)).

Recommendation:

Compute t and u up front and detect P + P = 2P case by iszero(or(t, u)).

diff --git a/precompiles/P256VERIFY.yul b/precompiles/P256VERIFY.yul
index 688d25e..1d08c51 100644
--- a/precompiles/P256VERIFY.yul
+++ b/precompiles/P256VERIFY.yul
@@ -460,21 +460,22 @@ object "P256VERIFY" {
                     zr := zp
                     leave
                 }
-                if eq(montgomeryMul(xp, zq, P(), P_PRIME()), montgomeryMul(xq, zp, P(), P_PRIME())) {
-                    if eq(montgomeryMul(yp, zq, P(), P_PRIME()), montgomeryMul(yq, zp, P(), P_PRIME())) {
-                        // P + P = 2P
-                        xr, yr, zr := projectiveDouble(xp, yp, zp)
-                        leave
-                    }
-                }
 
-                // P1 + P2 = P3
                 let t0 := montgomeryMul(yp, zq, P(), P_PRIME())
                 let t1 := montgomeryMul(yq, zp, P(), P_PRIME())
                 let t := montgomerySub(t0, t1, P())
                 let u0 := montgomeryMul(xp, zq, P(), P_PRIME())
                 let u1 := montgomeryMul(xq, zp, P(), P_PRIME())
                 let u := montgomerySub(u0, u1, P())
+
+                // t = (yp*zq - yq*zp); u = (xp*zq - xq*zp)
+                if iszero(or(t, u)) {
+                    // P + P = 2P
+                    xr, yr, zr := projectiveDouble(xp, yp, zp)
+                    leave
+                }
+
+                // P1 + P2 = P3
                 let u2 := montgomeryMul(u, u, P(), P_PRIME())
                 let u3 := montgomeryMul(u2, u, P(), P_PRIME())
                 let v := montgomeryMul(zp, zq, P(), P_PRIME())