Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove all Yul references in EVM placeholder base #46

Draft
wants to merge 26 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 0 additions & 135 deletions contracts/algebra/bn254.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,139 +25,4 @@ import {types} from "../types.sol";
library bn254_crypto {
uint256 constant p_mod = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
uint256 constant r_mod = 21888242871839275222246405745257275088548364400416034343698204186575808495617;

// Perform a modular exponentiation. This method is ideal for small exponents (~64 bits or less), as
// it is cheaper than using the pow precompile
function pow_small(uint256 base, uint256 exponent, uint256 modulus) internal pure returns (uint256) {
uint256 result = 1;
uint256 input = base;
uint256 count = 1;

assembly {
let endpoint := add(exponent, 0x01)
for {} lt(count, endpoint) {count := add(count, count)}
{
if and(exponent, count) {
result := mulmod(result, input, modulus)
}
input := mulmod(input, input, modulus)
}
}

return result;
}

function invert(uint256 fr) internal view returns (uint256) {
uint256 output;
bool success;
uint256 p = r_mod;
assembly {
let mPtr := mload(0x40)
mstore(mPtr, 0x20)
mstore(add(mPtr, 0x20), 0x20)
mstore(add(mPtr, 0x40), 0x20)
mstore(add(mPtr, 0x60), fr)
mstore(add(mPtr, 0x80), sub(p, 2))
mstore(add(mPtr, 0xa0), p)
success := staticcall(gas(), 0x05, mPtr, 0xc0, 0x00, 0x20)
output := mload(0x00)
}
require(success, "pow precompile call failed!");
return output;
}

function new_g1(uint256 x, uint256 y) internal pure returns (types.g1_point memory) {
uint256 xValue;
uint256 yValue;
assembly {
xValue := mod(x, r_mod)
yValue := mod(y, r_mod)
}
return types.g1_point(xValue, yValue);
}

function new_g2(uint256 x0, uint256 x1, uint256 y0, uint256 y1) internal pure returns (types.g2_point memory) {
return types.g2_point(x0, x1, y0, y1);
}

function P1() internal pure returns (types.g1_point memory) {
return types.g1_point(1, 2);
}

function P2() internal pure returns (types.g2_point memory) {
return types.g2_point({
x0 : 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2,
x1 : 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed,
y0 : 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b,
y1 : 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa
});
}


/// Evaluate the following pairing product:
/// e(a1, a2).e(-b1, b2) == 1
function pairingProd2(
types.g1_point memory a1,
types.g2_point memory a2,
types.g1_point memory b1,
types.g2_point memory b2
) internal view returns (bool) {
validateG1Point(a1);
validateG1Point(b1);
bool success;
uint256 out;
assembly {
let mPtr := mload(0x40)
mstore(mPtr, mload(a1))
mstore(add(mPtr, 0x20), mload(add(a1, 0x20)))
mstore(add(mPtr, 0x40), mload(a2))
mstore(add(mPtr, 0x60), mload(add(a2, 0x20)))
mstore(add(mPtr, 0x80), mload(add(a2, 0x40)))
mstore(add(mPtr, 0xa0), mload(add(a2, 0x60)))

mstore(add(mPtr, 0xc0), mload(b1))
mstore(add(mPtr, 0xe0), mload(add(b1, 0x20)))
mstore(add(mPtr, 0x100), mload(b2))
mstore(add(mPtr, 0x120), mload(add(b2, 0x20)))
mstore(add(mPtr, 0x140), mload(add(b2, 0x40)))
mstore(add(mPtr, 0x160), mload(add(b2, 0x60)))
success := staticcall(
gas(),
8,
mPtr,
0x180,
0x00,
0x20
)
out := mload(0x00)
}
require(success, "Pairing check failed!");
return (out != 0);
}

/**
* validate the following:
* x != 0
* y != 0
* x < p
* y < p
* y^2 = x^3 + 3 mod p
*/
function validateG1Point(types.g1_point memory point) internal pure {
bool is_well_formed;
uint256 p = p_mod;
assembly {
let x := mload(point)
let y := mload(add(point, 0x20))

is_well_formed := and(
and(
and(lt(x, p), lt(y, p)),
not(or(iszero(x), iszero(y)))
),
eq(mulmod(y, y, p), addmod(mulmod(x, mulmod(x, x, p), p), 3, p))
)
}
require(is_well_formed, "Bn254: G1 point not on curve, or is malformed");
}
}
166 changes: 76 additions & 90 deletions contracts/algebra/field.sol
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We definitely need something like expmod_static and inversed_static functions in this branch. We cannot run verifier without them. We need to think, what is the best way to do it using pure solidity.

Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,6 @@ pragma solidity >=0.8.4;
* @dev Provides some basic methods to compute bilinear pairings, construct group elements and misc numerical methods
*/
library field {
// Perform a modular exponentiation. This method is ideal for small exponents (~64 bits or less), as
// it is cheaper than using the pow precompile
function pow_small(uint256 base, uint256 exponent, uint256 modulus)
internal pure returns (uint256 result) {
result = 1;
assembly {
for {let count := 1}
lt(count, add(exponent, 0x01))
{count := shl(1, count)} {
if and(exponent, count) {
result := mulmod(result, base, modulus)
}
base := mulmod(base, base, modulus)
}
}
}

/// @dev Modular inverse of a (mod p) using euclid.
/// 'a' and 'p' must be co-prime.
Expand Down Expand Up @@ -66,106 +50,108 @@ library field {

function fadd(uint256 a, uint256 b, uint256 modulus)
internal pure returns (uint256 result) {
assembly {
result := addmod(a, b, modulus)
}
result = addmod(a, b, modulus);
// assembly {
// result := addmod(a, b, modulus)
// }
}


function fsub(uint256 a, uint256 b, uint256 modulus)
internal pure returns (uint256 result) {
assembly {
result := addmod(a, sub(modulus, b), modulus)
}
result =addmod(a , (modulus - b), modulus);
// assembly {
// result := addmod(a, sub(modulus, b), modulus)
// }
}

function fmul(uint256 a, uint256 b, uint256 modulus)
internal pure returns (uint256 result) {
assembly {
result := mulmod(a, b, modulus)
}
result = mulmod(a, b, modulus);
// assembly {
// result := mulmod(a, b, modulus)
// }
}

function fdiv(uint256 a, uint256 b, uint256 modulus)
internal pure returns (uint256 result) {
uint256 b_inv = invmod(b, modulus);
assembly {
result := mulmod(a, b_inv, modulus)
}
result =mulmod(a, b_inv, modulus);
// assembly {
// result := mulmod(a, b_inv, modulus)
// }
}

// See https://ethereum.stackexchange.com/questions/8086/logarithm-math-operation-in-solidity
function log2(uint256 x)
internal pure returns (uint256 y){
assembly {
let arg := x
x := sub(x, 1)
x := or(x, div(x, 0x02))
x := or(x, div(x, 0x04))
x := or(x, div(x, 0x10))
x := or(x, div(x, 0x100))
x := or(x, div(x, 0x10000))
x := or(x, div(x, 0x100000000))
x := or(x, div(x, 0x10000000000000000))
x := or(x, div(x, 0x100000000000000000000000000000000))
x := add(x, 1)
let m := mload(0x40)
mstore(m, 0xf8f9cbfae6cc78fbefe7cdc3a1793dfcf4f0e8bbd8cec470b6a28a7a5a3e1efd)
mstore(add(m, 0x20), 0xf5ecf1b3e9debc68e1d9cfabc5997135bfb7a7a3938b7b606b5b4b3f2f1f0ffe)
mstore(add(m, 0x40), 0xf6e4ed9ff2d6b458eadcdf97bd91692de2d4da8fd2d0ac50c6ae9a8272523616)
mstore(add(m, 0x60), 0xc8c0b887b0a8a4489c948c7f847c6125746c645c544c444038302820181008ff)
mstore(add(m, 0x80), 0xf7cae577eec2a03cf3bad76fb589591debb2dd67e0aa9834bea6925f6a4a2e0e)
mstore(add(m, 0xa0), 0xe39ed557db96902cd38ed14fad815115c786af479b7e83247363534337271707)
mstore(add(m, 0xc0), 0xc976c13bb96e881cb166a933a55e490d9d56952b8d4e801485467d2362422606)
mstore(add(m, 0xe0), 0x753a6d1b65325d0c552a4d1345224105391a310b29122104190a110309020100)
mstore(0x40, add(m, 0x100))
let magic := 0x818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff
let shift := 0x100000000000000000000000000000000000000000000000000000000000000
let a := div(mul(x, magic), shift)
y := div(mload(add(m, sub(255, a))), shift)
y := add(y, mul(256, gt(arg, 0x8000000000000000000000000000000000000000000000000000000000000000)))
}
//TODO : Check for a way to do this in pure cairo instead of solidity asm
// assembly {
// let arg := x
// x := sub(x, 1)
// x := or(x, div(x, 0x02))
// x := or(x, div(x, 0x04))
// x := or(x, div(x, 0x10))
// x := or(x, div(x, 0x100))
// x := or(x, div(x, 0x10000))
// x := or(x, div(x, 0x100000000))
// x := or(x, div(x, 0x10000000000000000))
// x := or(x, div(x, 0x100000000000000000000000000000000))
// x := add(x, 1)
// let m := mload(0x40)
// mstore(m, 0xf8f9cbfae6cc78fbefe7cdc3a1793dfcf4f0e8bbd8cec470b6a28a7a5a3e1efd)
// mstore(add(m, 0x20), 0xf5ecf1b3e9debc68e1d9cfabc5997135bfb7a7a3938b7b606b5b4b3f2f1f0ffe)
// mstore(add(m, 0x40), 0xf6e4ed9ff2d6b458eadcdf97bd91692de2d4da8fd2d0ac50c6ae9a8272523616)
// mstore(add(m, 0x60), 0xc8c0b887b0a8a4489c948c7f847c6125746c645c544c444038302820181008ff)
// mstore(add(m, 0x80), 0xf7cae577eec2a03cf3bad76fb589591debb2dd67e0aa9834bea6925f6a4a2e0e)
// mstore(add(m, 0xa0), 0xe39ed557db96902cd38ed14fad815115c786af479b7e83247363534337271707)
// mstore(add(m, 0xc0), 0xc976c13bb96e881cb166a933a55e490d9d56952b8d4e801485467d2362422606)
// mstore(add(m, 0xe0), 0x753a6d1b65325d0c552a4d1345224105391a310b29122104190a110309020100)
// mstore(0x40, add(m, 0x100))
// let magic := 0x818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff
// let shift := 0x100000000000000000000000000000000000000000000000000000000000000
// let a := div(mul(x, magic), shift)
// y := div(mload(add(m, sub(255, a))), shift)
// y := add(y, mul(256, gt(arg, 0x8000000000000000000000000000000000000000000000000000000000000000)))
// }
}

function expmod_static(uint256 base, uint256 exponent, uint256 modulus)
internal view returns (uint256 res) {
assembly {
let p := mload(0x40)
mstore(p, 0x20) // Length of Base.
mstore(add(p, 0x20), 0x20) // Length of Exponent.
mstore(add(p, 0x40), 0x20) // Length of Modulus.
mstore(add(p, 0x60), base) // Base.
mstore(add(p, 0x80), exponent) // Exponent.
mstore(add(p, 0xa0), modulus) // Modulus.
// Call modexp precompile.
if iszero(staticcall(gas(), 0x05, p, 0xc0, p, 0x20)) {
revert(0, 0)
}
res := mload(p)
}
//TODO check if you can do this in cairo
// assembly {
// let p := mload(0x40)
// mstore(p, 0x20) // Length of Base.
// mstore(add(p, 0x20), 0x20) // Length of Exponent.
// mstore(add(p, 0x40), 0x20) // Length of Modulus.
// mstore(add(p, 0x60), base) // Base.
// mstore(add(p, 0x80), exponent) // Exponent.
// mstore(add(p, 0xa0), modulus) // Modulus.
// // Call modexp precompile.
// if iszero(staticcall(gas(), 0x05, p, 0xc0, p, 0x20)) {
// revert(0, 0)
// }
// res := mload(p)
// }
}

function inverse_static(uint256 val, uint256 modulus)
internal view returns (uint256 res) {
// return expmod_static(val, modulus - 2, modulus); // code below similar to this call
assembly {
let p := mload(0x40)
mstore(p, 0x20) // Length of Base.
mstore(add(p, 0x20), 0x20) // Length of Exponent.
mstore(add(p, 0x40), 0x20) // Length of Modulus.
mstore(add(p, 0x60), val) // Base.
mstore(add(p, 0x80), sub(modulus, 0x02)) // Exponent.
mstore(add(p, 0xa0), modulus) // Modulus.
// Call modexp precompile.
if iszero(staticcall(gas(), 0x05, p, 0xc0, p, 0x20)) {
revert(0, 0)
}
res := mload(p)
}
}

function double(uint256 val, uint256 modulus) internal pure returns (uint256 result) {
assembly {
result := mulmod(2, val, modulus)
}
//TODO : Check cairo implementation
// assembly {
// let p := mload(0x40)
// mstore(p, 0x20) // Length of Base.
// mstore(add(p, 0x20), 0x20) // Length of Exponent.
// mstore(add(p, 0x40), 0x20) // Length of Modulus.
// mstore(add(p, 0x60), val) // Base.
// mstore(add(p, 0x80), sub(modulus, 0x02)) // Exponent.
// mstore(add(p, 0xa0), modulus) // Modulus.
// // Call modexp precompile.
// if iszero(staticcall(gas(), 0x05, p, 0xc0, p, 0x20)) {
// revert(0, 0)
// }
// res := mload(p)
// }
}
}
Loading