From 6bb4ac59baec53106f22d5e1224357643c7c524d Mon Sep 17 00:00:00 2001 From: vladbochok Date: Tue, 20 Feb 2024 08:40:44 +0100 Subject: [PATCH 1/3] Fixes & suggestions --- precompiles/EcPairing.yul | 52 +++++++++------------------------------ 1 file changed, 11 insertions(+), 41 deletions(-) diff --git a/precompiles/EcPairing.yul b/precompiles/EcPairing.yul index 0d5cadb7..48ce763f 100644 --- a/precompiles/EcPairing.yul +++ b/precompiles/EcPairing.yul @@ -448,17 +448,6 @@ object "EcPairing" { ny0, ny1 := fp2Neg(y0, y1) } - /// @notice Check if a G2 point in jacobian coordinates is in the subgroup of the twisted curve. - /// @dev The coordinates are encoded in Montgomery form. - /// @param xp0, xp1 The x coordinate of the point. - /// @param yp0, yp1 The y coordinate of the point. - /// @param zp0, zp1 The z coordinate of the point. - /// @return ret True if the point is in the subgroup, false otherwise. - function g2IsInSubGroup(xp0, xp1, yp0, yp1, zp0, zp1) -> ret { - let xr0, xr1, yr0, yr1, zr0, zr1 := g2ScalarMul(xp0, xp1, yp0, yp1, zp0, zp1, TWISTED_SUBGROUP_ORDER()) - ret := and(iszero(zr0), iszero(zr1)) - } - /// @notice Double a g2 point represented in jacobian coordinates. /// @dev The coordinates must be encoded in Montgomery form. /// @param xp0, xp1 The x coordinate of the point. @@ -1562,10 +1551,9 @@ object "EcPairing" { let inputSize := calldatasize() - // Empty input is valid and results in returning one. - if eq(inputSize, 0) { - mstore(0, 1) - return(0, 32) + // Empty input is valid and results in succcess with empty return data. + if iszero(inputSize) { + return(0, 0) } // If the input length is not a multiple of 192, the call fails. @@ -1579,11 +1567,9 @@ object "EcPairing" { // Calldata "parsing" for { let i := 0 } lt(i, inputSize) { i := add(i, PAIR_LENGTH()) } { /* G1 */ - calldatacopy(i, i, 32) // x - calldatacopy(add(i, 32), add(i, 32), 32) // y - let g1_x := mload(i) - let g1_y := mload(add(i, 32)) + let g1_x := calldataload(i) + let g1_y := calldataload(add(i, 32)) if iszero(and(coordinateIsOnFieldOrder(g1_x), coordinateIsOnFieldOrder(g1_y))) { burnGas() @@ -1593,33 +1579,21 @@ object "EcPairing" { g1_y := intoMontgomeryForm(g1_y) let g1IsInfinity := g1AffinePointIsInfinity(g1_x, g1_y) - if and(iszero(g1IsInfinity), iszero(g1AffinePointIsOnCurve(g1_x, g1_y))) { burnGas() } /* G2 */ - let g2_x1_offset := add(i, 64) - let g2_x0_offset := add(i, 96) - let g2_y1_offset := add(i, 128) - let g2_y0_offset := add(i, 160) - - calldatacopy(g2_x1_offset, g2_x1_offset, 32) - calldatacopy(g2_x0_offset, g2_x0_offset, 32) - calldatacopy(g2_y1_offset, g2_y1_offset, 32) - calldatacopy(g2_y0_offset, g2_y0_offset, 32) - - let g2_x1 := mload(g2_x1_offset) - let g2_x0 := mload(g2_x0_offset) - let g2_y1 := mload(g2_y1_offset) - let g2_y0 := mload(g2_y0_offset) - - // TODO: Double check if this is right + + let g2_x1 := calldataload(add(i, 64)) + let g2_x0 := calldataload(add(i, 96)) + let g2_y1 := calldataload(add(i, 128)) + let g2_y0 := calldataload(add(i, 160)) + if iszero(and(coordinateIsOnFieldOrder(g2_x0), coordinateIsOnFieldOrder(g2_x1))) { burnGas() } - // TODO: Double check if this is right if iszero(and(coordinateIsOnFieldOrder(g2_y0), coordinateIsOnFieldOrder(g2_y1))) { burnGas() } @@ -1633,10 +1607,6 @@ object "EcPairing" { g2_y0 := intoMontgomeryForm(g2_y0) g2_y1 := intoMontgomeryForm(g2_y1) - if iszero(g2IsInSubGroup(g2_x0,g2_x1, g2_y0, g2_y1, MONTGOMERY_ONE(), 0)) { - burnGas() - } - if iszero(g2AffinePointIsOnCurve(g2_x0, g2_x1, g2_y0, g2_y1)) { burnGas() } From 891c13a8f42d1f8569fa74bba0b652a1c9437956 Mon Sep 17 00:00:00 2001 From: vladbochok Date: Tue, 20 Feb 2024 08:57:26 +0100 Subject: [PATCH 2/3] Restore the correct check --- precompiles/EcPairing.yul | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/precompiles/EcPairing.yul b/precompiles/EcPairing.yul index 48ce763f..a91d5790 100644 --- a/precompiles/EcPairing.yul +++ b/precompiles/EcPairing.yul @@ -1551,9 +1551,10 @@ object "EcPairing" { let inputSize := calldatasize() - // Empty input is valid and results in succcess with empty return data. - if iszero(inputSize) { - return(0, 0) + // Empty input is valid and results in returning one. + if eq(inputSize, 0) { + mstore(0, 1) + return(0, 32) } // If the input length is not a multiple of 192, the call fails. From c849eb2e1eb45498b6cc50309e024b42c400b5c5 Mon Sep 17 00:00:00 2001 From: vladbochok Date: Tue, 20 Feb 2024 09:02:16 +0100 Subject: [PATCH 3/3] Restore the layout --- precompiles/EcPairing.yul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/precompiles/EcPairing.yul b/precompiles/EcPairing.yul index a91d5790..a70b0e8b 100644 --- a/precompiles/EcPairing.yul +++ b/precompiles/EcPairing.yul @@ -1553,7 +1553,7 @@ object "EcPairing" { // Empty input is valid and results in returning one. if eq(inputSize, 0) { - mstore(0, 1) + mstore(0, 1) return(0, 32) }