Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Loading...
Loading
Contract Name:
Bn128SchnorrVerifier
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import "./Bn128.sol";
/**
* @title Bn128SchnorrVerifier
* @dev Implementation of Schnorr signature verification for the Bn128 curve
* This contract provides functionality to verify Schnorr signatures using the Bn128 elliptic curve
*/
contract Bn128SchnorrVerifier is Bn128 {
using SafeMath for uint256;
/**
* @dev Structure representing a point on the elliptic curve
* @param x X-coordinate of the point
* @param y Y-coordinate of the point
*/
struct Point {
uint256 x; uint256 y;
}
/**
* @dev Structure containing all the data needed for signature verification
* @param groupKey The public key point
* @param randomPoint The random point used in signature generation
* @param signature The signature value
* @param message The message that was signed
* @param _hash The hash value computed during verification
* @param _left The left side of the verification equation
* @param _right The right side of the verification equation
*/
struct Verification {
Point groupKey;
Point randomPoint;
uint256 signature;
bytes32 message;
uint256 _hash;
Point _left;
Point _right;
}
/**
* @notice Computes the hash value used in Schnorr signature verification
* @dev Implements the hash function h(m, R) where m is the message and R is the random point
* @param m The message to be hashed
* @param a X-coordinate of the random point
* @param b Y-coordinate of the random point
* @return The computed hash value
*/
function h(bytes32 m, uint256 a, uint256 b) public pure returns (uint256) {
return uint256(sha256(abi.encodePacked(m, a, b)));
}
/**
* @notice Performs scalar multiplication on a point
* @dev Wrapper for the ecmul function from Bn128
* @param x X-coordinate of the input point
* @param y Y-coordinate of the input point
* @param scalar The scalar value to multiply by
* @return The resulting point coordinates
*/
function cmul(uint256 x, uint256 y, uint256 scalar) public view returns (uint256, uint256) {
return ecmul(x, y, scalar);
}
/**
* @notice Computes the signature point sG
* @dev Multiplies the base point G by the signature value
* @param sig_s The signature value
* @return The resulting point coordinates
*/
function sg(uint256 sig_s) public view returns (uint256, uint256) {
return ecmul(getGx(), getGy(), sig_s);
}
/**
* @notice Performs point addition
* @dev Wrapper for the ecadd function from Bn128
* @param ax X-coordinate of the first point
* @param ay Y-coordinate of the first point
* @param bx X-coordinate of the second point
* @param by Y-coordinate of the second point
* @return The resulting point coordinates
*/
function cadd(uint256 ax, uint256 ay, uint256 bx, uint256 by) public view returns (uint256, uint256) {
return ecadd(ax, ay, bx, by);
}
/**
* @notice Verifies a Schnorr signature
* @dev Implements the Schnorr signature verification algorithm for Bn128 curve
* The verification checks if sG = R + h(m,R)Y where:
* - s is the signature
* - G is the base point
* - R is the random point
* - h(m,R) is the hash of the message and random point
* - Y is the public key
* The hash value is reduced modulo the curve order to ensure it's in the correct range
* @param signature The signature to verify
* @param groupKeyX X-coordinate of the public key
* @param groupKeyY Y-coordinate of the public key
* @param randomPointX X-coordinate of the random point
* @param randomPointY Y-coordinate of the random point
* @param message The message that was signed
* @return bool indicating whether the signature is valid
*/
function verify(bytes32 signature, bytes32 groupKeyX, bytes32 groupKeyY, bytes32 randomPointX, bytes32 randomPointY, bytes32 message)
public
view
returns(bool)
{
bool flag = false;
Verification memory state;
state.signature = uint256(signature);
state.groupKey.x = uint256(groupKeyX);
state.groupKey.y = uint256(groupKeyY);
state.randomPoint.x = uint256(randomPointX);
state.randomPoint.y = uint256(randomPointY);
state.message = message;
state._hash = h(state.message, state.randomPoint.x, state.randomPoint.y);
/// @dev Reduce hash value to bn256 range
state._hash = (state._hash).mod(getOrder());
(state._left.x, state._left.y) = sg(state.signature);
Point memory rightPart;
(rightPart.x, rightPart.y) = cmul(state.groupKey.x, state.groupKey.y, state._hash);
(state._right.x, state._right.y) = cadd(state.randomPoint.x, state.randomPoint.y, rightPart.x, rightPart.y);
flag = state._left.x == state._right.x && state._left.y == state._right.y;
return flag;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
/**
* @title Bn128
* @dev Implementation of the Bn128 elliptic curve operations
* This contract provides:
* - Base point (G) coordinates
* - Curve order
* - Point addition (ECADD)
* - Scalar multiplication (ECMUL)
*/
contract Bn128 {
using SafeMath for uint256;
/// @notice x-coordinate of the base point G
uint256 constant gx = 0x1;
/// @notice y-coordinate of the base point G
uint256 constant gy = 0x2;
/// @notice Order of the curve
/// @dev Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1
uint256 constant order = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
/**
* @notice Returns the x-coordinate of the base point G
* @return x-coordinate of G
*/
function getGx() public pure returns (uint256) {
return gx;
}
/**
* @notice Returns the y-coordinate of the base point G
* @return y-coordinate of G
*/
function getGy() public pure returns (uint256) {
return gy;
}
/**
* @notice Returns the order of the curve
* @return Order of the curve
*/
function getOrder() public pure returns (uint256) {
return order;
}
/**
* @notice Performs point addition on the curve
* @dev Adds two points (x1,y1) and (x2,y2) to get (x3,y3)
* @param x1 x-coordinate of first point
* @param y1 y-coordinate of first point
* @param x2 x-coordinate of second point
* @param y2 y-coordinate of second point
* @return x3 x-coordinate of resulting point
* @return y3 y-coordinate of resulting point
*/
function ecadd(
uint256 x1,
uint256 y1,
uint256 x2,
uint256 y2
) public view returns (uint256 x3, uint256 y3) {
uint256[2] memory outValue;
uint256[4] memory input;
input[0] = x1;
input[1] = y1;
input[2] = x2;
input[3] = y2;
assembly {
if iszero(staticcall(gas(), 0x06, input, 0x80, outValue, 0x40)) {
revert(0, 0)
}
}
x3 = outValue[0];
y3 = outValue[1];
}
/**
* @notice Performs scalar multiplication on the curve
* @dev Multiplies point (x1,y1) by scalar to get (x2,y2)
* @param x1 x-coordinate of input point
* @param y1 y-coordinate of input point
* @param scalar Scalar value to multiply by
* @return x2 x-coordinate of resulting point
* @return y2 y-coordinate of resulting point
*/
function ecmul(
uint256 x1,
uint256 y1,
uint256 scalar
) public view returns (uint256 x2, uint256 y2) {
uint256[2] memory outValue;
uint256[3] memory input;
input[0] = x1;
input[1] = y1;
input[2] = scalar;
assembly {
if iszero(staticcall(gas(), 0x07, input, 0x60, outValue, 0x40)) {
revert(0, 0)
}
}
x2 = outValue[0];
y2 = outValue[1];
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract ABI
API[{"inputs":[{"internalType":"uint256","name":"ax","type":"uint256"},{"internalType":"uint256","name":"ay","type":"uint256"},{"internalType":"uint256","name":"bx","type":"uint256"},{"internalType":"uint256","name":"by","type":"uint256"}],"name":"cadd","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"},{"internalType":"uint256","name":"scalar","type":"uint256"}],"name":"cmul","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x1","type":"uint256"},{"internalType":"uint256","name":"y1","type":"uint256"},{"internalType":"uint256","name":"x2","type":"uint256"},{"internalType":"uint256","name":"y2","type":"uint256"}],"name":"ecadd","outputs":[{"internalType":"uint256","name":"x3","type":"uint256"},{"internalType":"uint256","name":"y3","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x1","type":"uint256"},{"internalType":"uint256","name":"y1","type":"uint256"},{"internalType":"uint256","name":"scalar","type":"uint256"}],"name":"ecmul","outputs":[{"internalType":"uint256","name":"x2","type":"uint256"},{"internalType":"uint256","name":"y2","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getGy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getOrder","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"m","type":"bytes32"},{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"}],"name":"h","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"sig_s","type":"uint256"}],"name":"sg","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"signature","type":"bytes32"},{"internalType":"bytes32","name":"groupKeyX","type":"bytes32"},{"internalType":"bytes32","name":"groupKeyY","type":"bytes32"},{"internalType":"bytes32","name":"randomPointX","type":"bytes32"},{"internalType":"bytes32","name":"randomPointY","type":"bytes32"},{"internalType":"bytes32","name":"message","type":"bytes32"}],"name":"verify","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b5061069a806100206000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c8063923e4f0111610066578063923e4f011461012a578063bb8c256a14610131578063d36dedd214610144578063f8fd2e831461016a578063fb3941b41461017d57600080fd5b8063182f875c146100a35780632dfb77cc146100cb5780634a6760b8146100f35780636495d679146101045780638081a1e714610117575b600080fd5b6100b66100b1366004610540565b610190565b60405190151581526020015b60405180910390f35b6100de6100d9366004610583565b6102c0565b604080519283526020830191909152016100c2565b60015b6040519081526020016100c2565b6100de6101123660046105af565b6102da565b6100de610125366004610583565b6102f6565b60026100f6565b6100de61013f3660046105af565b610341565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016100f6565b6100de6101783660046105e1565b610394565b6100f661018b366004610583565b6103ad565b60008061019b610443565b60408101899052805188905280516020908101889052808201805188905280518201879052606083018690525180519101516101d89186916103ad565b60808201819052610209907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610430565b6080820152604081015161021c90610394565b60a08301516020808201929092529190915260408051808201909152600080825281830152825180519201516080840151919261025b929091906102c0565b602080840182905282845284810151805191015161027d9391929091906102da565b60c0840180516020810192909252919052515160a0830151511480156102b257508160c00151602001518260a0015160200151145b9a9950505050505050505050565b6000806102ce8585856102f6565b91509150935093915050565b6000806102e986868686610341565b9150915094509492505050565b6000806103016104e6565b610309610504565b8681526020810186905260408082018690528260608360075afa61032c57600080fd5b50805160209091015190969095509350505050565b60008061034c6104e6565b610354610522565b878152602081018790526040808201879052606082018690528260808360065afa61037e57600080fd5b5080516020909101519097909650945050505050565b6000806103a460016002856102f6565b91509150915091565b60408051602081018590529081018390526060810182905260009060029060800160408051601f19818403018152908290526103e8916105fa565b602060405180830381855afa158015610405573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906104289190610629565b949350505050565b600061043c8284610642565b9392505050565b604080516101208101909152600060e0820181815261010083019190915281908152602001610485604051806040016040528060008152602001600081525090565b81526020016000815260200160008019168152602001600081526020016104bf604051806040016040528060008152602001600081525090565b81526020016104e1604051806040016040528060008152602001600081525090565b905290565b60405180604001604052806002906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b60008060008060008060c0878903121561055957600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b60008060006060848603121561059857600080fd5b505081359360208301359350604090920135919050565b600080600080608085870312156105c557600080fd5b5050823594602084013594506040840135936060013592509050565b6000602082840312156105f357600080fd5b5035919050565b6000825160005b8181101561061b5760208186018101518583015201610601565b506000920191825250919050565b60006020828403121561063b57600080fd5b5051919050565b60008261065f57634e487b7160e01b600052601260045260246000fd5b50069056fea26469706673582212202dba88d2730837bada25f841679fbc4ada909cce4c2bd317b7726b068bcedb8b64736f6c63430008120033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061009e5760003560e01c8063923e4f0111610066578063923e4f011461012a578063bb8c256a14610131578063d36dedd214610144578063f8fd2e831461016a578063fb3941b41461017d57600080fd5b8063182f875c146100a35780632dfb77cc146100cb5780634a6760b8146100f35780636495d679146101045780638081a1e714610117575b600080fd5b6100b66100b1366004610540565b610190565b60405190151581526020015b60405180910390f35b6100de6100d9366004610583565b6102c0565b604080519283526020830191909152016100c2565b60015b6040519081526020016100c2565b6100de6101123660046105af565b6102da565b6100de610125366004610583565b6102f6565b60026100f6565b6100de61013f3660046105af565b610341565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016100f6565b6100de6101783660046105e1565b610394565b6100f661018b366004610583565b6103ad565b60008061019b610443565b60408101899052805188905280516020908101889052808201805188905280518201879052606083018690525180519101516101d89186916103ad565b60808201819052610209907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610430565b6080820152604081015161021c90610394565b60a08301516020808201929092529190915260408051808201909152600080825281830152825180519201516080840151919261025b929091906102c0565b602080840182905282845284810151805191015161027d9391929091906102da565b60c0840180516020810192909252919052515160a0830151511480156102b257508160c00151602001518260a0015160200151145b9a9950505050505050505050565b6000806102ce8585856102f6565b91509150935093915050565b6000806102e986868686610341565b9150915094509492505050565b6000806103016104e6565b610309610504565b8681526020810186905260408082018690528260608360075afa61032c57600080fd5b50805160209091015190969095509350505050565b60008061034c6104e6565b610354610522565b878152602081018790526040808201879052606082018690528260808360065afa61037e57600080fd5b5080516020909101519097909650945050505050565b6000806103a460016002856102f6565b91509150915091565b60408051602081018590529081018390526060810182905260009060029060800160408051601f19818403018152908290526103e8916105fa565b602060405180830381855afa158015610405573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906104289190610629565b949350505050565b600061043c8284610642565b9392505050565b604080516101208101909152600060e0820181815261010083019190915281908152602001610485604051806040016040528060008152602001600081525090565b81526020016000815260200160008019168152602001600081526020016104bf604051806040016040528060008152602001600081525090565b81526020016104e1604051806040016040528060008152602001600081525090565b905290565b60405180604001604052806002906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b60008060008060008060c0878903121561055957600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b60008060006060848603121561059857600080fd5b505081359360208301359350604090920135919050565b600080600080608085870312156105c557600080fd5b5050823594602084013594506040840135936060013592509050565b6000602082840312156105f357600080fd5b5035919050565b6000825160005b8181101561061b5760208186018101518583015201610601565b506000920191825250919050565b60006020828403121561063b57600080fd5b5051919050565b60008261065f57634e487b7160e01b600052601260045260246000fd5b50069056fea26469706673582212202dba88d2730837bada25f841679fbc4ada909cce4c2bd317b7726b068bcedb8b64736f6c63430008120033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.