From 27ad5eb7c5ec82208a77f476be953a3feb912b91 Mon Sep 17 00:00:00 2001 From: poma Date: Fri, 31 Jan 2020 17:03:00 +0800 Subject: [PATCH] fix verifier.sol bugs, port it to Solidity 6 --- phase2/src/circom_circuit.rs | 2 +- phase2/src/verifier_groth.sol | 52 ++++++++++++++++++----------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/phase2/src/circom_circuit.rs b/phase2/src/circom_circuit.rs index 1c37435..146eb9e 100644 --- a/phase2/src/circom_circuit.rs +++ b/phase2/src/circom_circuit.rs @@ -256,7 +256,7 @@ pub fn create_verifier_sol(params: &Parameters) -> String { let x_c1 = repr_to_big(x.c1.into_repr()); let y_c0 = repr_to_big(y.c0.into_repr()); let y_c1 = repr_to_big(y.c1.into_repr()); - format!("[{}, {}], [{}, {}]", x_c0, x_c1, y_c0, y_c1) + format!("[{}, {}], [{}, {}]", x_c1, x_c0, y_c1, y_c0) }; let template = template.replace("<%vk_alfa1%>", &*p1_to_str(¶ms.vk.alpha_g1)); diff --git a/phase2/src/verifier_groth.sol b/phase2/src/verifier_groth.sol index ba2e4cf..cddfb57 100644 --- a/phase2/src/verifier_groth.sol +++ b/phase2/src/verifier_groth.sol @@ -9,7 +9,7 @@ // fixed linter warnings // added require error messages // -pragma solidity ^0.5.0; +pragma solidity ^0.6.0; library Pairing { struct G1Point { uint X; @@ -52,7 +52,7 @@ library Pairing { return G1Point(0, 0); return G1Point(p.X, q - (p.Y % q)); } - /// @return the sum of two points of G1 + /// @return r the sum of two points of G1 function addition(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) { uint[4] memory input; input[0] = p1.X; @@ -62,13 +62,13 @@ library Pairing { bool success; // solium-disable-next-line security/no-inline-assembly assembly { - success := staticcall(sub(gas, 2000), 6, input, 0xc0, r, 0x60) + success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } require(success,"pairing-add-failed"); } - /// @return the product of a point on G1 and a scalar, i.e. + /// @return r the product of a point on G1 and a scalar, i.e. /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p. function scalar_mul(G1Point memory p, uint s) internal view returns (G1Point memory r) { uint[3] memory input; @@ -78,7 +78,7 @@ library Pairing { bool success; // solium-disable-next-line security/no-inline-assembly assembly { - success := staticcall(sub(gas, 2000), 7, input, 0x80, r, 0x60) + success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } @@ -106,7 +106,7 @@ library Pairing { bool success; // solium-disable-next-line security/no-inline-assembly assembly { - success := staticcall(sub(gas, 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) + success := staticcall(sub(gas(), 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } @@ -181,43 +181,45 @@ contract Verifier { vk.IC = new Pairing.G1Point[](<%vk_ic_length%>); <%vk_ic_pts%> } - function verify(uint[] memory input, Proof memory proof) internal view returns (uint) { + function verify(Proof memory proof, uint[<%vk_input_length%>] memory input) internal view returns (bool) { uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617; VerifyingKey memory vk = verifyingKey(); - require(input.length + 1 == vk.IC.length,"verifier-bad-input"); + require(input.length + 1 == vk.IC.length, "verifier-bad-input"); // Compute the linear combination vk_x Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0); + vk_x = Pairing.addition(vk_x, vk.IC[0]); for (uint i = 0; i < input.length; i++) { - require(input[i] < snark_scalar_field,"verifier-gte-snark-scalar-field"); + require(input[i] < snark_scalar_field, "verifier-gte-snark-scalar-field"); vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[i + 1], input[i])); } - vk_x = Pairing.addition(vk_x, vk.IC[0]); - if (!Pairing.pairingProd4( + return Pairing.pairingProd4( Pairing.negate(proof.A), proof.B, vk.alfa1, vk.beta2, vk_x, vk.gamma2, proof.C, vk.delta2 - )) return 1; - return 0; + ); } function verifyProof( uint[2] memory a, uint[2][2] memory b, uint[2] memory c, uint[<%vk_input_length%>] memory input - ) public view returns (bool r) { - Proof memory proof; - proof.A = Pairing.G1Point(a[0], a[1]); - proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]); - proof.C = Pairing.G1Point(c[0], c[1]); - return verify(input, proof); + ) public view returns (bool) { + Proof memory _proof; + _proof.A = Pairing.G1Point(a[0], a[1]); + _proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]); + _proof.C = Pairing.G1Point(c[0], c[1]); + return verify(_proof, input); } - function verifyProof(bytes memory proof, uint[<%vk_input_length%>] memory inputs) public view returns (bool r) { + function verifyProof( + bytes memory proof, + uint[<%vk_input_length%>] memory input + ) public view returns (bool) { uint[8] memory p = abi.decode(proof, (uint[8])); - Proof memory proof; - proof.A = Pairing.G1Point(p[0], p[1]); - proof.B = Pairing.G2Point([p[2], p[3]], [p[4], p[5]]); - proof.C = Pairing.G1Point(p[6], c[7]); - return verify(inputs, proof) == 0; + Proof memory _proof; + _proof.A = Pairing.G1Point(p[0], p[1]); + _proof.B = Pairing.G2Point([p[2], p[3]], [p[4], p[5]]); + _proof.C = Pairing.G1Point(p[6], p[7]); + return verify(_proof, input); } }