Skip to content

Commit

Permalink
Merge pull request #25 from hyperledger-labs/kyc
Browse files Browse the repository at this point in the history
Add circuits for KYC enforcement with anonymity
  • Loading branch information
jimthematrix committed Aug 7, 2024
2 parents 1c7f4a7 + add8e32 commit b1be3ba
Show file tree
Hide file tree
Showing 147 changed files with 7,445 additions and 691,030 deletions.
77 changes: 55 additions & 22 deletions solidity/contracts/lib/registry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,69 @@
// limitations under the License.
pragma solidity ^0.8.20;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {SmtLib} from "@iden3/contracts/lib/SmtLib.sol";
import {PoseidonUnit2L, PoseidonUnit3L} from "@iden3/contracts/lib/Poseidon.sol";
import {Commonlib} from "./common.sol";
import "hardhat/console.sol";

/// @title A sample on-chain implementation of an account mapping between Ethereum addresses and BabyJubjub public keys
uint256 constant MAX_SMT_DEPTH = 64;

/// @title A sample on-chain implementation of a KYC registry
/// @dev The registry uses a Sparse Merkle Tree to store the
/// Zeto accounts (Babyjubjub keys), so that transaction
/// submitters can generate proofs of membership for the
/// accounts in a privacy-preserving manner.
/// @author Kaleido, Inc.
contract Registry is Ownable {
mapping(address => uint256[2]) private publicKeys;
abstract contract Registry {
SmtLib.Data internal _publicKeysTree;
using SmtLib for SmtLib.Data;

event IdentityRegistered(uint256[2] publicKey);

error AlreadyRegistered(address addr);
error AlreadyRegistered(uint256[2]);

constructor() Ownable(msg.sender) {}
constructor() {
_publicKeysTree.initialize(MAX_SMT_DEPTH);
}

/// @dev Register a new public key for the calling Ethereum address
/// @param ethAddress The Ethereum address to register
/// @dev Register a new Zeto account
/// @param publicKey The public Babyjubjub key to register
function register(
address ethAddress,
uint256[2] memory publicKey
) public onlyOwner {
if (publicKeys[ethAddress][0] != 0 || publicKeys[ethAddress][1] != 0) {
revert AlreadyRegistered(ethAddress);
function _register(uint256[2] memory publicKey) internal {
uint256 nodeHash = _getIdentitiesLeafNodeHash(publicKey);
SmtLib.Node memory node = _publicKeysTree.getNode(nodeHash);
if (node.nodeType != SmtLib.NodeType.EMPTY) {
revert AlreadyRegistered(publicKey);
}
publicKeys[ethAddress] = publicKey;
_publicKeysTree.addLeaf(nodeHash, nodeHash);
emit IdentityRegistered(publicKey);
}

/// @dev returns whether the given public key is registered
/// @param publicKey The Babyjubjub public key to check
/// @return bool whether the given public key is included in the registry
function isRegistered(
uint256[2] memory publicKey
) public view returns (bool) {
uint256 nodeKey = _getIdentitiesLeafNodeKey(publicKey);
SmtLib.Node memory node = _publicKeysTree.getNode(nodeKey);
return node.nodeType != SmtLib.NodeType.EMPTY;
}

/// @dev Query the public key for a given Ethereum address
/// @param addr The Ethereum address to query
/// @return publicKey The public key for the given address
function getPublicKey(
address addr
) public view returns (uint256[2] memory publicKey) {
return publicKeys[addr];
function getIdentitiesRoot() public view returns (uint256) {
return _publicKeysTree.getRoot();
}

function _getIdentitiesLeafNodeHash(
uint256[2] memory publicKey
) internal pure returns (uint256) {
return PoseidonUnit2L.poseidon(publicKey);
}

function _getIdentitiesLeafNodeKey(
uint256[2] memory publicKey
) internal pure returns (uint256) {
uint256 nodeHash = PoseidonUnit2L.poseidon(publicKey);
uint256[3] memory params = [nodeHash, nodeHash, uint256(1)];
return PoseidonUnit3L.poseidon(params);
}
}
2 changes: 1 addition & 1 deletion solidity/contracts/lib/verifier_anon.sol
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ contract Groth16Verifier_Anon {
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[4] calldata _pubSignals) public view returns (bool) {
assembly {
function checkField(v) {
if iszero(lt(v, r)) {
if iszero(lt(v, q)) {
mstore(0, 0)
return(0, 0x20)
}
Expand Down
2 changes: 1 addition & 1 deletion solidity/contracts/lib/verifier_anon_enc.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ contract Groth16Verifier_AnonEnc {
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[7] calldata _pubSignals) public view returns (bool) {
assembly {
function checkField(v) {
if iszero(lt(v, r)) {
if iszero(lt(v, q)) {
mstore(0, 0)
return(0, 0x20)
}
Expand Down
22 changes: 11 additions & 11 deletions solidity/contracts/lib/verifier_anon_enc_nullifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ contract Groth16Verifier_AnonEncNullifier {
uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;


uint256 constant IC0x = 1132180179491441538738452273651946883461412832203743112811118844473379442028;
uint256 constant IC0y = 5390783026485963433523207720053244289587838204839623860596474298081543088585;
uint256 constant IC0x = 4568570755632788643394533153911199637393845847987729293464981238980340214701;
uint256 constant IC0y = 15128319276870423050909157626275409799208340368213199411576816383311184129195;

uint256 constant IC1x = 9479671548635182258434953602646699552143280379254562789430654117067623065154;
uint256 constant IC1y = 4513875910577591187417669244456597493215594361393034699197432847781635817944;
Expand All @@ -58,23 +58,23 @@ contract Groth16Verifier_AnonEncNullifier {
uint256 constant IC4x = 8045706817285648122335493621835686579889910526627484670178299244569350873337;
uint256 constant IC4y = 14703212748037329834343212171120394526601085625912333793516662767512116840031;

uint256 constant IC5x = 17557824284863559227631182945646272910505435334053056722808626217521393289128;
uint256 constant IC5y = 16307615047799173365519895850598694329138770383868524034358007080013608669085;
uint256 constant IC5x = 12289213637181054892282624823702301699573523320936692431552214952203040411410;
uint256 constant IC5y = 16455438753606683924006591564176938596063251993144033301210430323087499194482;

uint256 constant IC6x = 5415585987138244191813990034208825389253432804629600554497141813191469438492;
uint256 constant IC6y = 17755870055831490788712008393346742047905432267237159229825629073030204324527;
uint256 constant IC6x = 14303047076752096755721879884111868337074094864491631063458708071696569838284;
uint256 constant IC6y = 5911949370715042191384217137312039273992455050421022652157649670332806294542;

uint256 constant IC7x = 8677981225322796966854381897381189421248711504209293881165286829150524884164;
uint256 constant IC7y = 12816796872832476519349268616267285968398279397067849918595558738184610770874;
uint256 constant IC7x = 15841884851029529902011697322996410384031024289464678913047883869169350568208;
uint256 constant IC7y = 21520807340471527261351700326658280597567437458476043915147723227393128763810;

uint256 constant IC8x = 15740540576184573386354609430256689221677491143833514512062380094508866796269;
uint256 constant IC8y = 2340484610103666557078136629597674107756904443534921271417989072923691667449;

uint256 constant IC9x = 3726988392811514450533313378412430039053796082573590843909105394276411441536;
uint256 constant IC9y = 7347033125306979340056255923745117502907380131073815888051201665421460725544;

uint256 constant IC10x = 6619094542081504921297870625144079235409984730673107107299279901988791810356;
uint256 constant IC10y = 10549347737329626943980590291223696927409993218357923512265036708353601601743;
uint256 constant IC10x = 4371277742931522011055134703913097482787808225431324421232573076499659150767;
uint256 constant IC10y = 11516411764009653445050545510250621675398241508987088025760029722333645258716;


// Memory data
Expand All @@ -86,7 +86,7 @@ contract Groth16Verifier_AnonEncNullifier {
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[10] calldata _pubSignals) public view returns (bool) {
assembly {
function checkField(v) {
if iszero(lt(v, r)) {
if iszero(lt(v, q)) {
mstore(0, 0)
return(0, 0x20)
}
Expand Down
18 changes: 9 additions & 9 deletions solidity/contracts/lib/verifier_anon_nullifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,23 @@ contract Groth16Verifier_AnonNullifier {
uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;


uint256 constant IC0x = 7831194482890201907912813708954693484499937202778946556314791150355497052838;
uint256 constant IC0y = 17214367048578530654688121231520081865319465732684236954806278278486355045687;
uint256 constant IC0x = 5484373638915608486871020804166539520782909040345505335019959652136228862082;
uint256 constant IC0y = 16138277411069907720477228076440687453311854575356818231417756272310801661588;

uint256 constant IC1x = 657611904883114148980717005767820105315776575523580933462233892133390721686;
uint256 constant IC1y = 3690011531716382218745803104163270083920150842903711282044842015835943598950;

uint256 constant IC2x = 13247301284400305330080530887135251465329343308345822132754291671475418335661;
uint256 constant IC2y = 6878027108417593313264947615215679812389458074470859941986417727720332868266;

uint256 constant IC3x = 4393308877038816112044751113703161046884042023529143670482606285253407357318;
uint256 constant IC3y = 10861402902194208967056892862272521752290820790123718158389295013478034329376;
uint256 constant IC3x = 12122806794972194128212202542170444918567562037253242662728390689220136089417;
uint256 constant IC3y = 9885901744875470674355026551458972605308247499314156850898233682886130241050;

uint256 constant IC4x = 20567726645522252344842011251254616164566067019107949894642154009522868698126;
uint256 constant IC4y = 13058332362792856027058697122630683468388748189437006630731046361022666962675;
uint256 constant IC4x = 14497189114754949587485834175427788983830001040470111882678218991459557006481;
uint256 constant IC4y = 20830021231156123029529082857782030827870844726616623033674403796120242993032;

uint256 constant IC5x = 11519149396981714918708162608439765519813165816162067214356117934500928163278;
uint256 constant IC5y = 4896357293383145162082835572689841388496488666220683242957098534343617845489;
uint256 constant IC5x = 15185920369074896375657194229340428184369591270326493422044278017722304487940;
uint256 constant IC5y = 19431411716277310851795675028059565579151437630225658811235304233499648067653;

uint256 constant IC6x = 13045447923950887968308059891638935794209679677588887793771333234932902547512;
uint256 constant IC6y = 1960124371120172285328335936511540489447355418368729402128803121783956301995;
Expand All @@ -77,7 +77,7 @@ contract Groth16Verifier_AnonNullifier {
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[7] calldata _pubSignals) public view returns (bool) {
assembly {
function checkField(v) {
if iszero(lt(v, r)) {
if iszero(lt(v, q)) {
mstore(0, 0)
return(0, 0x20)
}
Expand Down
Loading

0 comments on commit b1be3ba

Please sign in to comment.