mirror of
https://github.com/zkemail/zk-email-verify.git
synced 2026-01-08 21:18:09 -05:00
halfway through contract rewrite to support proxies
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -53,8 +53,6 @@ cache/
|
||||
test.log
|
||||
src/contracts/out/
|
||||
.next
|
||||
*Wallet*
|
||||
*wallet*
|
||||
node_modules.nosync
|
||||
|
||||
# Files that never should be committed, but can be obtained by asking Aayush or generating them yourself
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"react-use": "^17.3.2",
|
||||
"readline": "^1.3.0",
|
||||
"serve": "^14.0.1",
|
||||
"snarkjs": "git+https://github.com/vb7401/snarkjs.git#24981febe8826b6ab76ae4d76cf7f9142919d2b8",
|
||||
"snarkjs": "latest",
|
||||
"sshpk": "^1.17.0",
|
||||
"styled-components": "^5.3.5",
|
||||
"ts-node": "^10.9.1",
|
||||
|
||||
@@ -58,3 +58,7 @@ Maybe fullnode is on [old geth](https://github.com/ethereum/go-ethereum/issues/2
|
||||
```
|
||||
forge script script/Deploy.s.sol:Deploy -vvvv --rpc-url $RPC_URL --broadcast --slow
|
||||
```
|
||||
|
||||
### Versions
|
||||
|
||||
10a840db7305d9cdcd1fa56aee88ec77db86a562 is the last stable wallet version before breaking changes to add on-chain anonymity.
|
||||
|
||||
48
src/contracts/script/DeployWallet.s.sol
Normal file
48
src/contracts/script/DeployWallet.s.sol
Normal file
@@ -0,0 +1,48 @@
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "forge-std/Test.sol";
|
||||
import "forge-std/console.sol";
|
||||
import "forge-std/Script.sol";
|
||||
import "../src/WalletEmailHandler.sol";
|
||||
import "../src/WalletEmailHandlerLogic.sol";
|
||||
import "../src/WalletEmailHandlerProxy.sol";
|
||||
import "../src/StringUtils.sol";
|
||||
import "../src/Groth16VerifierWalletAnon.sol";
|
||||
import "../src/TestERC20.sol";
|
||||
|
||||
contract Deploy is Script, Test {
|
||||
function getPrivateKey() internal returns (uint256) {
|
||||
try vm.envUint("PRIVATE_KEY") returns (uint256 privateKey) {
|
||||
return privateKey;
|
||||
} catch {
|
||||
// This is the anvil default exposed secret key
|
||||
return 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80;
|
||||
}
|
||||
}
|
||||
|
||||
// function oldRunDeployNonproxy() public {
|
||||
// uint256 sk = getPrivateKey();
|
||||
// vm.startBroadcast(sk);
|
||||
// Verifier proofVerifier = new Verifier();
|
||||
// MailServer mailServer = new MailServer();
|
||||
// TestEmailToken erc20 = new TestEmailToken(5000);
|
||||
|
||||
// VerifiedWalletEmail testVerifier = new VerifiedWalletEmail(proofVerifier, mailServer, erc20);
|
||||
// vm.stopBroadcast();
|
||||
// }
|
||||
|
||||
function run() public {
|
||||
uint256 sk = getPrivateKey();
|
||||
vm.startBroadcast(sk);
|
||||
Verifier proofVerifier = new Verifier();
|
||||
MailServer mailServer = new MailServer();
|
||||
TokenRegistry tokenRegistry = new TokenRegistry();
|
||||
TestEmailToken erc20 = new TestEmailToken(5000);
|
||||
WalletEmailHandlerLogic logic = new WalletEmailHandlerLogic();
|
||||
address admin = 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D; // HEVM Cheat Code Address
|
||||
bytes memory initData =
|
||||
abi.encodeWithSignature("initialize(Verifier,MailServer,TestEmailToken,TokenRegistry)", proofVerifier, mailServer, erc20, tokenRegistry);
|
||||
WalletEmailHandlerProxy proxy = new WalletEmailHandlerProxy(address(logic), admin, initData);
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
}
|
||||
29
src/contracts/src/AutoApproveWallet.sol
Normal file
29
src/contracts/src/AutoApproveWallet.sol
Normal file
@@ -0,0 +1,29 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
|
||||
|
||||
contract AutoApproveWallet is Ownable, Initializable {
|
||||
uint256 constant MAX_UINT256 = type(uint256).max;
|
||||
uint256 public constant version = 1;
|
||||
mapping(string => address) public customVerifiers;
|
||||
|
||||
constructor() {}
|
||||
|
||||
function initialize(address tokenAddress, address approver) public onlyOwner initializer {
|
||||
IERC20 token = IERC20(tokenAddress);
|
||||
token.approve(approver, MAX_UINT256);
|
||||
}
|
||||
|
||||
// These are here as placeholders, but eventually can gate withdraws from the account
|
||||
function setVerifier(string memory command, address verifier) public onlyOwner {
|
||||
customVerifiers[command] = verifier;
|
||||
}
|
||||
|
||||
// These are here as placeholders, but eventually can gate withdraws from the account
|
||||
function getVerifier(string memory command) public view returns (address) {
|
||||
return customVerifiers[command];
|
||||
}
|
||||
}
|
||||
@@ -1,425 +0,0 @@
|
||||
//
|
||||
// Copyright 2017 Christian Reitwiessner
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// 2019 OKIMS
|
||||
// ported to solidity 0.6
|
||||
// fixed linter warnings
|
||||
// added requiere error messages
|
||||
//
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.6.11;
|
||||
|
||||
library Pairing {
|
||||
struct G1Point {
|
||||
uint256 X;
|
||||
uint256 Y;
|
||||
}
|
||||
// Encoding of field elements is: X[0] * z + X[1]
|
||||
|
||||
struct G2Point {
|
||||
uint256[2] X;
|
||||
uint256[2] Y;
|
||||
}
|
||||
|
||||
/// @return the generator of G1
|
||||
function P1() internal pure returns (G1Point memory) {
|
||||
return G1Point(1, 2);
|
||||
}
|
||||
|
||||
/// @return the generator of G2
|
||||
function P2() internal pure returns (G2Point memory) {
|
||||
// Original code point
|
||||
return
|
||||
G2Point(
|
||||
[11559732032986387107991004021392285783925812861821192530917403151452391805634, 10857046999023057135944570762232829481370756359578518086990519993285655852781],
|
||||
[4082367875863433681332203403145435568316851327593401208105741076214120093531, 8495653923123431417604973247489272438418190587263600148770280649306958101930]
|
||||
);
|
||||
|
||||
/*
|
||||
// Changed by Jordi point
|
||||
return G2Point(
|
||||
[10857046999023057135944570762232829481370756359578518086990519993285655852781,
|
||||
11559732032986387107991004021392285783925812861821192530917403151452391805634],
|
||||
[8495653923123431417604973247489272438418190587263600148770280649306958101930,
|
||||
4082367875863433681332203403145435568316851327593401208105741076214120093531]
|
||||
);*/
|
||||
}
|
||||
|
||||
/// @return r the negation of p, i.e. p.addition(p.negate()) should be zero.
|
||||
function negate(G1Point memory p) internal pure returns (G1Point memory r) {
|
||||
// The prime q in the base field F_q for G1
|
||||
uint256 q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||
if (p.X == 0 && p.Y == 0) return G1Point(0, 0);
|
||||
return G1Point(p.X, q - (p.Y % q));
|
||||
}
|
||||
|
||||
/// @return r the sum of two points of G1
|
||||
function addition(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) {
|
||||
uint256[4] memory input;
|
||||
input[0] = p1.X;
|
||||
input[1] = p1.Y;
|
||||
input[2] = p2.X;
|
||||
input[3] = p2.Y;
|
||||
bool success;
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly {
|
||||
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 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, uint256 s) internal view returns (G1Point memory r) {
|
||||
uint256[3] memory input;
|
||||
input[0] = p.X;
|
||||
input[1] = p.Y;
|
||||
input[2] = s;
|
||||
bool success;
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly {
|
||||
success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60)
|
||||
// Use "invalid" to make gas estimation work
|
||||
switch success
|
||||
case 0 {
|
||||
invalid()
|
||||
}
|
||||
}
|
||||
require(success, "pairing-mul-failed");
|
||||
}
|
||||
|
||||
/// @return the result of computing the pairing check
|
||||
/// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1
|
||||
/// For example pairing([P1(), P1().negate()], [P2(), P2()]) should
|
||||
/// return true.
|
||||
function pairing(G1Point[] memory p1, G2Point[] memory p2) internal view returns (bool) {
|
||||
require(p1.length == p2.length, "pairing-lengths-failed");
|
||||
uint256 elements = p1.length;
|
||||
uint256 inputSize = elements * 6;
|
||||
uint256[] memory input = new uint[](inputSize);
|
||||
for (uint256 i = 0; i < elements; i++) {
|
||||
input[i * 6 + 0] = p1[i].X;
|
||||
input[i * 6 + 1] = p1[i].Y;
|
||||
input[i * 6 + 2] = p2[i].X[0];
|
||||
input[i * 6 + 3] = p2[i].X[1];
|
||||
input[i * 6 + 4] = p2[i].Y[0];
|
||||
input[i * 6 + 5] = p2[i].Y[1];
|
||||
}
|
||||
uint256[1] memory out;
|
||||
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)
|
||||
// Use "invalid" to make gas estimation work
|
||||
switch success
|
||||
case 0 {
|
||||
invalid()
|
||||
}
|
||||
}
|
||||
require(success, "pairing-opcode-failed");
|
||||
return out[0] != 0;
|
||||
}
|
||||
|
||||
/// Convenience method for a pairing check for two pairs.
|
||||
function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2) internal view returns (bool) {
|
||||
G1Point[] memory p1 = new G1Point[](2);
|
||||
G2Point[] memory p2 = new G2Point[](2);
|
||||
p1[0] = a1;
|
||||
p1[1] = b1;
|
||||
p2[0] = a2;
|
||||
p2[1] = b2;
|
||||
return pairing(p1, p2);
|
||||
}
|
||||
|
||||
/// Convenience method for a pairing check for three pairs.
|
||||
function pairingProd3(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2, G1Point memory c1, G2Point memory c2) internal view returns (bool) {
|
||||
G1Point[] memory p1 = new G1Point[](3);
|
||||
G2Point[] memory p2 = new G2Point[](3);
|
||||
p1[0] = a1;
|
||||
p1[1] = b1;
|
||||
p1[2] = c1;
|
||||
p2[0] = a2;
|
||||
p2[1] = b2;
|
||||
p2[2] = c2;
|
||||
return pairing(p1, p2);
|
||||
}
|
||||
|
||||
/// Convenience method for a pairing check for four pairs.
|
||||
function pairingProd4(
|
||||
G1Point memory a1,
|
||||
G2Point memory a2,
|
||||
G1Point memory b1,
|
||||
G2Point memory b2,
|
||||
G1Point memory c1,
|
||||
G2Point memory c2,
|
||||
G1Point memory d1,
|
||||
G2Point memory d2
|
||||
) internal view returns (bool) {
|
||||
G1Point[] memory p1 = new G1Point[](4);
|
||||
G2Point[] memory p2 = new G2Point[](4);
|
||||
p1[0] = a1;
|
||||
p1[1] = b1;
|
||||
p1[2] = c1;
|
||||
p1[3] = d1;
|
||||
p2[0] = a2;
|
||||
p2[1] = b2;
|
||||
p2[2] = c2;
|
||||
p2[3] = d2;
|
||||
return pairing(p1, p2);
|
||||
}
|
||||
}
|
||||
|
||||
contract Verifier {
|
||||
using Pairing for *;
|
||||
|
||||
struct VerifyingKey {
|
||||
Pairing.G1Point alfa1;
|
||||
Pairing.G2Point beta2;
|
||||
Pairing.G2Point gamma2;
|
||||
Pairing.G2Point delta2;
|
||||
Pairing.G1Point[] IC;
|
||||
}
|
||||
|
||||
struct Proof {
|
||||
Pairing.G1Point A;
|
||||
Pairing.G2Point B;
|
||||
Pairing.G1Point C;
|
||||
}
|
||||
|
||||
function verifyingKey() internal pure returns (VerifyingKey memory vk) {
|
||||
vk.alfa1 = Pairing.G1Point(
|
||||
20491192805390485299153009773594534940189261866228447918068658471970481763042,
|
||||
9383485363053290200918347156157836566562967994039712273449902621266178545958
|
||||
);
|
||||
|
||||
vk.beta2 = Pairing.G2Point(
|
||||
[4252822878758300859123897981450591353533073413197771768651442665752259397132, 6375614351688725206403948262868962793625744043794305715222011528459656738731],
|
||||
[21847035105528745403288232691147584728191162732299865338377159692350059136679, 10505242626370262277552901082094356697409835680220590971873171140371331206856]
|
||||
);
|
||||
vk.gamma2 = Pairing.G2Point(
|
||||
[11559732032986387107991004021392285783925812861821192530917403151452391805634, 10857046999023057135944570762232829481370756359578518086990519993285655852781],
|
||||
[4082367875863433681332203403145435568316851327593401208105741076214120093531, 8495653923123431417604973247489272438418190587263600148770280649306958101930]
|
||||
);
|
||||
vk.delta2 = Pairing.G2Point(
|
||||
[1513129022268504209358763521777110646559191312944535983790343685540452445612, 12195000584114682213316512369139242650405673197296308277565313794080256232701],
|
||||
[8360772797757285669693588223224368324652217960280535125476432579464480898413, 520894096459672819696448581165649200639580943346471218758886059131097679200]
|
||||
);
|
||||
vk.IC = new Pairing.G1Point[](35);
|
||||
|
||||
vk.IC[0] = Pairing.G1Point(
|
||||
11537328283226768393732428330956073110918624081922605220849994462257164716154,
|
||||
21836950190585457727786541794875874204342457073442279657287670575335295859939
|
||||
);
|
||||
|
||||
vk.IC[1] = Pairing.G1Point(
|
||||
2646307150509379456483324388204599416197823343744573056776580441757968778128,
|
||||
14368370831419521837815784599306984151624772530159432470308283448431330483438
|
||||
);
|
||||
|
||||
vk.IC[2] = Pairing.G1Point(
|
||||
16971624750468472956383457363672950966338870541072731251437414691217134411120,
|
||||
8171770470043873321771537156021753591829282779422875691859226771666334115210
|
||||
);
|
||||
|
||||
vk.IC[3] = Pairing.G1Point(
|
||||
17003248154885997024042723500051841853373913724967509464380365353802575974728,
|
||||
7268687626523176370339202918269959082095447462862347953587350206552205642559
|
||||
);
|
||||
|
||||
vk.IC[4] = Pairing.G1Point(
|
||||
9147424234223179035895482077044817222415554273556867838268712944193520459125,
|
||||
21578705994822322813698189503736815299185497639660343771670537250469027755948
|
||||
);
|
||||
|
||||
vk.IC[5] = Pairing.G1Point(
|
||||
16948417333412259029407181850226843375508933350680650127572170476630717282234,
|
||||
9665563179883720332817127456522837835577284997912132910805194791161889398512
|
||||
);
|
||||
|
||||
vk.IC[6] = Pairing.G1Point(
|
||||
9319994583370423638602672994382300950312503535351144768052894387193551537459,
|
||||
19171031111811822064434269353657536224339902296340766041252096715670766153578
|
||||
);
|
||||
|
||||
vk.IC[7] = Pairing.G1Point(
|
||||
9371603635986601434942264619807195148477116766259006354709633771674992552724,
|
||||
11103293940652841271958831421967970005702672122254116205870466468493278826958
|
||||
);
|
||||
|
||||
vk.IC[8] = Pairing.G1Point(
|
||||
3561757143230234005632456376532802121489770329687277876867422136368222736134,
|
||||
11734814901687269585580202167146602218102049962630061844516173384912435005151
|
||||
);
|
||||
|
||||
vk.IC[9] = Pairing.G1Point(
|
||||
16676238706569507337573176601181670688707264606170712075388734731572549373015,
|
||||
11158592034910239776632780480510406146251140896522712858892689171974748083747
|
||||
);
|
||||
|
||||
vk.IC[10] = Pairing.G1Point(
|
||||
9822993420542467873912218347366938030193407618831916003032667186678059114349,
|
||||
6863223533781083402167797754430699108902384970089129346113470095574463296737
|
||||
);
|
||||
|
||||
vk.IC[11] = Pairing.G1Point(
|
||||
4866721301322510775531094866459672146070982818674092273969310571220291630556,
|
||||
9846640210996171367705574856419053631553093780701851221089070591862473684456
|
||||
);
|
||||
|
||||
vk.IC[12] = Pairing.G1Point(
|
||||
11121919417977708038028243712145798541888876824913262431306415256568966652024,
|
||||
12609770408698645498350514024296607224475353273713173177251900216074217014850
|
||||
);
|
||||
|
||||
vk.IC[13] = Pairing.G1Point(
|
||||
14840050373651993593383756529988239317958775236310376879012996717055845150487,
|
||||
16683016138329247649135414505803188190565946292769946693147365719646757192352
|
||||
);
|
||||
|
||||
vk.IC[14] = Pairing.G1Point(
|
||||
12331471170495648864015185687161748641193043583582691780623236535573811426959,
|
||||
11714531956225516771424892308789701085922077646343882797070434158311220922011
|
||||
);
|
||||
|
||||
vk.IC[15] = Pairing.G1Point(
|
||||
20857366342421630154576707922479406842052250461154457549932210545889187427626,
|
||||
19731871495034015170236307573440414758884960293847791130561428843792753429086
|
||||
);
|
||||
|
||||
vk.IC[16] = Pairing.G1Point(
|
||||
16209406523379999199236029863462575441846948663847567298395841886469797214082,
|
||||
20718988335004414356172240953954108902387108184538803896124546491420460740169
|
||||
);
|
||||
|
||||
vk.IC[17] = Pairing.G1Point(
|
||||
8397179853577453858892608876746062307226175687475102639712031393841003387919,
|
||||
7154528864876839718549215559715861424372452521581853695056564308745992761672
|
||||
);
|
||||
|
||||
vk.IC[18] = Pairing.G1Point(
|
||||
15000425614899689626185464253582174491572354417903507356426258449407132127046,
|
||||
13602373364472815067534003393627538602411204908660744540946955553406039633451
|
||||
);
|
||||
|
||||
vk.IC[19] = Pairing.G1Point(
|
||||
5545252939208963791309142258539499940294193526436021787091019273144246885261,
|
||||
2675833647327088808677716501235324721140769279456271927816550777395489852251
|
||||
);
|
||||
|
||||
vk.IC[20] = Pairing.G1Point(
|
||||
2537047834074478023060297384888724410218136939149736151242515713484635642789,
|
||||
3193147508270124393755481767836877808561856886429215905854576456538260642120
|
||||
);
|
||||
|
||||
vk.IC[21] = Pairing.G1Point(
|
||||
13819984179784763421503658502014430958296359352165019537755065452645355466085,
|
||||
18994178127386658997162783196808799873728043389545801736093808610346271161658
|
||||
);
|
||||
|
||||
vk.IC[22] = Pairing.G1Point(
|
||||
6589370869708283514329318539826110923064805897289825414235274269171407140900,
|
||||
9625792054986455984618262255946246252268480571067521104852530192902386719593
|
||||
);
|
||||
|
||||
vk.IC[23] = Pairing.G1Point(
|
||||
14453270681522455527144160729543145025587040770258214008741757192612444737673,
|
||||
20143300120523312381709649823189168032874279267240134119356286009260298185475
|
||||
);
|
||||
|
||||
vk.IC[24] = Pairing.G1Point(
|
||||
8846979524751473322994268234754538401482894217522349506066299416316984717260,
|
||||
14238278950875447301003974303300008365515832894025960431754069250458716988985
|
||||
);
|
||||
|
||||
vk.IC[25] = Pairing.G1Point(
|
||||
1407828395464361821905309927863167268883721160860555328581866885124611897528,
|
||||
15987854649208373291691713233856831065610123809032682196292981616658494776987
|
||||
);
|
||||
|
||||
vk.IC[26] = Pairing.G1Point(
|
||||
20657483817998070093869648777824400547660398552294774144027193285451239619382,
|
||||
21826613460615350291777797645121185151869814459512699120411019581958075991542
|
||||
);
|
||||
|
||||
vk.IC[27] = Pairing.G1Point(
|
||||
20624928617240774729161710928323453036077574938263627000040473137006018415415,
|
||||
5131454817008842892320970265930200727731593782574755474310860262365965990664
|
||||
);
|
||||
|
||||
vk.IC[28] = Pairing.G1Point(
|
||||
13895249990164764352618348094492621630575085672410127797817030490897283284460,
|
||||
11796920177436300262655702063092510613755939821586920802170520825907606184557
|
||||
);
|
||||
|
||||
vk.IC[29] = Pairing.G1Point(
|
||||
3135811994020780743324086008729747183900335277491189104250977002197575809365,
|
||||
19637480211624980857501152516366188197895066151113910763057713919944678029866
|
||||
);
|
||||
|
||||
vk.IC[30] = Pairing.G1Point(
|
||||
606103022421566187118689786319065266252504972683102249226453076393842587324,
|
||||
10274587862652629723961486759561149321143114208996217550785138347396636546119
|
||||
);
|
||||
|
||||
vk.IC[31] = Pairing.G1Point(
|
||||
17876636758905622230688544604495142065478803287376541138330575508029036910921,
|
||||
845514606482911379811389987862147832754587150586772012493153117259870748818
|
||||
);
|
||||
|
||||
vk.IC[32] = Pairing.G1Point(
|
||||
3055934057788309375612017678081361462642124203699024466299800387864964176162,
|
||||
6215463225683464296816602777995066291454589608119271052091343612576965188139
|
||||
);
|
||||
|
||||
vk.IC[33] = Pairing.G1Point(
|
||||
15655816926053512024400351678850471800118254812943223488624167720306406940886,
|
||||
1318451441938966067851976459607266837893918068783070216555767331693196884126
|
||||
);
|
||||
|
||||
vk.IC[34] = Pairing.G1Point(
|
||||
13942491345765259320815758221010163510633256522676138655574537850419728932090,
|
||||
2449428677603436766608016448595332101485961035234011384134049218692804513154
|
||||
);
|
||||
}
|
||||
|
||||
function verify(uint256[] memory input, Proof memory proof) public view returns (uint256) {
|
||||
uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||
VerifyingKey memory vk = verifyingKey();
|
||||
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);
|
||||
for (uint256 i = 0; i < input.length; i++) {
|
||||
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(Pairing.negate(proof.A), proof.B, vk.alfa1, vk.beta2, vk_x, vk.gamma2, proof.C, vk.delta2)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @return r bool true if proof is valid
|
||||
function verifyProof(uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c, uint256[34] 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]);
|
||||
uint256[] memory inputValues = new uint[](input.length);
|
||||
for (uint256 i = 0; i < input.length; i++) {
|
||||
inputValues[i] = input[i];
|
||||
}
|
||||
if (verify(inputValues, proof) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
423
src/contracts/src/Groth16VerifierWalletAnon.sol
Normal file
423
src/contracts/src/Groth16VerifierWalletAnon.sol
Normal file
@@ -0,0 +1,423 @@
|
||||
//
|
||||
// Copyright 2017 Christian Reitwiessner
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// 2019 OKIMS
|
||||
// ported to solidity 0.6
|
||||
// fixed linter warnings
|
||||
// added requiere error messages
|
||||
//
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.6.11;
|
||||
|
||||
library Pairing {
|
||||
struct G1Point {
|
||||
uint256 X;
|
||||
uint256 Y;
|
||||
}
|
||||
// Encoding of field elements is: X[0] * z + X[1]
|
||||
|
||||
struct G2Point {
|
||||
uint256[2] X;
|
||||
uint256[2] Y;
|
||||
}
|
||||
/// @return the generator of G1
|
||||
|
||||
function P1() internal pure returns (G1Point memory) {
|
||||
return G1Point(1, 2);
|
||||
}
|
||||
/// @return the generator of G2
|
||||
|
||||
function P2() internal pure returns (G2Point memory) {
|
||||
// Original code point
|
||||
return G2Point(
|
||||
[
|
||||
11559732032986387107991004021392285783925812861821192530917403151452391805634,
|
||||
10857046999023057135944570762232829481370756359578518086990519993285655852781
|
||||
],
|
||||
[
|
||||
4082367875863433681332203403145435568316851327593401208105741076214120093531,
|
||||
8495653923123431417604973247489272438418190587263600148770280649306958101930
|
||||
]
|
||||
);
|
||||
|
||||
/*
|
||||
// Changed by Jordi point
|
||||
return G2Point(
|
||||
[10857046999023057135944570762232829481370756359578518086990519993285655852781,
|
||||
11559732032986387107991004021392285783925812861821192530917403151452391805634],
|
||||
[8495653923123431417604973247489272438418190587263600148770280649306958101930,
|
||||
4082367875863433681332203403145435568316851327593401208105741076214120093531]
|
||||
);*/
|
||||
}
|
||||
/// @return r the negation of p, i.e. p.addition(p.negate()) should be zero.
|
||||
|
||||
function negate(G1Point memory p) internal pure returns (G1Point memory r) {
|
||||
// The prime q in the base field F_q for G1
|
||||
uint256 q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||
if (p.X == 0 && p.Y == 0) {
|
||||
return G1Point(0, 0);
|
||||
}
|
||||
return G1Point(p.X, q - (p.Y % q));
|
||||
}
|
||||
/// @return r the sum of two points of G1
|
||||
|
||||
function addition(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) {
|
||||
uint256[4] memory input;
|
||||
input[0] = p1.X;
|
||||
input[1] = p1.Y;
|
||||
input[2] = p2.X;
|
||||
input[3] = p2.Y;
|
||||
bool success;
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly {
|
||||
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 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, uint256 s) internal view returns (G1Point memory r) {
|
||||
uint256[3] memory input;
|
||||
input[0] = p.X;
|
||||
input[1] = p.Y;
|
||||
input[2] = s;
|
||||
bool success;
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly {
|
||||
success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60)
|
||||
// Use "invalid" to make gas estimation work
|
||||
switch success
|
||||
case 0 { invalid() }
|
||||
}
|
||||
require(success, "pairing-mul-failed");
|
||||
}
|
||||
/// @return the result of computing the pairing check
|
||||
/// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1
|
||||
/// For example pairing([P1(), P1().negate()], [P2(), P2()]) should
|
||||
/// return true.
|
||||
|
||||
function pairing(G1Point[] memory p1, G2Point[] memory p2) internal view returns (bool) {
|
||||
require(p1.length == p2.length, "pairing-lengths-failed");
|
||||
uint256 elements = p1.length;
|
||||
uint256 inputSize = elements * 6;
|
||||
uint256[] memory input = new uint[](inputSize);
|
||||
for (uint256 i = 0; i < elements; i++) {
|
||||
input[i * 6 + 0] = p1[i].X;
|
||||
input[i * 6 + 1] = p1[i].Y;
|
||||
input[i * 6 + 2] = p2[i].X[0];
|
||||
input[i * 6 + 3] = p2[i].X[1];
|
||||
input[i * 6 + 4] = p2[i].Y[0];
|
||||
input[i * 6 + 5] = p2[i].Y[1];
|
||||
}
|
||||
uint256[1] memory out;
|
||||
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)
|
||||
// Use "invalid" to make gas estimation work
|
||||
switch success
|
||||
case 0 { invalid() }
|
||||
}
|
||||
require(success, "pairing-opcode-failed");
|
||||
return out[0] != 0;
|
||||
}
|
||||
/// Convenience method for a pairing check for two pairs.
|
||||
|
||||
function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
G1Point[] memory p1 = new G1Point[](2);
|
||||
G2Point[] memory p2 = new G2Point[](2);
|
||||
p1[0] = a1;
|
||||
p1[1] = b1;
|
||||
p2[0] = a2;
|
||||
p2[1] = b2;
|
||||
return pairing(p1, p2);
|
||||
}
|
||||
/// Convenience method for a pairing check for three pairs.
|
||||
|
||||
function pairingProd3(
|
||||
G1Point memory a1,
|
||||
G2Point memory a2,
|
||||
G1Point memory b1,
|
||||
G2Point memory b2,
|
||||
G1Point memory c1,
|
||||
G2Point memory c2
|
||||
) internal view returns (bool) {
|
||||
G1Point[] memory p1 = new G1Point[](3);
|
||||
G2Point[] memory p2 = new G2Point[](3);
|
||||
p1[0] = a1;
|
||||
p1[1] = b1;
|
||||
p1[2] = c1;
|
||||
p2[0] = a2;
|
||||
p2[1] = b2;
|
||||
p2[2] = c2;
|
||||
return pairing(p1, p2);
|
||||
}
|
||||
/// Convenience method for a pairing check for four pairs.
|
||||
|
||||
function pairingProd4(
|
||||
G1Point memory a1,
|
||||
G2Point memory a2,
|
||||
G1Point memory b1,
|
||||
G2Point memory b2,
|
||||
G1Point memory c1,
|
||||
G2Point memory c2,
|
||||
G1Point memory d1,
|
||||
G2Point memory d2
|
||||
) internal view returns (bool) {
|
||||
G1Point[] memory p1 = new G1Point[](4);
|
||||
G2Point[] memory p2 = new G2Point[](4);
|
||||
p1[0] = a1;
|
||||
p1[1] = b1;
|
||||
p1[2] = c1;
|
||||
p1[3] = d1;
|
||||
p2[0] = a2;
|
||||
p2[1] = b2;
|
||||
p2[2] = c2;
|
||||
p2[3] = d2;
|
||||
return pairing(p1, p2);
|
||||
}
|
||||
}
|
||||
|
||||
contract Verifier {
|
||||
using Pairing for *;
|
||||
|
||||
struct VerifyingKey {
|
||||
Pairing.G1Point alfa1;
|
||||
Pairing.G2Point beta2;
|
||||
Pairing.G2Point gamma2;
|
||||
Pairing.G2Point delta2;
|
||||
Pairing.G1Point[] IC;
|
||||
}
|
||||
|
||||
struct Proof {
|
||||
Pairing.G1Point A;
|
||||
Pairing.G2Point B;
|
||||
Pairing.G1Point C;
|
||||
}
|
||||
|
||||
function verifyingKey() internal pure returns (VerifyingKey memory vk) {
|
||||
vk.alfa1 = Pairing.G1Point(
|
||||
20491192805390485299153009773594534940189261866228447918068658471970481763042,
|
||||
9383485363053290200918347156157836566562967994039712273449902621266178545958
|
||||
);
|
||||
|
||||
vk.beta2 = Pairing.G2Point(
|
||||
[
|
||||
4252822878758300859123897981450591353533073413197771768651442665752259397132,
|
||||
6375614351688725206403948262868962793625744043794305715222011528459656738731
|
||||
],
|
||||
[
|
||||
21847035105528745403288232691147584728191162732299865338377159692350059136679,
|
||||
10505242626370262277552901082094356697409835680220590971873171140371331206856
|
||||
]
|
||||
);
|
||||
vk.gamma2 = Pairing.G2Point(
|
||||
[
|
||||
11559732032986387107991004021392285783925812861821192530917403151452391805634,
|
||||
10857046999023057135944570762232829481370756359578518086990519993285655852781
|
||||
],
|
||||
[
|
||||
4082367875863433681332203403145435568316851327593401208105741076214120093531,
|
||||
8495653923123431417604973247489272438418190587263600148770280649306958101930
|
||||
]
|
||||
);
|
||||
vk.delta2 = Pairing.G2Point(
|
||||
[
|
||||
11290853248376174984358904800549027724052843605043786792250961933582559784416,
|
||||
19088798087869078895098454041957301282545108040983567066634161706546841377180
|
||||
],
|
||||
[
|
||||
2613549324505590928634725081465721100391648691301061977245024195885201175000,
|
||||
16900711717488710996527635174082863643624363550916773862600170691920516587179
|
||||
]
|
||||
);
|
||||
vk.IC = new Pairing.G1Point[](27);
|
||||
|
||||
vk.IC[0] = Pairing.G1Point(
|
||||
19979818312650249281018016981052950968675990952627346907483591409385889371334,
|
||||
14675330954786426353321242780661450755204240791125907513954615409547191814285
|
||||
);
|
||||
|
||||
vk.IC[1] = Pairing.G1Point(
|
||||
5829003113921117432206175983572010026961474373472855647935001341465808816339,
|
||||
19782944755006085617526906642429180306138946798837355469130386866160911601011
|
||||
);
|
||||
|
||||
vk.IC[2] = Pairing.G1Point(
|
||||
12588535573679309327992671270902604443900873491408310753588166121975917769023,
|
||||
8219477726636990585687042181227262680748408234115867638626693699807529624430
|
||||
);
|
||||
|
||||
vk.IC[3] = Pairing.G1Point(
|
||||
16419566697611418137868233429812774560970274989774297684287789963725247230594,
|
||||
16739285080804767717417083389880687834670337497889709161148870804899232453933
|
||||
);
|
||||
|
||||
vk.IC[4] = Pairing.G1Point(
|
||||
16265380280881177170721470304996523746928776552716196405150646742099377669931,
|
||||
19638885469076190510322825514105945378813865877644439953162824321505237392070
|
||||
);
|
||||
|
||||
vk.IC[5] = Pairing.G1Point(
|
||||
6796494020533467002863143139458992782913216971691648483712266994414215291949,
|
||||
9707665463330159969812119514363493770851005080885912428651081561719521094933
|
||||
);
|
||||
|
||||
vk.IC[6] = Pairing.G1Point(
|
||||
21544862858428587736887827977241946178420087708877339811347489861404200945678,
|
||||
2500513994651656141840810268606328266633030698182038222554168868998950911851
|
||||
);
|
||||
|
||||
vk.IC[7] = Pairing.G1Point(
|
||||
1230711131658930327648030092718986304477079060235946436492012186862476441198,
|
||||
2924327811705850943352392316547023661300393599290009775476572413301695659477
|
||||
);
|
||||
|
||||
vk.IC[8] = Pairing.G1Point(
|
||||
4593824226566234819232211820162561709239122795404699806154965441179806789185,
|
||||
9489624936684684917819113770049200619128274295587594808702038943690694641556
|
||||
);
|
||||
|
||||
vk.IC[9] = Pairing.G1Point(
|
||||
2920165003775211935037985895884368960628002338669905002705242721889293661500,
|
||||
19325075961718529602218214575556958381871801093875004623824789089894826295257
|
||||
);
|
||||
|
||||
vk.IC[10] = Pairing.G1Point(
|
||||
798816348892537467071912883235430376248661781038228218104756604377494380304,
|
||||
11781557459672808558858136202683204507290115613628432130488538278285238135010
|
||||
);
|
||||
|
||||
vk.IC[11] = Pairing.G1Point(
|
||||
12364547354186510362274174544601523892849537922961743171051730704612856215491,
|
||||
1940501514916509359250239441208143117730918007390438148791819014454436111300
|
||||
);
|
||||
|
||||
vk.IC[12] = Pairing.G1Point(
|
||||
19374594578181611716973001664490855487600832530676195301956619061624976816219,
|
||||
14177536357346623944961788153399669848956517572484804092424908023324631652114
|
||||
);
|
||||
|
||||
vk.IC[13] = Pairing.G1Point(
|
||||
13278036469043701173415661010457809115535144694893393869550044351530605334767,
|
||||
17412800250990974973260595224521507568391191455832434113883056179425663097823
|
||||
);
|
||||
|
||||
vk.IC[14] = Pairing.G1Point(
|
||||
9915947382759385783486901323053324677105393406725118625368034668340091270389,
|
||||
16486030947539867411575826079702988059459377097615987701025504390895170318699
|
||||
);
|
||||
|
||||
vk.IC[15] = Pairing.G1Point(
|
||||
10032727001807914582863553934823535175601796608073836535872731307698533085785,
|
||||
3081085031123792073612063961064472989961107449944557192691595148458951458227
|
||||
);
|
||||
|
||||
vk.IC[16] = Pairing.G1Point(
|
||||
12861664141229362488575301280006958327960741616945360590354230646571221543276,
|
||||
9465078685742145838883804510121221671872710132970132842647710792990557843321
|
||||
);
|
||||
|
||||
vk.IC[17] = Pairing.G1Point(
|
||||
5005765047541457738526606112299880823121166660296178632472432158059866023590,
|
||||
800508591566316812025121111977116353798488540486465046929671355188348296221
|
||||
);
|
||||
|
||||
vk.IC[18] = Pairing.G1Point(
|
||||
8233737885441865638780817092959136454488041028245340573670741092114576019836,
|
||||
1905649541669160515152119016722479564120799606865265758708514046334911361937
|
||||
);
|
||||
|
||||
vk.IC[19] = Pairing.G1Point(
|
||||
18783017403141463325045721611662222497187068636914351056270968332721736892315,
|
||||
8662142271865866054873642500672292664959895899040501045955952275645237184560
|
||||
);
|
||||
|
||||
vk.IC[20] = Pairing.G1Point(
|
||||
10527153227169483592824206336300422008699543534031594270383348457913225882068,
|
||||
12804751884521386825828658510190690148865851791523892609868081031939605961358
|
||||
);
|
||||
|
||||
vk.IC[21] = Pairing.G1Point(
|
||||
5041944607478059177624125335241251234509534257695185749390941036022860960816,
|
||||
14715110692011943220034133025600270907853469183775324358827935283475641931483
|
||||
);
|
||||
|
||||
vk.IC[22] = Pairing.G1Point(
|
||||
6488469541772400815270748483575613205398117193227035746999009466332002218363,
|
||||
18106240437835593271599347077483242513463538315052985603960081531158477315442
|
||||
);
|
||||
|
||||
vk.IC[23] = Pairing.G1Point(
|
||||
1230872150417054152826647550639910854731193569978803913801080823930604821153,
|
||||
4441239834640115257417519970272248211734460485545616030668417315357415914154
|
||||
);
|
||||
|
||||
vk.IC[24] = Pairing.G1Point(
|
||||
6406343488542573114884112413464096480828930995605113106495691687545227712109,
|
||||
17426609856363619856299264045979224732259410005301876158111198396440753914863
|
||||
);
|
||||
|
||||
vk.IC[25] = Pairing.G1Point(
|
||||
3552034247779690337035218009628728589744256014872407428271837630950111570086,
|
||||
6728361796164047891923136810794508198912347890773721917248600316699829273168
|
||||
);
|
||||
|
||||
vk.IC[26] = Pairing.G1Point(
|
||||
948342784008576109120692844149854821628015902379340058471998856660569607438,
|
||||
4633908852276178055277686663038238149681803147457082772385350331688615889853
|
||||
);
|
||||
}
|
||||
|
||||
function verify(uint256[] memory input, Proof memory proof) internal view returns (uint256) {
|
||||
uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||
VerifyingKey memory vk = verifyingKey();
|
||||
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);
|
||||
for (uint256 i = 0; i < input.length; i++) {
|
||||
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(
|
||||
Pairing.negate(proof.A), proof.B, vk.alfa1, vk.beta2, vk_x, vk.gamma2, proof.C, vk.delta2
|
||||
)
|
||||
) return 1;
|
||||
return 0;
|
||||
}
|
||||
/// @return r bool true if proof is valid
|
||||
|
||||
function verifyProof(uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c, uint256[26] 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]);
|
||||
uint256[] memory inputValues = new uint[](input.length);
|
||||
for (uint256 i = 0; i < input.length; i++) {
|
||||
inputValues[i] = input[i];
|
||||
}
|
||||
if (verify(inputValues, proof) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
461
src/contracts/src/Groth16VerifierWalletNonAnon.sol
Normal file
461
src/contracts/src/Groth16VerifierWalletNonAnon.sol
Normal file
@@ -0,0 +1,461 @@
|
||||
//
|
||||
// Copyright 2017 Christian Reitwiessner
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// 2019 OKIMS
|
||||
// ported to solidity 0.6
|
||||
// fixed linter warnings
|
||||
// added requiere error messages
|
||||
//
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.6.11;
|
||||
|
||||
library Pairing {
|
||||
struct G1Point {
|
||||
uint256 X;
|
||||
uint256 Y;
|
||||
}
|
||||
// Encoding of field elements is: X[0] * z + X[1]
|
||||
|
||||
struct G2Point {
|
||||
uint256[2] X;
|
||||
uint256[2] Y;
|
||||
}
|
||||
|
||||
/// @return the generator of G1
|
||||
function P1() internal pure returns (G1Point memory) {
|
||||
return G1Point(1, 2);
|
||||
}
|
||||
|
||||
/// @return the generator of G2
|
||||
function P2() internal pure returns (G2Point memory) {
|
||||
// Original code point
|
||||
return G2Point(
|
||||
[
|
||||
11559732032986387107991004021392285783925812861821192530917403151452391805634,
|
||||
10857046999023057135944570762232829481370756359578518086990519993285655852781
|
||||
],
|
||||
[
|
||||
4082367875863433681332203403145435568316851327593401208105741076214120093531,
|
||||
8495653923123431417604973247489272438418190587263600148770280649306958101930
|
||||
]
|
||||
);
|
||||
|
||||
/*
|
||||
// Changed by Jordi point
|
||||
return G2Point(
|
||||
[10857046999023057135944570762232829481370756359578518086990519993285655852781,
|
||||
11559732032986387107991004021392285783925812861821192530917403151452391805634],
|
||||
[8495653923123431417604973247489272438418190587263600148770280649306958101930,
|
||||
4082367875863433681332203403145435568316851327593401208105741076214120093531]
|
||||
);*/
|
||||
}
|
||||
|
||||
/// @return r the negation of p, i.e. p.addition(p.negate()) should be zero.
|
||||
function negate(G1Point memory p) internal pure returns (G1Point memory r) {
|
||||
// The prime q in the base field F_q for G1
|
||||
uint256 q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||
if (p.X == 0 && p.Y == 0) return G1Point(0, 0);
|
||||
return G1Point(p.X, q - (p.Y % q));
|
||||
}
|
||||
|
||||
/// @return r the sum of two points of G1
|
||||
function addition(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) {
|
||||
uint256[4] memory input;
|
||||
input[0] = p1.X;
|
||||
input[1] = p1.Y;
|
||||
input[2] = p2.X;
|
||||
input[3] = p2.Y;
|
||||
bool success;
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly {
|
||||
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 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, uint256 s) internal view returns (G1Point memory r) {
|
||||
uint256[3] memory input;
|
||||
input[0] = p.X;
|
||||
input[1] = p.Y;
|
||||
input[2] = s;
|
||||
bool success;
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly {
|
||||
success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60)
|
||||
// Use "invalid" to make gas estimation work
|
||||
switch success
|
||||
case 0 { invalid() }
|
||||
}
|
||||
require(success, "pairing-mul-failed");
|
||||
}
|
||||
|
||||
/// @return the result of computing the pairing check
|
||||
/// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1
|
||||
/// For example pairing([P1(), P1().negate()], [P2(), P2()]) should
|
||||
/// return true.
|
||||
function pairing(G1Point[] memory p1, G2Point[] memory p2) internal view returns (bool) {
|
||||
require(p1.length == p2.length, "pairing-lengths-failed");
|
||||
uint256 elements = p1.length;
|
||||
uint256 inputSize = elements * 6;
|
||||
uint256[] memory input = new uint[](inputSize);
|
||||
for (uint256 i = 0; i < elements; i++) {
|
||||
input[i * 6 + 0] = p1[i].X;
|
||||
input[i * 6 + 1] = p1[i].Y;
|
||||
input[i * 6 + 2] = p2[i].X[0];
|
||||
input[i * 6 + 3] = p2[i].X[1];
|
||||
input[i * 6 + 4] = p2[i].Y[0];
|
||||
input[i * 6 + 5] = p2[i].Y[1];
|
||||
}
|
||||
uint256[1] memory out;
|
||||
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)
|
||||
// Use "invalid" to make gas estimation work
|
||||
switch success
|
||||
case 0 { invalid() }
|
||||
}
|
||||
require(success, "pairing-opcode-failed");
|
||||
return out[0] != 0;
|
||||
}
|
||||
|
||||
/// Convenience method for a pairing check for two pairs.
|
||||
function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
G1Point[] memory p1 = new G1Point[](2);
|
||||
G2Point[] memory p2 = new G2Point[](2);
|
||||
p1[0] = a1;
|
||||
p1[1] = b1;
|
||||
p2[0] = a2;
|
||||
p2[1] = b2;
|
||||
return pairing(p1, p2);
|
||||
}
|
||||
|
||||
/// Convenience method for a pairing check for three pairs.
|
||||
function pairingProd3(
|
||||
G1Point memory a1,
|
||||
G2Point memory a2,
|
||||
G1Point memory b1,
|
||||
G2Point memory b2,
|
||||
G1Point memory c1,
|
||||
G2Point memory c2
|
||||
) internal view returns (bool) {
|
||||
G1Point[] memory p1 = new G1Point[](3);
|
||||
G2Point[] memory p2 = new G2Point[](3);
|
||||
p1[0] = a1;
|
||||
p1[1] = b1;
|
||||
p1[2] = c1;
|
||||
p2[0] = a2;
|
||||
p2[1] = b2;
|
||||
p2[2] = c2;
|
||||
return pairing(p1, p2);
|
||||
}
|
||||
|
||||
/// Convenience method for a pairing check for four pairs.
|
||||
function pairingProd4(
|
||||
G1Point memory a1,
|
||||
G2Point memory a2,
|
||||
G1Point memory b1,
|
||||
G2Point memory b2,
|
||||
G1Point memory c1,
|
||||
G2Point memory c2,
|
||||
G1Point memory d1,
|
||||
G2Point memory d2
|
||||
) internal view returns (bool) {
|
||||
G1Point[] memory p1 = new G1Point[](4);
|
||||
G2Point[] memory p2 = new G2Point[](4);
|
||||
p1[0] = a1;
|
||||
p1[1] = b1;
|
||||
p1[2] = c1;
|
||||
p1[3] = d1;
|
||||
p2[0] = a2;
|
||||
p2[1] = b2;
|
||||
p2[2] = c2;
|
||||
p2[3] = d2;
|
||||
return pairing(p1, p2);
|
||||
}
|
||||
}
|
||||
|
||||
contract VerifierNonAnonWallet {
|
||||
using Pairing for *;
|
||||
|
||||
struct VerifyingKey {
|
||||
Pairing.G1Point alfa1;
|
||||
Pairing.G2Point beta2;
|
||||
Pairing.G2Point gamma2;
|
||||
Pairing.G2Point delta2;
|
||||
Pairing.G1Point[] IC;
|
||||
}
|
||||
|
||||
struct Proof {
|
||||
Pairing.G1Point A;
|
||||
Pairing.G2Point B;
|
||||
Pairing.G1Point C;
|
||||
}
|
||||
|
||||
function verifyingKey() internal pure returns (VerifyingKey memory vk) {
|
||||
vk.alfa1 = Pairing.G1Point(
|
||||
20491192805390485299153009773594534940189261866228447918068658471970481763042,
|
||||
9383485363053290200918347156157836566562967994039712273449902621266178545958
|
||||
);
|
||||
|
||||
vk.beta2 = Pairing.G2Point(
|
||||
[
|
||||
4252822878758300859123897981450591353533073413197771768651442665752259397132,
|
||||
6375614351688725206403948262868962793625744043794305715222011528459656738731
|
||||
],
|
||||
[
|
||||
21847035105528745403288232691147584728191162732299865338377159692350059136679,
|
||||
10505242626370262277552901082094356697409835680220590971873171140371331206856
|
||||
]
|
||||
);
|
||||
vk.gamma2 = Pairing.G2Point(
|
||||
[
|
||||
11559732032986387107991004021392285783925812861821192530917403151452391805634,
|
||||
10857046999023057135944570762232829481370756359578518086990519993285655852781
|
||||
],
|
||||
[
|
||||
4082367875863433681332203403145435568316851327593401208105741076214120093531,
|
||||
8495653923123431417604973247489272438418190587263600148770280649306958101930
|
||||
]
|
||||
);
|
||||
vk.delta2 = Pairing.G2Point(
|
||||
[
|
||||
1513129022268504209358763521777110646559191312944535983790343685540452445612,
|
||||
12195000584114682213316512369139242650405673197296308277565313794080256232701
|
||||
],
|
||||
[
|
||||
8360772797757285669693588223224368324652217960280535125476432579464480898413,
|
||||
520894096459672819696448581165649200639580943346471218758886059131097679200
|
||||
]
|
||||
);
|
||||
vk.IC = new Pairing.G1Point[](35);
|
||||
|
||||
vk.IC[0] = Pairing.G1Point(
|
||||
11537328283226768393732428330956073110918624081922605220849994462257164716154,
|
||||
21836950190585457727786541794875874204342457073442279657287670575335295859939
|
||||
);
|
||||
|
||||
vk.IC[1] = Pairing.G1Point(
|
||||
2646307150509379456483324388204599416197823343744573056776580441757968778128,
|
||||
14368370831419521837815784599306984151624772530159432470308283448431330483438
|
||||
);
|
||||
|
||||
vk.IC[2] = Pairing.G1Point(
|
||||
16971624750468472956383457363672950966338870541072731251437414691217134411120,
|
||||
8171770470043873321771537156021753591829282779422875691859226771666334115210
|
||||
);
|
||||
|
||||
vk.IC[3] = Pairing.G1Point(
|
||||
17003248154885997024042723500051841853373913724967509464380365353802575974728,
|
||||
7268687626523176370339202918269959082095447462862347953587350206552205642559
|
||||
);
|
||||
|
||||
vk.IC[4] = Pairing.G1Point(
|
||||
9147424234223179035895482077044817222415554273556867838268712944193520459125,
|
||||
21578705994822322813698189503736815299185497639660343771670537250469027755948
|
||||
);
|
||||
|
||||
vk.IC[5] = Pairing.G1Point(
|
||||
16948417333412259029407181850226843375508933350680650127572170476630717282234,
|
||||
9665563179883720332817127456522837835577284997912132910805194791161889398512
|
||||
);
|
||||
|
||||
vk.IC[6] = Pairing.G1Point(
|
||||
9319994583370423638602672994382300950312503535351144768052894387193551537459,
|
||||
19171031111811822064434269353657536224339902296340766041252096715670766153578
|
||||
);
|
||||
|
||||
vk.IC[7] = Pairing.G1Point(
|
||||
9371603635986601434942264619807195148477116766259006354709633771674992552724,
|
||||
11103293940652841271958831421967970005702672122254116205870466468493278826958
|
||||
);
|
||||
|
||||
vk.IC[8] = Pairing.G1Point(
|
||||
3561757143230234005632456376532802121489770329687277876867422136368222736134,
|
||||
11734814901687269585580202167146602218102049962630061844516173384912435005151
|
||||
);
|
||||
|
||||
vk.IC[9] = Pairing.G1Point(
|
||||
16676238706569507337573176601181670688707264606170712075388734731572549373015,
|
||||
11158592034910239776632780480510406146251140896522712858892689171974748083747
|
||||
);
|
||||
|
||||
vk.IC[10] = Pairing.G1Point(
|
||||
9822993420542467873912218347366938030193407618831916003032667186678059114349,
|
||||
6863223533781083402167797754430699108902384970089129346113470095574463296737
|
||||
);
|
||||
|
||||
vk.IC[11] = Pairing.G1Point(
|
||||
4866721301322510775531094866459672146070982818674092273969310571220291630556,
|
||||
9846640210996171367705574856419053631553093780701851221089070591862473684456
|
||||
);
|
||||
|
||||
vk.IC[12] = Pairing.G1Point(
|
||||
11121919417977708038028243712145798541888876824913262431306415256568966652024,
|
||||
12609770408698645498350514024296607224475353273713173177251900216074217014850
|
||||
);
|
||||
|
||||
vk.IC[13] = Pairing.G1Point(
|
||||
14840050373651993593383756529988239317958775236310376879012996717055845150487,
|
||||
16683016138329247649135414505803188190565946292769946693147365719646757192352
|
||||
);
|
||||
|
||||
vk.IC[14] = Pairing.G1Point(
|
||||
12331471170495648864015185687161748641193043583582691780623236535573811426959,
|
||||
11714531956225516771424892308789701085922077646343882797070434158311220922011
|
||||
);
|
||||
|
||||
vk.IC[15] = Pairing.G1Point(
|
||||
20857366342421630154576707922479406842052250461154457549932210545889187427626,
|
||||
19731871495034015170236307573440414758884960293847791130561428843792753429086
|
||||
);
|
||||
|
||||
vk.IC[16] = Pairing.G1Point(
|
||||
16209406523379999199236029863462575441846948663847567298395841886469797214082,
|
||||
20718988335004414356172240953954108902387108184538803896124546491420460740169
|
||||
);
|
||||
|
||||
vk.IC[17] = Pairing.G1Point(
|
||||
8397179853577453858892608876746062307226175687475102639712031393841003387919,
|
||||
7154528864876839718549215559715861424372452521581853695056564308745992761672
|
||||
);
|
||||
|
||||
vk.IC[18] = Pairing.G1Point(
|
||||
15000425614899689626185464253582174491572354417903507356426258449407132127046,
|
||||
13602373364472815067534003393627538602411204908660744540946955553406039633451
|
||||
);
|
||||
|
||||
vk.IC[19] = Pairing.G1Point(
|
||||
5545252939208963791309142258539499940294193526436021787091019273144246885261,
|
||||
2675833647327088808677716501235324721140769279456271927816550777395489852251
|
||||
);
|
||||
|
||||
vk.IC[20] = Pairing.G1Point(
|
||||
2537047834074478023060297384888724410218136939149736151242515713484635642789,
|
||||
3193147508270124393755481767836877808561856886429215905854576456538260642120
|
||||
);
|
||||
|
||||
vk.IC[21] = Pairing.G1Point(
|
||||
13819984179784763421503658502014430958296359352165019537755065452645355466085,
|
||||
18994178127386658997162783196808799873728043389545801736093808610346271161658
|
||||
);
|
||||
|
||||
vk.IC[22] = Pairing.G1Point(
|
||||
6589370869708283514329318539826110923064805897289825414235274269171407140900,
|
||||
9625792054986455984618262255946246252268480571067521104852530192902386719593
|
||||
);
|
||||
|
||||
vk.IC[23] = Pairing.G1Point(
|
||||
14453270681522455527144160729543145025587040770258214008741757192612444737673,
|
||||
20143300120523312381709649823189168032874279267240134119356286009260298185475
|
||||
);
|
||||
|
||||
vk.IC[24] = Pairing.G1Point(
|
||||
8846979524751473322994268234754538401482894217522349506066299416316984717260,
|
||||
14238278950875447301003974303300008365515832894025960431754069250458716988985
|
||||
);
|
||||
|
||||
vk.IC[25] = Pairing.G1Point(
|
||||
1407828395464361821905309927863167268883721160860555328581866885124611897528,
|
||||
15987854649208373291691713233856831065610123809032682196292981616658494776987
|
||||
);
|
||||
|
||||
vk.IC[26] = Pairing.G1Point(
|
||||
20657483817998070093869648777824400547660398552294774144027193285451239619382,
|
||||
21826613460615350291777797645121185151869814459512699120411019581958075991542
|
||||
);
|
||||
|
||||
vk.IC[27] = Pairing.G1Point(
|
||||
20624928617240774729161710928323453036077574938263627000040473137006018415415,
|
||||
5131454817008842892320970265930200727731593782574755474310860262365965990664
|
||||
);
|
||||
|
||||
vk.IC[28] = Pairing.G1Point(
|
||||
13895249990164764352618348094492621630575085672410127797817030490897283284460,
|
||||
11796920177436300262655702063092510613755939821586920802170520825907606184557
|
||||
);
|
||||
|
||||
vk.IC[29] = Pairing.G1Point(
|
||||
3135811994020780743324086008729747183900335277491189104250977002197575809365,
|
||||
19637480211624980857501152516366188197895066151113910763057713919944678029866
|
||||
);
|
||||
|
||||
vk.IC[30] = Pairing.G1Point(
|
||||
606103022421566187118689786319065266252504972683102249226453076393842587324,
|
||||
10274587862652629723961486759561149321143114208996217550785138347396636546119
|
||||
);
|
||||
|
||||
vk.IC[31] = Pairing.G1Point(
|
||||
17876636758905622230688544604495142065478803287376541138330575508029036910921,
|
||||
845514606482911379811389987862147832754587150586772012493153117259870748818
|
||||
);
|
||||
|
||||
vk.IC[32] = Pairing.G1Point(
|
||||
3055934057788309375612017678081361462642124203699024466299800387864964176162,
|
||||
6215463225683464296816602777995066291454589608119271052091343612576965188139
|
||||
);
|
||||
|
||||
vk.IC[33] = Pairing.G1Point(
|
||||
15655816926053512024400351678850471800118254812943223488624167720306406940886,
|
||||
1318451441938966067851976459607266837893918068783070216555767331693196884126
|
||||
);
|
||||
|
||||
vk.IC[34] = Pairing.G1Point(
|
||||
13942491345765259320815758221010163510633256522676138655574537850419728932090,
|
||||
2449428677603436766608016448595332101485961035234011384134049218692804513154
|
||||
);
|
||||
}
|
||||
|
||||
function verify(uint256[] memory input, Proof memory proof) public view returns (uint256) {
|
||||
uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||
VerifyingKey memory vk = verifyingKey();
|
||||
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);
|
||||
for (uint256 i = 0; i < input.length; i++) {
|
||||
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(
|
||||
Pairing.negate(proof.A), proof.B, vk.alfa1, vk.beta2, vk_x, vk.gamma2, proof.C, vk.delta2
|
||||
)
|
||||
) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @return r bool true if proof is valid
|
||||
function verifyProof(uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c, uint256[34] 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]);
|
||||
uint256[] memory inputValues = new uint[](input.length);
|
||||
for (uint256 i = 0; i < input.length; i++) {
|
||||
inputValues[i] = input[i];
|
||||
}
|
||||
if (verify(inputValues, proof) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,171 +3,248 @@ pragma solidity >=0.7.6;
|
||||
|
||||
// https://github.com/nalinbhardwaj/ethdosnumber/blob/main/ethdos-contracts/src/HexStrings.sol
|
||||
library StringUtils {
|
||||
bytes16 internal constant ALPHABET = "0123456789abcdef";
|
||||
bytes16 internal constant ALPHABET = "0123456789abcdef";
|
||||
|
||||
/// @notice Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
|
||||
/// @dev Credit to Open Zeppelin under MIT license https://github.com/OpenZeppelin/openzeppelin-contracts/blob/243adff49ce1700e0ecb99fe522fb16cff1d1ddc/contracts/utils/Strings.sol#L55
|
||||
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
|
||||
bytes memory buffer = new bytes(2 * length + 2);
|
||||
buffer[0] = "0";
|
||||
buffer[1] = "x";
|
||||
for (uint256 i = 2 * length + 1; i > 1; --i) {
|
||||
buffer[i] = ALPHABET[value & 0xf];
|
||||
value >>= 4;
|
||||
}
|
||||
require(value == 0, "Strings: hex length insufficient");
|
||||
return string(buffer);
|
||||
}
|
||||
|
||||
function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory) {
|
||||
bytes memory buffer = new bytes(2 * length);
|
||||
for (uint256 i = buffer.length; i > 0; i--) {
|
||||
buffer[i - 1] = ALPHABET[value & 0xf];
|
||||
value >>= 4;
|
||||
}
|
||||
return string(buffer);
|
||||
}
|
||||
|
||||
function toString(uint256 value) internal pure returns (string memory) {
|
||||
return toString(abi.encodePacked(value));
|
||||
}
|
||||
|
||||
function toString(bytes32 value) internal pure returns (string memory) {
|
||||
return toString(abi.encodePacked(value));
|
||||
}
|
||||
|
||||
function toString(address account) internal pure returns (string memory) {
|
||||
return toString(abi.encodePacked(account));
|
||||
}
|
||||
|
||||
function stringEq(string memory a, string memory b) internal pure returns (bool) {
|
||||
return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b));
|
||||
}
|
||||
|
||||
function toString(bytes memory data) internal pure returns (string memory) {
|
||||
bytes memory alphabet = "0123456789abcdef";
|
||||
|
||||
bytes memory str = new bytes(2 + data.length * 2);
|
||||
str[0] = "0";
|
||||
str[1] = "x";
|
||||
for (uint256 i = 0; i < data.length; i++) {
|
||||
str[2 + i * 2] = alphabet[uint256(uint8(data[i] >> 4))];
|
||||
str[3 + i * 2] = alphabet[uint256(uint8(data[i] & 0x0f))];
|
||||
}
|
||||
return string(str);
|
||||
}
|
||||
|
||||
// Unpacks uint256s into bytes and then extracts the non-zero characters
|
||||
// Only extracts contiguous non-zero characters and ensures theres only 1 such state
|
||||
// Note that unpackedLen may be more than packedBytes.length * 8 since there may be 0s
|
||||
// TODO: Remove console.logs and define this as a pure function instead of a view
|
||||
function convertPackedBytesToString(uint256[] memory packedBytes, uint256 maxBytes, uint256 packSize) internal pure returns (string memory extractedString) {
|
||||
uint8 state = 0;
|
||||
// bytes: 0 0 0 0 y u s h _ g 0 0 0
|
||||
// state: 0 0 0 0 1 1 1 1 1 1 2 2 2
|
||||
bytes memory nonzeroBytesArray = new bytes(packedBytes.length * 7);
|
||||
uint256 nonzeroBytesArrayIndex = 0;
|
||||
for (uint16 i = 0; i < packedBytes.length; i++) {
|
||||
uint256 packedByte = packedBytes[i];
|
||||
uint8[] memory unpackedBytes = new uint8[](packSize);
|
||||
for (uint256 j = 0; j < packSize; j++) {
|
||||
unpackedBytes[j] = uint8(packedByte >> (j * 8));
|
||||
}
|
||||
for (uint256 j = 0; j < packSize; j++) {
|
||||
uint256 unpackedByte = unpackedBytes[j]; //unpackedBytes[j];
|
||||
// console.log(i, j, state, unpackedByte);
|
||||
if (unpackedByte != 0) {
|
||||
nonzeroBytesArray[nonzeroBytesArrayIndex] = bytes1(uint8(unpackedByte));
|
||||
nonzeroBytesArrayIndex++;
|
||||
if (state % 2 == 0) {
|
||||
state += 1;
|
||||
}
|
||||
} else {
|
||||
if (state % 2 == 1) {
|
||||
state += 1;
|
||||
}
|
||||
/// @notice Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
|
||||
/// @dev Credit to Open Zeppelin under MIT license https://github.com/OpenZeppelin/openzeppelin-contracts/blob/243adff49ce1700e0ecb99fe522fb16cff1d1ddc/contracts/utils/Strings.sol#L55
|
||||
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
|
||||
bytes memory buffer = new bytes(2 * length + 2);
|
||||
buffer[0] = "0";
|
||||
buffer[1] = "x";
|
||||
for (uint256 i = 2 * length + 1; i > 1; --i) {
|
||||
buffer[i] = ALPHABET[value & 0xf];
|
||||
value >>= 4;
|
||||
}
|
||||
packedByte = packedByte >> 8;
|
||||
}
|
||||
require(value == 0, "Strings: hex length insufficient");
|
||||
return string(buffer);
|
||||
}
|
||||
require(state >= 1, "Invalid final state of packed bytes in email");
|
||||
require(nonzeroBytesArrayIndex <= maxBytes, "Packed bytes more than allowed max length!");
|
||||
string memory returnValue = removeTrailingZeros(string(nonzeroBytesArray));
|
||||
return returnValue;
|
||||
// Have to end at the end of the email -- state cannot be 1 since there should be an email footer
|
||||
}
|
||||
|
||||
function bytes32ToString(bytes32 input) internal pure returns (string memory) {
|
||||
uint256 i;
|
||||
for (i = 0; i < 32 && input[i] != 0; i++) {}
|
||||
bytes memory resultBytes = new bytes(i);
|
||||
for (i = 0; i < 32 && input[i] != 0; i++) {
|
||||
resultBytes[i] = input[i];
|
||||
function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory) {
|
||||
bytes memory buffer = new bytes(2 * length);
|
||||
for (uint256 i = buffer.length; i > 0; i--) {
|
||||
buffer[i - 1] = ALPHABET[value & 0xf];
|
||||
value >>= 4;
|
||||
}
|
||||
return string(buffer);
|
||||
}
|
||||
return string(resultBytes);
|
||||
}
|
||||
|
||||
// sliceArray is used to slice an array of uint256s from start-end into a new array of uint256s
|
||||
function sliceArray(uint256[] memory input, uint256 start, uint256 end) internal pure returns (uint256[] memory) {
|
||||
require(start <= end && end <= input.length, "Invalid slice indices");
|
||||
uint256[] memory result = new uint256[](end - start);
|
||||
for (uint256 i = start; i < end; i++) {
|
||||
result[i - start] = input[i];
|
||||
function toString(uint256 value) internal pure returns (string memory) {
|
||||
return toString(abi.encodePacked(value));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// stringToUint is used to convert a string like "45" to a uint256 4
|
||||
function stringToUint(string memory s) internal pure returns (uint256) {
|
||||
bytes memory b = bytes(s);
|
||||
uint256 result = 0;
|
||||
for (uint256 i = 0; i < b.length; i++) {
|
||||
if (b[i] >= 0x30 && b[i] <= 0x39) {
|
||||
result = result * 10 + (uint256(uint8(b[i])) - 48);
|
||||
}
|
||||
function toString(bytes32 value) internal pure returns (string memory) {
|
||||
return toString(abi.encodePacked(value));
|
||||
}
|
||||
|
||||
// TODO: Currently truncates decimals
|
||||
if (b[i] == 0x2E) {
|
||||
function toString(address account) internal pure returns (string memory) {
|
||||
return toString(abi.encodePacked(account));
|
||||
}
|
||||
|
||||
function stringEq(string memory a, string memory b) internal pure returns (bool) {
|
||||
return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b));
|
||||
}
|
||||
|
||||
function toString(bytes memory data) internal pure returns (string memory) {
|
||||
bytes memory alphabet = "0123456789abcdef";
|
||||
|
||||
bytes memory str = new bytes(2 + data.length * 2);
|
||||
str[0] = "0";
|
||||
str[1] = "x";
|
||||
for (uint256 i = 0; i < data.length; i++) {
|
||||
str[2 + i * 2] = alphabet[uint256(uint8(data[i] >> 4))];
|
||||
str[3 + i * 2] = alphabet[uint256(uint8(data[i] & 0x0f))];
|
||||
}
|
||||
return string(str);
|
||||
}
|
||||
|
||||
// Unpacks uint256s into bytes and then extracts the non-zero characters
|
||||
// Only extracts contiguous non-zero characters and ensures theres only 1 such state
|
||||
// Note that unpackedLen may be more than packedBytes.length * 8 since there may be 0s
|
||||
// TODO: Remove console.logs and define this as a pure function instead of a view
|
||||
function convertPackedBytesToString(uint256[] memory packedBytes, uint256 maxBytes, uint256 packSize)
|
||||
internal
|
||||
pure
|
||||
returns (string memory extractedString)
|
||||
{
|
||||
uint8 state = 0;
|
||||
// bytes: 0 0 0 0 y u s h _ g 0 0 0
|
||||
// state: 0 0 0 0 1 1 1 1 1 1 2 2 2
|
||||
bytes memory nonzeroBytesArray = new bytes(packedBytes.length * 7);
|
||||
uint256 nonzeroBytesArrayIndex = 0;
|
||||
for (uint16 i = 0; i < packedBytes.length; i++) {
|
||||
uint256 packedByte = packedBytes[i];
|
||||
uint8[] memory unpackedBytes = new uint8[](packSize);
|
||||
for (uint256 j = 0; j < packSize; j++) {
|
||||
unpackedBytes[j] = uint8(packedByte >> (j * 8));
|
||||
}
|
||||
for (uint256 j = 0; j < packSize; j++) {
|
||||
uint256 unpackedByte = unpackedBytes[j]; //unpackedBytes[j];
|
||||
// console.log(i, j, state, unpackedByte);
|
||||
if (unpackedByte != 0) {
|
||||
nonzeroBytesArray[nonzeroBytesArrayIndex] = bytes1(uint8(unpackedByte));
|
||||
nonzeroBytesArrayIndex++;
|
||||
if (state % 2 == 0) {
|
||||
state += 1;
|
||||
}
|
||||
} else {
|
||||
if (state % 2 == 1) {
|
||||
state += 1;
|
||||
}
|
||||
}
|
||||
packedByte = packedByte >> 8;
|
||||
}
|
||||
}
|
||||
require(state >= 1, "Invalid final state of packed bytes in email");
|
||||
require(nonzeroBytesArrayIndex <= maxBytes, "Packed bytes more than allowed max length!");
|
||||
string memory returnValue = removeTrailingZeros(string(nonzeroBytesArray));
|
||||
return returnValue;
|
||||
// Have to end at the end of the email -- state cannot be 1 since there should be an email footer
|
||||
}
|
||||
|
||||
function bytes32ToString(bytes32 input) internal pure returns (string memory) {
|
||||
uint256 i;
|
||||
for (i = 0; i < 32 && input[i] != 0; i++) {}
|
||||
bytes memory resultBytes = new bytes(i);
|
||||
for (i = 0; i < 32 && input[i] != 0; i++) {
|
||||
resultBytes[i] = input[i];
|
||||
}
|
||||
return string(resultBytes);
|
||||
}
|
||||
|
||||
// sliceArray is used to slice an array of uint256s from start-end into a new array of uint256s
|
||||
function sliceArray(uint256[] memory input, uint256 start, uint256 end) internal pure returns (uint256[] memory) {
|
||||
require(start <= end && end <= input.length, "Invalid slice indices");
|
||||
uint256[] memory result = new uint256[](end - start);
|
||||
for (uint256 i = start; i < end; i++) {
|
||||
result[i - start] = input[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// getDomainFromEmail is used to extract the domain from an email i.e. the part after the @
|
||||
function getDomainFromEmail(string memory fromEmail) internal pure returns (string memory) {
|
||||
bytes memory emailBytes = bytes(fromEmail);
|
||||
uint256 atIndex;
|
||||
for (uint256 i = 0; i < emailBytes.length; i++) {
|
||||
if (emailBytes[i] == "@") {
|
||||
atIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bytes memory domainBytes = new bytes(emailBytes.length - atIndex - 1);
|
||||
for (uint256 j = 0; j < domainBytes.length; j++) {
|
||||
domainBytes[j] = emailBytes[atIndex + 1 + j];
|
||||
}
|
||||
return bytes32ToString(bytes32(bytes(domainBytes)));
|
||||
}
|
||||
// stringToUint is used to convert a string like "45" to a uint256 4
|
||||
function stringToUint(string memory s) internal pure returns (uint256) {
|
||||
bytes memory b = bytes(s);
|
||||
uint256 result = 0;
|
||||
for (uint256 i = 0; i < b.length; i++) {
|
||||
if (b[i] >= 0x30 && b[i] <= 0x39) {
|
||||
result = result * 10 + (uint256(uint8(b[i])) - 48);
|
||||
}
|
||||
|
||||
function removeTrailingZeros(string memory input) public pure returns (string memory) {
|
||||
bytes memory inputBytes = bytes(input);
|
||||
uint256 endIndex = inputBytes.length;
|
||||
|
||||
for (uint256 i = 0; i < inputBytes.length; i++) {
|
||||
if (inputBytes[i] == 0) {
|
||||
endIndex = i;
|
||||
break;
|
||||
// TODO: Currently truncates decimals
|
||||
if (b[i] == 0x2E) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bytes memory resultBytes = new bytes(endIndex);
|
||||
for (uint256 i = 0; i < endIndex; i++) {
|
||||
resultBytes[i] = inputBytes[i];
|
||||
// getDomainFromEmail is used to extract the domain from an email i.e. the part after the @
|
||||
function getDomainFromEmail(string memory fromEmail) internal pure returns (string memory) {
|
||||
bytes memory emailBytes = bytes(fromEmail);
|
||||
uint256 atIndex;
|
||||
for (uint256 i = 0; i < emailBytes.length; i++) {
|
||||
if (emailBytes[i] == "@") {
|
||||
atIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bytes memory domainBytes = new bytes(emailBytes.length - atIndex - 1);
|
||||
for (uint256 j = 0; j < domainBytes.length; j++) {
|
||||
domainBytes[j] = emailBytes[atIndex + 1 + j];
|
||||
}
|
||||
return bytes32ToString(bytes32(bytes(domainBytes)));
|
||||
}
|
||||
|
||||
return string(resultBytes);
|
||||
}
|
||||
function removeTrailingZeros(string memory input) public pure returns (string memory) {
|
||||
bytes memory inputBytes = bytes(input);
|
||||
uint256 endIndex = inputBytes.length;
|
||||
|
||||
for (uint256 i = 0; i < inputBytes.length; i++) {
|
||||
if (inputBytes[i] == 0) {
|
||||
endIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bytes memory resultBytes = new bytes(endIndex);
|
||||
for (uint256 i = 0; i < endIndex; i++) {
|
||||
resultBytes[i] = inputBytes[i];
|
||||
}
|
||||
|
||||
return string(resultBytes);
|
||||
}
|
||||
|
||||
// Upper/lower string utils from https://github.com/willitscale/solidity-util/blob/master/lib/Strings.sol
|
||||
/**
|
||||
* Upper
|
||||
*
|
||||
* Converts all the values of a string to their corresponding upper case
|
||||
* value.
|
||||
*
|
||||
* @param _base When being used for a data type this is the extended object
|
||||
* otherwise this is the string base to convert to upper case
|
||||
* @return string
|
||||
*/
|
||||
function upper(string memory _base) public pure returns (string memory) {
|
||||
bytes memory _baseBytes = bytes(_base);
|
||||
for (uint256 i = 0; i < _baseBytes.length; i++) {
|
||||
_baseBytes[i] = _upper(_baseBytes[i]);
|
||||
}
|
||||
return string(_baseBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower
|
||||
*
|
||||
* Converts all the values of a string to their corresponding lower case
|
||||
* value.
|
||||
*
|
||||
* @param _base When being used for a data type this is the extended object
|
||||
* otherwise this is the string base to convert to lower case
|
||||
* @return string
|
||||
*/
|
||||
function lower(string memory _base) public pure returns (string memory) {
|
||||
bytes memory _baseBytes = bytes(_base);
|
||||
for (uint256 i = 0; i < _baseBytes.length; i++) {
|
||||
_baseBytes[i] = _lower(_baseBytes[i]);
|
||||
}
|
||||
return string(_baseBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upper
|
||||
*
|
||||
* Convert an alphabetic character to upper case and return the original
|
||||
* value when not alphabetic
|
||||
*
|
||||
* @param _b1 The byte to be converted to upper case
|
||||
* @return bytes1 The converted value if the passed value was alphabetic
|
||||
* and in a lower case otherwise returns the original value
|
||||
*/
|
||||
function _upper(bytes1 _b1) private pure returns (bytes1) {
|
||||
if (_b1 >= 0x61 && _b1 <= 0x7A) {
|
||||
return bytes1(uint8(_b1) - 32);
|
||||
}
|
||||
|
||||
return _b1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower
|
||||
*
|
||||
* Convert an alphabetic character to lower case and return the original
|
||||
* value when not alphabetic
|
||||
*
|
||||
* @param _b1 The byte to be converted to lower case
|
||||
* @return bytes1 The converted value if the passed value was alphabetic
|
||||
* and in a upper case otherwise returns the original value
|
||||
*/
|
||||
function _lower(bytes1 _b1) private pure returns (bytes1) {
|
||||
if (_b1 >= 0x41 && _b1 <= 0x5A) {
|
||||
return bytes1(uint8(_b1) + 32);
|
||||
}
|
||||
|
||||
return _b1;
|
||||
}
|
||||
}
|
||||
|
||||
104
src/contracts/src/TokenRegistry.sol
Normal file
104
src/contracts/src/TokenRegistry.sol
Normal file
@@ -0,0 +1,104 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
contract TokenRegistry {
|
||||
// Define a structure that represents a token
|
||||
struct Token {
|
||||
address optimism;
|
||||
address arbitrum;
|
||||
address xdai;
|
||||
address goerli;
|
||||
address mainnet;
|
||||
}
|
||||
|
||||
// Define a mapping from token names to their addresses on each chain
|
||||
mapping(string => Token) private tokens;
|
||||
mapping(uint256 => string) private chainIdToName;
|
||||
|
||||
// Define the owner of the contract
|
||||
address private owner;
|
||||
|
||||
// Ensure that only the owner can call certain functions
|
||||
modifier onlyOwner() {
|
||||
require(msg.sender == owner, "Only the owner can call this function.");
|
||||
_;
|
||||
}
|
||||
|
||||
// Set the owner of the contract
|
||||
constructor() {
|
||||
owner = msg.sender;
|
||||
|
||||
// Initialize the mapping with some hardcoded addresses
|
||||
// TODO: Add RAI, and some other tokens
|
||||
tokens["DAI"] = Token({
|
||||
optimism: 0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1,
|
||||
arbitrum: 0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1,
|
||||
xdai: 0x44fA8E6f47987339850636F88629646662444217,
|
||||
goerli: 0x11fE4B6AE13d2a6055C8D9cF65c55bac32B5d844,
|
||||
mainnet: 0x6B175474E89094C44Da98b954EedeAC495271d0F
|
||||
});
|
||||
tokens["USDC"] = Token({
|
||||
optimism: 0x7F5c764cBc14f9669B88837ca1490cCa17c31607,
|
||||
arbitrum: 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8,
|
||||
xdai: 0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83,
|
||||
goerli: 0x07865c6E87B9F70255377e024ace6630C1Eaa37F,
|
||||
mainnet: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
|
||||
});
|
||||
tokens["WETH"] = Token({
|
||||
optimism: 0x4200000000000000000000000000000000000006,
|
||||
arbitrum: 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1,
|
||||
xdai: 0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1,
|
||||
goerli: 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6,
|
||||
mainnet: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
|
||||
});
|
||||
|
||||
chainIdToName[0] = "mainnet";
|
||||
chainIdToName[10] = "optimism";
|
||||
chainIdToName[100] = "xdai";
|
||||
chainIdToName[42161] = "arbitrum";
|
||||
chainIdToName[5] = "goerli";
|
||||
chainIdToName[31337] = "goerli"; // Local foundry test chain goerli fork
|
||||
}
|
||||
|
||||
// Return the address of a token on a specific chain
|
||||
function getTokenAddress(string memory tokenName, uint256 chainId) public view returns (address) {
|
||||
return getTokenAddress(tokenName, chainIdToName[chainId]);
|
||||
}
|
||||
|
||||
// Return the address of a token on a specific chain
|
||||
function getTokenAddress(string memory tokenName, string memory chainName) public view returns (address) {
|
||||
if (keccak256(abi.encodePacked(chainName)) == keccak256(abi.encodePacked("optimism"))) {
|
||||
return tokens[tokenName].optimism;
|
||||
} else if (keccak256(abi.encodePacked(chainName)) == keccak256(abi.encodePacked("arbitrum"))) {
|
||||
return tokens[tokenName].arbitrum;
|
||||
} else if (keccak256(abi.encodePacked(chainName)) == keccak256(abi.encodePacked("xdai"))) {
|
||||
return tokens[tokenName].xdai;
|
||||
} else if (keccak256(abi.encodePacked(chainName)) == keccak256(abi.encodePacked("goerli"))) {
|
||||
return tokens[tokenName].goerli;
|
||||
} else if (keccak256(abi.encodePacked(chainName)) == keccak256(abi.encodePacked("mainnet"))) {
|
||||
return tokens[tokenName].mainnet;
|
||||
} else {
|
||||
revert("Invalid chain name.");
|
||||
}
|
||||
}
|
||||
|
||||
// Update the address of a token on a specific chain
|
||||
function updateTokenAddress(string memory tokenName, string memory chainName, address newAddress)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
if (keccak256(abi.encodePacked(chainName)) == keccak256(abi.encodePacked("optimism"))) {
|
||||
tokens[tokenName].optimism = newAddress;
|
||||
} else if (keccak256(abi.encodePacked(chainName)) == keccak256(abi.encodePacked("arbitrum"))) {
|
||||
tokens[tokenName].arbitrum = newAddress;
|
||||
} else if (keccak256(abi.encodePacked(chainName)) == keccak256(abi.encodePacked("xdai"))) {
|
||||
tokens[tokenName].xdai = newAddress;
|
||||
} else if (keccak256(abi.encodePacked(chainName)) == keccak256(abi.encodePacked("goerli"))) {
|
||||
tokens[tokenName].goerli = newAddress;
|
||||
} else if (keccak256(abi.encodePacked(chainName)) == keccak256(abi.encodePacked("mainnet"))) {
|
||||
tokens[tokenName].mainnet = newAddress;
|
||||
} else {
|
||||
revert("Invalid chain name.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,157 +4,22 @@ pragma solidity ^0.8.0;
|
||||
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
|
||||
import "@openzeppelin/contracts/utils/Strings.sol";
|
||||
import "@openzeppelin/contracts/utils/Counters.sol";
|
||||
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/proxy/Proxy.sol";
|
||||
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
|
||||
|
||||
import "forge-std/console.sol";
|
||||
// import "./base64.sol";
|
||||
import "./StringUtils.sol";
|
||||
import "./AutoApproveWallet.sol";
|
||||
import "./TestERC20.sol";
|
||||
import "./NFTSVG.sol";
|
||||
import {Verifier} from "./Groth16VerifierWallet.sol";
|
||||
import {Verifier} from "./Groth16VerifierWalletAnon.sol";
|
||||
import "./MailServer.sol";
|
||||
|
||||
contract VerifiedWalletEmail {
|
||||
using StringUtils for *;
|
||||
|
||||
uint16 public constant packSize = 7; // 7 bytes in a packed item returned from circom
|
||||
|
||||
uint16 public constant body_len = 4 * 4;
|
||||
uint16 public constant rsa_modulus_chunks_len = 17;
|
||||
uint16 public constant commitment_len = 1;
|
||||
uint16 public constant msg_len = body_len + rsa_modulus_chunks_len + commitment_len; // 34
|
||||
|
||||
uint16 public constant header_len = msg_len - body_len;
|
||||
uint16 public constant addressIndexInSignals = msg_len - 1; // The last index is the commitment
|
||||
|
||||
mapping(string => uint256[rsa_modulus_chunks_len]) public verifiedMailserverKeys;
|
||||
mapping(string => uint256) public balance;
|
||||
// NOTE: is Ownable is only for emergency ejects in testing deployments
|
||||
contract VerifiedWalletEmailStorage {
|
||||
// mapping(string => uint256) public balance;
|
||||
mapping(uint256 => bool) public nullifier;
|
||||
MailServer mailServer;
|
||||
Verifier public immutable verifier;
|
||||
TestEmailToken public testToken;
|
||||
|
||||
mapping(bytes32 => address) public wallets;
|
||||
|
||||
// Arguments are deployed contracts/addresses
|
||||
constructor(Verifier v, MailServer m, TestEmailToken t) {
|
||||
// Do dig TXT outgoing._domainkey.twitter.com to verify these.
|
||||
// This is the base 2^121 representation of that key.
|
||||
// Circom bigint: represent a = a[0] + a[1] * 2**n + .. + a[k - 1] * 2**(n * k)
|
||||
require(rsa_modulus_chunks_len + body_len + 1 == msg_len, "Variable counts are wrong!");
|
||||
verifier = v;
|
||||
mailServer = m;
|
||||
testToken = t;
|
||||
}
|
||||
|
||||
// TODO: Make internal
|
||||
function moveTokens(bytes32 salt1, bytes32 salt2, uint256 amount) public {
|
||||
address wallet1 = getOrCreateWallet(salt1);
|
||||
address wallet2 = getOrCreateWallet(salt2);
|
||||
|
||||
// Check for allowance and balance
|
||||
require(testToken.allowance(wallet1, address(this)) >= amount, "Allowance too low");
|
||||
require(testToken.balanceOf(wallet1) >= amount, "Insufficient balance to perform the transfer");
|
||||
testToken.transferFrom(wallet1, wallet2, amount);
|
||||
}
|
||||
|
||||
function getOrCreateWallet(bytes32 salt) internal returns (address) {
|
||||
bytes32 hashedSalt = keccak256(abi.encodePacked(salt));
|
||||
address wallet = wallets[hashedSalt];
|
||||
if (wallet == address(0)) {
|
||||
// Create wallet
|
||||
bytes memory bytecode = type(AutoApproveWallet).creationCode;
|
||||
assembly {
|
||||
wallet := create2(0, add(bytecode, 0x20), mload(bytecode), hashedSalt)
|
||||
}
|
||||
console.log("Wallet index at:");
|
||||
console.logBytes32(hashedSalt);
|
||||
console.log("Wallet address created:", wallet);
|
||||
require(wallet != address(0), "Wallet creation failed");
|
||||
wallets[hashedSalt] = wallet;
|
||||
|
||||
// TODO: Remove this mint, it's only for test token
|
||||
testToken.mint(wallet, 10 * 10 ** testToken.decimals()); // 10 tokens with 18 decimals
|
||||
|
||||
// Initialize the wallet with the token address and approver
|
||||
AutoApproveWallet(wallet).initialize(address(testToken), address(this));
|
||||
}
|
||||
return wallet;
|
||||
}
|
||||
|
||||
function convertEmailToIndex(string memory email) public pure returns (bytes32) {
|
||||
return keccak256(abi.encodePacked(convertEmailToBytes(email)));
|
||||
}
|
||||
|
||||
function convertEmailToBytes(string memory email) public pure returns (bytes32) {
|
||||
return bytes32(bytes(StringUtils.removeTrailingZeros(email)));
|
||||
}
|
||||
|
||||
// TODO: When anon, it shouldn't be possible to get this via email, you have to pass in the salt
|
||||
function getBalance(string memory email) public view returns (uint256) {
|
||||
return testToken.balanceOf(wallets[convertEmailToIndex(email)]);
|
||||
}
|
||||
|
||||
function transfer(uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c, uint256[msg_len] memory signals)
|
||||
public
|
||||
{
|
||||
// TODO no invalid signal check yet, which is fine since the zk proof does it
|
||||
// Checks: Verify proof and check signals
|
||||
// require(signals[0] == 1337, "invalid signals");
|
||||
|
||||
// 3 public signals are the masked packed message bytes, 17 are the modulus.
|
||||
uint256[] memory bodySignals = new uint256[](body_len);
|
||||
uint256[] memory rsaModulusSignals = new uint256[](header_len);
|
||||
for (uint256 i = 0; i < body_len; i++) {
|
||||
bodySignals[i] = signals[i];
|
||||
}
|
||||
for (uint256 i = body_len; i < msg_len - 1; i++) {
|
||||
rsaModulusSignals[i - body_len] = signals[i];
|
||||
}
|
||||
|
||||
// Check eth address committed to in proof matches msg.sender, to avoid doublespend and relayer-frontrunning-relayer-for-profit
|
||||
// require(address(uint160(signals[addressIndexInSignals])) == msg.sender, "Invalid address");
|
||||
|
||||
// TODO: Note that this is buggy since it is malleable
|
||||
require(!nullifier[a[0]], "Value is already true");
|
||||
nullifier[a[0]] = true;
|
||||
|
||||
// Check from/to email domains are correct [in this case, only from domain is checked]
|
||||
// Right now, we just check that any email was received from anyone at Twitter, which is good enough for now
|
||||
// We will upload the version with these domain checks soon!
|
||||
// require(_domainCheck(headerSignals), "Invalid domain");
|
||||
string memory fromEmail =
|
||||
StringUtils.convertPackedBytesToString(StringUtils.sliceArray(bodySignals, 0, 5), packSize * 4, packSize);
|
||||
string memory amount =
|
||||
StringUtils.convertPackedBytesToString(StringUtils.sliceArray(bodySignals, 5, 10), packSize * 4, packSize);
|
||||
string memory currency =
|
||||
StringUtils.convertPackedBytesToString(StringUtils.sliceArray(bodySignals, 10, 11), packSize * 4, packSize);
|
||||
string memory recipientEmail =
|
||||
StringUtils.convertPackedBytesToString(StringUtils.sliceArray(bodySignals, 11, 16), packSize * 4, packSize);
|
||||
|
||||
string memory domain = StringUtils.getDomainFromEmail(fromEmail);
|
||||
console.log(domain);
|
||||
// Verify that the public key for RSA matches the hardcoded one
|
||||
for (uint256 i = body_len; i < msg_len - 1; i++) {
|
||||
require(mailServer.isVerified(domain, i - body_len, signals[i]), "Invalid: RSA modulus not matched");
|
||||
}
|
||||
require(verifier.verifyProof(a, b, c, signals), "Invalid Proof"); // checks effects iteractions, this should come first
|
||||
console.log("Proof passed!");
|
||||
|
||||
// Print transfer data
|
||||
uint256 amountToTransfer = StringUtils.stringToUint(amount) * 10 ** testToken.decimals();
|
||||
console.log("Original from email", fromEmail);
|
||||
console.log("Original recipient email", recipientEmail);
|
||||
console.log("Original amount", amount);
|
||||
console.log("Original currency", currency);
|
||||
console.log("Transferring", amountToTransfer);
|
||||
console.log("From", fromEmail, "to", recipientEmail);
|
||||
|
||||
// Effects: Send money
|
||||
// Transfer the tokens
|
||||
moveTokens(convertEmailToBytes(fromEmail), convertEmailToBytes(recipientEmail), amountToTransfer);
|
||||
}
|
||||
|
||||
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal {
|
||||
require(from == address(0), "Cannot transfer - VerifiedEmail is soulbound");
|
||||
}
|
||||
}
|
||||
|
||||
269
src/contracts/src/WalletEmailHandlerLogic.sol
Normal file
269
src/contracts/src/WalletEmailHandlerLogic.sol
Normal file
@@ -0,0 +1,269 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
|
||||
import "@openzeppelin/contracts/utils/Strings.sol";
|
||||
import "@openzeppelin/contracts/utils/Counters.sol";
|
||||
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
|
||||
import "@openzeppelin/contracts/proxy/Proxy.sol";
|
||||
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
|
||||
|
||||
import "./WalletEmailHandler.sol";
|
||||
import "forge-std/console.sol";
|
||||
import "./StringUtils.sol";
|
||||
import "./AutoApproveWallet.sol";
|
||||
import "./TestERC20.sol";
|
||||
import "./NFTSVG.sol";
|
||||
import "./TokenRegistry.sol";
|
||||
import {Verifier} from "./Groth16VerifierWalletAnon.sol";
|
||||
import "./MailServer.sol";
|
||||
|
||||
// Defines upgradable logic
|
||||
contract WalletEmailHandlerLogic is VerifiedWalletEmailStorage, Ownable, Initializable {
|
||||
using StringUtils for *;
|
||||
|
||||
uint16 public constant packSize = 30; // Bytes in a packed item returned from circom
|
||||
|
||||
uint16 public constant body_len = 4 + 4;
|
||||
uint16 public constant rsa_modulus_chunks_len = 17;
|
||||
uint16 public constant commitment_len = 1;
|
||||
uint16 public constant msg_len = body_len + rsa_modulus_chunks_len + commitment_len; // 26
|
||||
|
||||
uint16 public constant header_len = msg_len - body_len;
|
||||
uint16 public constant addressIndexInSignals = msg_len - 1; // The last index is the commitment
|
||||
Verifier public verifier;
|
||||
TestEmailToken public testToken;
|
||||
TokenRegistry public tokenRegistry;
|
||||
MailServer mailServer;
|
||||
mapping(string => address) public defaultVerifiers;
|
||||
// Note that the data lives in the WalletEmailHandlerStorage contract
|
||||
// Arguments are deployed contracts/addresses
|
||||
|
||||
function initialize(Verifier v, MailServer m, TestEmailToken t, TokenRegistry r) public initializer {
|
||||
// Do dig TXT outgoing._domainkey.twitter.com to verify these.
|
||||
// This is the base 2^121 representation of that key.
|
||||
// Circom bigint: represent a = a[0] + a[1] * 2**n + .. + a[k - 1] * 2**(n * k)
|
||||
console.log("Entering initialize.");
|
||||
require(rsa_modulus_chunks_len + body_len + 1 == msg_len, "Variable counts are wrong!");
|
||||
verifier = v;
|
||||
mailServer = m;
|
||||
testToken = t;
|
||||
tokenRegistry = r;
|
||||
}
|
||||
|
||||
function commandString() public pure returns (string memory) {
|
||||
return "send";
|
||||
}
|
||||
|
||||
// NOTE: This is only for emergency ejects in testing deployments
|
||||
function upgradeVerifier(Verifier v) public onlyOwner {
|
||||
verifier = v;
|
||||
}
|
||||
|
||||
// NOTE: This is only for emergency ejects in testing deployments
|
||||
function migrateAllToken(uint256 fromSalt, uint256 toSalt, address token) public onlyOwner {
|
||||
address fromWallet = getOrCreateWallet(fromSalt);
|
||||
uint256 balance = IERC20(token).balanceOf(fromWallet);
|
||||
moveTokens(fromSalt, toSalt, balance, token);
|
||||
}
|
||||
|
||||
// NOTE: This is only for emergency ejects in testing deployments
|
||||
function migrateAllToken(uint256 fromSalt, uint256 toSalt, string memory tokenName) public onlyOwner {
|
||||
address tokenAddress = tokenRegistry.getTokenAddress(tokenName, getChainID());
|
||||
migrateAllToken(fromSalt, toSalt, tokenAddress);
|
||||
}
|
||||
|
||||
// NOTE: This is only for emergency ejects in testing deployments
|
||||
function migrateAllToken(bytes32 fromSalt, address toWallet, string memory tokenName) public onlyOwner {
|
||||
address tokenAddress = tokenRegistry.getTokenAddress(tokenName, getChainID());
|
||||
migrateAllToken(fromSalt, toWallet, tokenAddress);
|
||||
}
|
||||
|
||||
// NOTE: This is only for emergency ejects in testing deployments
|
||||
function migrateAllToken(bytes32 fromSalt, address toWallet, address token) public onlyOwner {
|
||||
address fromWallet = getOrCreateWallet(fromSalt);
|
||||
uint256 amount = IERC20(token).balanceOf(fromWallet);
|
||||
IERC20 tokenToUse = token == address(0) ? testToken : IERC20(token);
|
||||
require(tokenToUse.allowance(fromWallet, address(this)) >= amount, "Allowance too low");
|
||||
require(tokenToUse.balanceOf(fromWallet) >= amount, "Insufficient balance to perform the transfer");
|
||||
tokenToUse.transferFrom(fromWallet, toWallet, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Moves tokens from one wallet to another using the provided salts.
|
||||
* @param fromSalt The salt used to derive the sender's wallet address.
|
||||
* @param toSalt The salt used to derive the recipient's wallet address.
|
||||
* @param amount The amount of tokens to transfer.
|
||||
* @param token The address of the token to transfer. 0 if should use test token.
|
||||
*/
|
||||
function moveTokens(uint256 fromSalt, uint256 toSalt, uint256 amount, address token) internal {
|
||||
address toWallet = getOrCreateWallet(bytes32(toSalt));
|
||||
address fromWallet = getOrCreateWallet(bytes32(fromSalt));
|
||||
moveTokens(fromWallet, toWallet, amount, token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Moves tokens from one wallet to another using the provided wallet addresses.
|
||||
* @param fromWallet The wallet address of the sender.
|
||||
* @param toWallet The wallet address of the recipient.
|
||||
* @param amount The amount of tokens to transfer.
|
||||
* @param token The address of the token to transfer. 0 if should use test token.
|
||||
*/
|
||||
function moveTokens(address fromWallet, address toWallet, uint256 amount, address token) internal {
|
||||
IERC20 tokenToUse = token == address(0) ? testToken : IERC20(token);
|
||||
// Check for allowance and balance
|
||||
require(tokenToUse.allowance(fromWallet, address(this)) >= amount, "Allowance too low");
|
||||
require(tokenToUse.balanceOf(fromWallet) >= amount, "Insufficient balance to perform the transfer");
|
||||
tokenToUse.transferFrom(fromWallet, toWallet, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the wallet address associated with the given salt. If the wallet does not exist, it creates a new one and gives it 10 TestTokens.
|
||||
* @param salt The salt used to derive the wallet address.
|
||||
* @return wallet The wallet address associated with the given salt.
|
||||
*/
|
||||
function getOrCreateWallet(uint256 salt) public returns (address) {
|
||||
return getOrCreateWallet(bytes32(salt));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the wallet address associated with the given salt. If the wallet does not exist, it creates a new one and gives it 10 TestTokens.
|
||||
* @param salt The salt used to derive the wallet address.
|
||||
* @return wallet The wallet address associated with the given salt.
|
||||
*/
|
||||
function getOrCreateWallet(bytes32 salt) public returns (address) {
|
||||
return getOrCreateWallet(salt, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the wallet address associated with the given salt. If the wallet does not exist, it creates a new one and gives it 10 TestTokens.
|
||||
* @param salt The salt used to derive the wallet address.
|
||||
* @param allowedToCreateWallet A boolean flag indicating if a new wallet is authorized to be created if it does not exist. True if the message id matches an email.
|
||||
* @return wallet The wallet address associated with the given salt.
|
||||
*/
|
||||
function getOrCreateWallet(uint256 salt, bool allowedToCreateWallet) internal returns (address) {
|
||||
return getOrCreateWallet(bytes32(salt), allowedToCreateWallet);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the wallet address associated with the given salt. If the wallet does not exist and allowedToCreateWallet is true, it creates a new one and gives it 10 TestTokens.
|
||||
* @param salt The salt used to derive the wallet address.
|
||||
* @param allowedToCreateWallet A boolean flag indicating if a new wallet is authorized to be created if it does not exist.
|
||||
* @return wallet The wallet address associated with the given salt.
|
||||
*/
|
||||
function getOrCreateWallet(bytes32 salt, bool allowedToCreateWallet) internal returns (address) {
|
||||
address wallet = wallets[salt];
|
||||
if (wallet == address(0) && allowedToCreateWallet) {
|
||||
// Create wallet
|
||||
bytes memory bytecode = type(AutoApproveWallet).creationCode;
|
||||
assembly {
|
||||
wallet := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
|
||||
}
|
||||
console.log("Wallet index at:");
|
||||
console.logBytes32(salt);
|
||||
console.log("Wallet address created:", wallet);
|
||||
require(wallet != address(0), "Wallet creation failed");
|
||||
wallets[salt] = wallet;
|
||||
|
||||
// TODO: Remove this mint, it's only for test token
|
||||
testToken.mint(wallet, 10 * 10 ** testToken.decimals()); // 10 tokens with 18 decimals
|
||||
|
||||
// Initialize the wallet with the token address and approver
|
||||
AutoApproveWallet(wallet).initialize(address(testToken), address(this));
|
||||
}
|
||||
return wallet;
|
||||
}
|
||||
|
||||
// OLD DEPRECATED PUBLIC WALLET HELPER FUNCTIONS
|
||||
// function convertEmailToIndex(string memory email) public pure returns (bytes32) {
|
||||
// // EDIT: Take MIMC here.
|
||||
// return keccak256(abi.encodePacked(convertEmailToBytes(email)));
|
||||
// }
|
||||
|
||||
// function convertEmailToBytes(string memory email) public pure returns (bytes32) {
|
||||
// return bytes32(bytes(StringUtils.removeTrailingZeros(email)));
|
||||
// }
|
||||
|
||||
// // NOTE: Calling this function will break your anonymity to a light/full node.
|
||||
// function getBalance(string memory email, string memory salt) public view returns (uint256) {
|
||||
// return testToken.balanceOf(wallets[convertEmailToIndex(email)]);
|
||||
// }
|
||||
|
||||
// MAIN TRANSFER FUNCTION
|
||||
function transfer(uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c, uint256[msg_len] memory signals)
|
||||
public
|
||||
{
|
||||
// TODO no invalid signal check yet, which is fine since the zk proof does it
|
||||
// Checks: Verify proof and check signals
|
||||
// require(signals[0] == 1337, "invalid signals");
|
||||
|
||||
// 3 public signals are the masked packed message bytes, 17 are the modulus.
|
||||
uint256[] memory bodySignals = new uint256[](body_len);
|
||||
uint256[] memory rsaModulusSignals = new uint256[](header_len);
|
||||
for (uint256 i = 0; i < body_len; i++) {
|
||||
bodySignals[i] = signals[i];
|
||||
}
|
||||
for (uint256 i = body_len; i < msg_len - 1; i++) {
|
||||
rsaModulusSignals[i - body_len] = signals[i];
|
||||
}
|
||||
|
||||
// Check eth address committed to in proof matches msg.sender, to avoid doublespend and relayer-frontrunning-relayer-for-profit
|
||||
// require(address(uint160(signals[addressIndexInSignals])) == msg.sender, "Invalid address");
|
||||
|
||||
// TODO: Must edit generate_input to have a unique value for "address" for this nullifier to pass
|
||||
require(!nullifier[signals[msg_len - 1]], "Value is already true");
|
||||
nullifier[signals[msg_len - 1]] = true;
|
||||
|
||||
// Check from/to email domains are correct [in this case, only from domain is checked]
|
||||
// We will upload the version with these domain checks soon!
|
||||
// require(_domainCheck(headerSignals), "Invalid domain");
|
||||
string memory command =
|
||||
StringUtils.convertPackedBytesToString(StringUtils.sliceArray(bodySignals, 0, 1), packSize, packSize);
|
||||
string memory amount =
|
||||
StringUtils.convertPackedBytesToString(StringUtils.sliceArray(bodySignals, 1, 2), packSize, packSize);
|
||||
string memory currency =
|
||||
StringUtils.convertPackedBytesToString(StringUtils.sliceArray(bodySignals, 3, 4), packSize, packSize);
|
||||
bool canCreateFromWallet = bodySignals[4] == 1;
|
||||
uint256 fromSalt = bodySignals[5];
|
||||
bool canCreateToWallet = bodySignals[6] == 1;
|
||||
uint256 toSalt = bodySignals[7];
|
||||
|
||||
// Require that the user is calling with the correct command
|
||||
require(StringUtils.stringEq(StringUtils.lower(command), commandString()));
|
||||
|
||||
string memory additionalInfo = StringUtils.convertPackedBytesToString(
|
||||
StringUtils.sliceArray(bodySignals, msg_len - 1, msg_len), packSize, packSize
|
||||
);
|
||||
string memory domain = additionalInfo; // Change this later to actually parse the domain
|
||||
|
||||
// Verify that the public key for RSA matches the hardcoded one
|
||||
for (uint256 i = body_len; i < msg_len - 1; i++) {
|
||||
require(mailServer.isVerified(domain, i - body_len, signals[i]), "Invalid: RSA modulus not matched");
|
||||
}
|
||||
require(verifier.verifyProof(a, b, c, signals), "Invalid Proof"); // checks effects iteractions, this should come first
|
||||
console.log("Proof passed!");
|
||||
|
||||
// Print transfer data
|
||||
uint256 amountToTransfer = StringUtils.stringToUint(amount) * 10 ** testToken.decimals();
|
||||
console.log("Original from salt", fromSalt);
|
||||
console.log("Original recipient salt", toSalt);
|
||||
console.log("Original amount", amount);
|
||||
console.log("Original currency", currency);
|
||||
console.log("Transferring", amountToTransfer);
|
||||
console.log("From", fromSalt, "to", toSalt);
|
||||
|
||||
// Effects: Send money
|
||||
// Transfer the tokens
|
||||
moveTokens(fromSalt, toSalt, amountToTransfer, address(testToken));
|
||||
}
|
||||
|
||||
function getChainID() public view returns (uint256) {
|
||||
uint256 chainId;
|
||||
assembly {
|
||||
chainId := chainid()
|
||||
}
|
||||
return chainId;
|
||||
}
|
||||
}
|
||||
11
src/contracts/src/WalletEmailHandlerProxy.sol
Normal file
11
src/contracts/src/WalletEmailHandlerProxy.sol
Normal file
@@ -0,0 +1,11 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "@openzeppelin/contracts/proxy/Proxy.sol";
|
||||
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
|
||||
|
||||
contract WalletEmailHandlerProxy is TransparentUpgradeableProxy {
|
||||
constructor(address logic, address admin, bytes memory data)
|
||||
TransparentUpgradeableProxy(logic, admin, data)
|
||||
{}
|
||||
}
|
||||
1780
src/contracts/src/test/MIMC.sol
Normal file
1780
src/contracts/src/test/MIMC.sol
Normal file
File diff suppressed because it is too large
Load Diff
@@ -180,7 +180,7 @@ contract TwitterUtilsTest is Test {
|
||||
assert(bytes(svgValue).length > 0);
|
||||
}
|
||||
|
||||
function testChainID() public {
|
||||
function testChainID() public view {
|
||||
uint256 chainId;
|
||||
assembly {
|
||||
chainId := chainid()
|
||||
|
||||
@@ -3,9 +3,12 @@ pragma solidity ^0.8.0;
|
||||
import "forge-std/Test.sol";
|
||||
import "forge-std/console.sol";
|
||||
import "../WalletEmailHandler.sol";
|
||||
import "../WalletEmailHandlerLogic.sol";
|
||||
import "../WalletEmailHandlerProxy.sol";
|
||||
import "../TestERC20.sol";
|
||||
import "../StringUtils.sol";
|
||||
import "../Groth16VerifierWallet.sol";
|
||||
import "../Groth16VerifierWalletAnon.sol";
|
||||
import "./MIMC.sol";
|
||||
|
||||
contract WalletUtilsTest is Test {
|
||||
using StringUtils for *;
|
||||
@@ -16,16 +19,36 @@ contract WalletUtilsTest is Test {
|
||||
uint16 public constant packSize = 30;
|
||||
uint16 public constant body_len = 4 * 4;
|
||||
|
||||
VerifiedWalletEmail testVerifier;
|
||||
WalletEmailHandlerProxy testVerifier;
|
||||
MailServer mailServer;
|
||||
Verifier proofVerifier;
|
||||
WalletEmailHandlerLogic logic;
|
||||
TokenRegistry tokenRegistry;
|
||||
TestEmailToken erc20;
|
||||
|
||||
function setUp() public {
|
||||
proofVerifier = new Verifier();
|
||||
mailServer = new MailServer();
|
||||
erc20 = new TestEmailToken(5000);
|
||||
testVerifier = new VerifiedWalletEmail(proofVerifier, mailServer, erc20);
|
||||
logic = new WalletEmailHandlerLogic();
|
||||
tokenRegistry = new TokenRegistry();
|
||||
address admin = msg.sender;
|
||||
console.log("This address:");
|
||||
console.log(address(this));
|
||||
console.log("Caller/admin address:");
|
||||
console.log(msg.sender);
|
||||
// Initialize logic
|
||||
logic.initialize(proofVerifier, mailServer, erc20, tokenRegistry);
|
||||
|
||||
bytes memory initData = abi.encodeWithSignature(
|
||||
"initialize(Verifier,MailServer,TestEmailToken,TokenRegistry)",
|
||||
proofVerifier,
|
||||
mailServer,
|
||||
erc20,
|
||||
tokenRegistry
|
||||
);
|
||||
// TODO: Fix admin in place of address(this)
|
||||
testVerifier = new WalletEmailHandlerProxy(address(logic), address(this), initData);
|
||||
}
|
||||
|
||||
// Old unpacks
|
||||
@@ -102,109 +125,33 @@ contract WalletUtilsTest is Test {
|
||||
|
||||
function testUnpackIntoString_Pack30_1() public {
|
||||
uint256[] memory packedBytes = new uint256[](1);
|
||||
packedBytes[0] = 2097152;
|
||||
packedBytes[0] = 12544;
|
||||
string memory byteList = StringUtils.convertPackedBytesToString(packedBytes, 30, packSize);
|
||||
string memory intended_value = "dai";
|
||||
string memory intended_value = "1";
|
||||
console.logString(byteList);
|
||||
assertEq(bytes32(bytes(byteList)), bytes32(bytes(intended_value)));
|
||||
}
|
||||
|
||||
function testUnpackIntoString_Pack30_2() public {
|
||||
uint256[] memory packedBytes = new uint256[](1);
|
||||
packedBytes[0] = 452605509681;
|
||||
packedBytes[0] = 452605509632;
|
||||
string memory byteList = StringUtils.convertPackedBytesToString(packedBytes, 30, packSize);
|
||||
string memory intended_value = "2";
|
||||
string memory intended_value = "dai";
|
||||
console.logString(byteList);
|
||||
assertEq(bytes32(bytes(byteList)), bytes32(bytes(intended_value)));
|
||||
}
|
||||
|
||||
// Should pass (note that there are extra 0 bytes, which are filtered out but should be noted in audits)
|
||||
function testVerifyWalletEmail() public {
|
||||
uint256[34] memory publicSignals;
|
||||
publicSignals[0] = 30515164652858234;
|
||||
publicSignals[1] = 14207229598262646;
|
||||
publicSignals[2] = 13067048790615872;
|
||||
publicSignals[3] = 7171939;
|
||||
publicSignals[4] = 0;
|
||||
publicSignals[5] = 3485236;
|
||||
publicSignals[6] = 0;
|
||||
publicSignals[7] = 0;
|
||||
publicSignals[8] = 0;
|
||||
publicSignals[9] = 0;
|
||||
publicSignals[10] = 13661285;
|
||||
publicSignals[11] = 30515164652858234;
|
||||
publicSignals[12] = 18147879272211830;
|
||||
publicSignals[13] = 27917065853693287;
|
||||
publicSignals[14] = 28015;
|
||||
publicSignals[15] = 0;
|
||||
publicSignals[16] = 2645260732387577900369388087711111123;
|
||||
publicSignals[17] = 2332356685544126002119529566553287568;
|
||||
publicSignals[18] = 587306946802222480578301599869128605;
|
||||
publicSignals[19] = 1506808391343308562602228807782956759;
|
||||
publicSignals[20] = 346696857027646434280628892032962406;
|
||||
publicSignals[21] = 1655371642328152796841392591809876356;
|
||||
publicSignals[22] = 773654757689631205903545947464515700;
|
||||
publicSignals[23] = 137546842031326636154929265514533208;
|
||||
publicSignals[24] = 979104436480501594376401576155183314;
|
||||
publicSignals[25] = 1231402749194646866996172591430155068;
|
||||
publicSignals[26] = 1573385231473380013164181608611759098;
|
||||
publicSignals[27] = 1199794061179553911325952711127005960;
|
||||
publicSignals[28] = 1393369642957971131987926230229916984;
|
||||
publicSignals[29] = 2610100650498432208787557818514105421;
|
||||
publicSignals[30] = 1405475120223887084339881602469286332;
|
||||
publicSignals[31] = 2000538708964654339221687925776343058;
|
||||
publicSignals[32] = 3483697379198011592407370076533025;
|
||||
publicSignals[33] = 0;
|
||||
uint256[2] memory proof_a = [
|
||||
18214528451748025070455293058606558684367776249349482399993204103864741723468,
|
||||
15003530197647463595718037429164132062637106744660222086396269550328064261424
|
||||
];
|
||||
// Note: you need to swap the order of the two elements in each subarray
|
||||
uint256[2][2] memory proof_b = [
|
||||
[
|
||||
6461911610358766053365043908758394834732672681413987884242698462904724197255,
|
||||
342103975494932482608081876029483576044074727035168137477391964391537410934
|
||||
],
|
||||
[
|
||||
18351039964982209778799207158064219024562949371673722720718374575366986849311,
|
||||
4669785024601609291633792167221088192727471283005169123961871153351390329210
|
||||
]
|
||||
];
|
||||
uint256[2] memory proof_c = [
|
||||
17308091971421169481892128502517801279695749002269857786558424203436590932091,
|
||||
14587778590638321976005513090859474748106449498450192078465868665769372103254
|
||||
];
|
||||
|
||||
// Test proof verification
|
||||
bool verified = proofVerifier.verifyProof(proof_a, proof_b, proof_c, publicSignals);
|
||||
assertEq(verified, true);
|
||||
|
||||
// Test mint after spoofing msg.sender
|
||||
// Vm vm = Vm(VM_ADDR);
|
||||
// vm.startPrank(0x0000000000000000000000000000000000000001);
|
||||
// testVerifier.transfer(proof_a, proof_b, proof_c, publicSignals);
|
||||
// vm.stopPrank();
|
||||
}
|
||||
|
||||
// Should pass (note that there are extra 0 bytes, which are filtered out but should be noted in audits)function testTransferWalletEmail3() public {
|
||||
function testTransferWalletEmail3() public {
|
||||
uint256[34] memory publicSignals = [
|
||||
uint256(30515164652858234),
|
||||
18147879272211830,
|
||||
27917065853693287,
|
||||
28015,
|
||||
0,
|
||||
50,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
13762560,
|
||||
30515164652858234,
|
||||
14207229598262646,
|
||||
13067048790615872,
|
||||
7171939,
|
||||
function testVerifyWalletEmailSendVerifier() public {
|
||||
uint256[26] memory publicSignals = [
|
||||
uint256(1684956499),
|
||||
12544,
|
||||
0,
|
||||
452605509632,
|
||||
1,
|
||||
11578046119786885486589898473893761816011340408005885677852497807442621066251,
|
||||
1,
|
||||
668633821978676526869556450266953888005839843040173803440403455913247484181,
|
||||
1886180949733815343726466520516992271,
|
||||
1551366393280668736485689616947198994,
|
||||
1279057759087427731263511728885611780,
|
||||
@@ -226,24 +173,24 @@ contract WalletUtilsTest is Test {
|
||||
];
|
||||
|
||||
uint256[2] memory proof_a = [
|
||||
18568569282385577752003966587062685654688127322905645867690168113644909624209,
|
||||
18759903706259146962639961745797835986209265804220236624283397965640158483190
|
||||
4872484627504163815767110038859301103806605763419531960813764990208898018369,
|
||||
3795754906589823037161769237444876552416343748488835176598797103098367263607
|
||||
];
|
||||
|
||||
uint256[2][2] memory proof_b = [
|
||||
[
|
||||
5803446705026913357518568395981657569264671269353189435142412707651256173413,
|
||||
8593766898146870509264586194439641404493723665652266429471383540616111544172
|
||||
18376557720828688581045481496486129744102916628430359078845301368276153581701,
|
||||
21877761512995850430716476389626777330111796016898814534754595086427125573614
|
||||
],
|
||||
[
|
||||
16046700810774537572443697469030305204645791362097372667928847558873110846124,
|
||||
20178806529375442298313753931928150693393269974972769756293026303013302674806
|
||||
12159889909152109241814076562911568076239686025478424469066060467237613288152,
|
||||
15701808273441108469395513343272104829223041229728428179673134509885945260640
|
||||
]
|
||||
];
|
||||
|
||||
uint256[2] memory proof_c = [
|
||||
13905944782945043014900524454195421236229551576754549828484627488690083504903,
|
||||
21309166547782902503710040024457074452294672356307955049572131380081774653722
|
||||
15982822555429931992864851554044019444318888053001687160362952266505524933490,
|
||||
10069972634237977706980635879331410342197879055629137669963055695388053169516
|
||||
];
|
||||
|
||||
console.log("Calldata");
|
||||
@@ -256,19 +203,183 @@ contract WalletUtilsTest is Test {
|
||||
// Test mint after spoofing msg.sender
|
||||
Vm vm = Vm(VM_ADDR);
|
||||
vm.startPrank(0x0000000000000000000000000000000000000001);
|
||||
testVerifier.transfer(proof_a, proof_b, proof_c, publicSignals);
|
||||
bytes memory encodedData = abi.encodeWithSignature(
|
||||
"transfer(uint256[2],uint256[2][2],uint256[2],uint256[26])", proof_a, proof_b, proof_c, publicSignals
|
||||
);
|
||||
(bool success, bytes memory result) = address(testVerifier).delegatecall(encodedData);
|
||||
console.log(success);
|
||||
console.logBytes(result);
|
||||
vm.stopPrank();
|
||||
|
||||
assert(testVerifier.getBalance("zkemailverify@gmail.com") == 8 * 10 ** erc20.decimals());
|
||||
assert(testVerifier.getBalance("zkemailverify2@gmail.com") == 12 * 10 ** erc20.decimals());
|
||||
}
|
||||
|
||||
function testMoveERC20() public {
|
||||
string memory fromEmail = "zkemailverify@gmail.com";
|
||||
string memory recipientEmail = "zkemailverify2@gmail.com";
|
||||
uint256 amountToTransfer = 1 * 10 ** erc20.decimals();
|
||||
testVerifier.moveTokens(bytes32(bytes(fromEmail)), bytes32(bytes(recipientEmail)), amountToTransfer);
|
||||
assert(testVerifier.getBalance(fromEmail) == 9 * 10 ** erc20.decimals());
|
||||
assert(testVerifier.getBalance(recipientEmail) == 11 * 10 ** erc20.decimals());
|
||||
// Should pass (note that there are extra 0 bytes, which are filtered out but should be noted in audits)function testTransferWalletEmail3() public {
|
||||
// function testTransferWalletEmailSendVerifier2() public {
|
||||
// uint256[34] memory publicSignals = [
|
||||
// uint256(30515164652858234),
|
||||
// 18147879272211830,
|
||||
// 27917065853693287,
|
||||
// 28015,
|
||||
// 0,
|
||||
// 50,
|
||||
// 0,
|
||||
// 0,
|
||||
// 0,
|
||||
// 0,
|
||||
// 13762560,
|
||||
// 30515164652858234,
|
||||
// 14207229598262646,
|
||||
// 13067048790615872,
|
||||
// 7171939,
|
||||
// 0,
|
||||
// 1886180949733815343726466520516992271,
|
||||
// 1551366393280668736485689616947198994,
|
||||
// 1279057759087427731263511728885611780,
|
||||
// 1711061746895435768547617398484429347,
|
||||
// 2329140368326888129406637741054282011,
|
||||
// 2094858442222190249786465516374057361,
|
||||
// 2584558507302599829894674874442909655,
|
||||
// 1521552483858643935889582214011445675,
|
||||
// 176847449040377757035522930003764000,
|
||||
// 632921959964166974634188077062540145,
|
||||
// 2172441457165086627497230906075093832,
|
||||
// 248112436365636977369105357296082574,
|
||||
// 1408592841800630696650784801114783401,
|
||||
// 364610811473321782531041012695979858,
|
||||
// 342338521965453258686441392321054163,
|
||||
// 2269703683857229911110544415296249295,
|
||||
// 3643644972862751728748413716653892,
|
||||
// 0
|
||||
// ];
|
||||
|
||||
// uint256[2] memory proof_a = [
|
||||
// 18568569282385577752003966587062685654688127322905645867690168113644909624209,
|
||||
// 18759903706259146962639961745797835986209265804220236624283397965640158483190
|
||||
// ];
|
||||
|
||||
// uint256[2][2] memory proof_b = [
|
||||
// [
|
||||
// 5803446705026913357518568395981657569264671269353189435142412707651256173413,
|
||||
// 8593766898146870509264586194439641404493723665652266429471383540616111544172
|
||||
// ],
|
||||
// [
|
||||
// 16046700810774537572443697469030305204645791362097372667928847558873110846124,
|
||||
// 20178806529375442298313753931928150693393269974972769756293026303013302674806
|
||||
// ]
|
||||
// ];
|
||||
|
||||
// uint256[2] memory proof_c = [
|
||||
// 13905944782945043014900524454195421236229551576754549828484627488690083504903,
|
||||
// 21309166547782902503710040024457074452294672356307955049572131380081774653722
|
||||
// ];
|
||||
|
||||
// console.log("Calldata");
|
||||
// console.logBytes(abi.encode(proof_a, proof_b, proof_c, publicSignals));
|
||||
|
||||
// // Test proof verification
|
||||
// bool verified = proofVerifier.verifyProof(proof_a, proof_b, proof_c, publicSignals);
|
||||
// assertEq(verified, true);
|
||||
|
||||
// // Test mint after spoofing msg.sender
|
||||
// Vm vm = Vm(VM_ADDR);
|
||||
// vm.startPrank(0x0000000000000000000000000000000000000001);
|
||||
// bytes memory encodedData = abi.encodeWithSignature(
|
||||
// "transfer(uint256[2],uint256[2][2],uint256[2],uint256[26])",
|
||||
// proof_a, proof_b, proof_c, publicSignals
|
||||
// );
|
||||
// (bool success, bytes memory result) = address(testVerifier).delegatecall(encodedData);
|
||||
|
||||
// vm.stopPrank();
|
||||
|
||||
// assert(testVerifier.getBalance("zkemailverify@gmail.com") == 8 * 10 ** erc20.decimals());
|
||||
// assert(testVerifier.getBalance("zkemailverify2@gmail.com") == 12 * 10 ** erc20.decimals());
|
||||
// }
|
||||
|
||||
// Should pass (note that there are extra 0 bytes, which are filtered out but should be noted in audits)function testTransferWalletEmail3() public {
|
||||
// function testTransferWalletEmailCommandVerifier() public {
|
||||
// uint256[34] memory publicSignals = [
|
||||
// uint256(30515164652858234),
|
||||
// 18147879272211830,
|
||||
// 27917065853693287,
|
||||
// 28015,
|
||||
// 0,
|
||||
// 50,
|
||||
// 0,
|
||||
// 0,
|
||||
// 0,
|
||||
// 0,
|
||||
// 13762560,
|
||||
// 30515164652858234,
|
||||
// 14207229598262646,
|
||||
// 13067048790615872,
|
||||
// 7171939,
|
||||
// 0,
|
||||
// 1886180949733815343726466520516992271,
|
||||
// 1551366393280668736485689616947198994,
|
||||
// 1279057759087427731263511728885611780,
|
||||
// 1711061746895435768547617398484429347,
|
||||
// 2329140368326888129406637741054282011,
|
||||
// 2094858442222190249786465516374057361,
|
||||
// 2584558507302599829894674874442909655,
|
||||
// 1521552483858643935889582214011445675,
|
||||
// 176847449040377757035522930003764000,
|
||||
// 632921959964166974634188077062540145,
|
||||
// 2172441457165086627497230906075093832,
|
||||
// 248112436365636977369105357296082574,
|
||||
// 1408592841800630696650784801114783401,
|
||||
// 364610811473321782531041012695979858,
|
||||
// 342338521965453258686441392321054163,
|
||||
// 2269703683857229911110544415296249295,
|
||||
// 3643644972862751728748413716653892,
|
||||
// 0
|
||||
// ];
|
||||
|
||||
// uint256[2] memory proof_a = [
|
||||
// 18568569282385577752003966587062685654688127322905645867690168113644909624209,
|
||||
// 18759903706259146962639961745797835986209265804220236624283397965640158483190
|
||||
// ];
|
||||
|
||||
// uint256[2][2] memory proof_b = [
|
||||
// [
|
||||
// 5803446705026913357518568395981657569264671269353189435142412707651256173413,
|
||||
// 8593766898146870509264586194439641404493723665652266429471383540616111544172
|
||||
// ],
|
||||
// [
|
||||
// 16046700810774537572443697469030305204645791362097372667928847558873110846124,
|
||||
// 20178806529375442298313753931928150693393269974972769756293026303013302674806
|
||||
// ]
|
||||
// ];
|
||||
|
||||
// uint256[2] memory proof_c = [
|
||||
// 13905944782945043014900524454195421236229551576754549828484627488690083504903,
|
||||
// 21309166547782902503710040024457074452294672356307955049572131380081774653722
|
||||
// ];
|
||||
|
||||
// console.log("Calldata");
|
||||
// console.logBytes(abi.encode(proof_a, proof_b, proof_c, publicSignals));
|
||||
|
||||
// // Test proof verification
|
||||
// bool verified = proofVerifier.verifyProof(proof_a, proof_b, proof_c, publicSignals);
|
||||
// assertEq(verified, true);
|
||||
|
||||
// // Test mint after spoofing msg.sender
|
||||
// Vm vm = Vm(VM_ADDR);
|
||||
// vm.startPrank(0x0000000000000000000000000000000000000001);
|
||||
// testVerifier.transfer(proof_a, proof_b, proof_c, publicSignals);
|
||||
// vm.stopPrank();
|
||||
|
||||
// assert(testVerifier.getBalance("zkemailverify@gmail.com") == 8 * 10 ** erc20.decimals());
|
||||
// assert(testVerifier.getBalance("zkemailverify2@gmail.com") == 12 * 10 ** erc20.decimals());
|
||||
// }
|
||||
|
||||
function testMigrateAllERC20() public {
|
||||
uint256 fromSalt = 11578046119786885486589898473893761816011340408005885677852497807442621066251;
|
||||
uint256 toSalt = 668633821978676526869556450266953888005839843040173803440403455913247484181;
|
||||
bytes memory encodedData =
|
||||
abi.encodeWithSignature("migrateAllToken(uint256,uint256,string)", fromSalt, toSalt, "DAI");
|
||||
(bool success, bytes memory result) = address(testVerifier).delegatecall(encodedData);
|
||||
console.log(success);
|
||||
console.logBytes(result);
|
||||
// assert(testVerifier.getBalance(fromEmail) == 9 * 10 ** erc20.decimals());
|
||||
// assert(testVerifier.getBalance(recipientEmail) == 11 * 10 ** erc20.decimals());
|
||||
}
|
||||
}
|
||||
|
||||
145
yarn.lock
145
yarn.lock
@@ -2503,16 +2503,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@iden3/binfileutils@npm:0.0.10":
|
||||
version: 0.0.10
|
||||
resolution: "@iden3/binfileutils@npm:0.0.10"
|
||||
dependencies:
|
||||
fastfile: 0.0.19
|
||||
ffjavascript: ^0.2.48
|
||||
checksum: cdeb8ac01e12f485d9fb236654c00d5d5016fc89eae24f7822885dd42f09935cbef601dbdd8a0c96dfb00ded9f4f623e0eec0b568aa86d16522cf77ce6f9498b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@iden3/binfileutils@npm:0.0.11":
|
||||
version: 0.0.11
|
||||
resolution: "@iden3/binfileutils@npm:0.0.11"
|
||||
@@ -6295,13 +6285,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"big-integer@npm:^1.6.42, big-integer@npm:^1.6.48":
|
||||
version: 1.6.51
|
||||
resolution: "big-integer@npm:1.6.51"
|
||||
checksum: 3d444173d1b2e20747e2c175568bedeebd8315b0637ea95d75fd27830d3b8e8ba36c6af40374f36bdaea7b5de376dcada1b07587cb2a79a928fccdb6e6e3c518
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"big.js@npm:^5.2.2":
|
||||
version: 5.2.2
|
||||
resolution: "big.js@npm:5.2.2"
|
||||
@@ -7324,17 +7307,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"circom_runtime@npm:0.1.17":
|
||||
version: 0.1.17
|
||||
resolution: "circom_runtime@npm:0.1.17"
|
||||
dependencies:
|
||||
ffjavascript: 0.2.48
|
||||
bin:
|
||||
calcwit: calcwit.js
|
||||
checksum: 595fc0cc3a62ba5daf8d849feae41c48805c0df43965f85dde4dc434efb607e455fa7801d41c1feacfe0c3c71952a45cd3985abf26fde40c54138392891afd8c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"circom_runtime@npm:0.1.21":
|
||||
version: 0.1.21
|
||||
resolution: "circom_runtime@npm:0.1.21"
|
||||
@@ -7346,6 +7318,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"circom_runtime@npm:0.1.22":
|
||||
version: 0.1.22
|
||||
resolution: "circom_runtime@npm:0.1.22"
|
||||
dependencies:
|
||||
ffjavascript: 0.2.57
|
||||
bin:
|
||||
calcwit: calcwit.js
|
||||
checksum: bf7b2e9f74cd7704ebc45ce686d4df49e58ed09114070a98beaab90e5ff7784d1943468ea3315bd4db638e6a76cda24e8b610aa2cd50be56adb4391e20469366
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"circom_tester@npm:^0.0.19":
|
||||
version: 0.0.19
|
||||
resolution: "circom_tester@npm:0.0.19"
|
||||
@@ -9085,7 +9068,7 @@ __metadata:
|
||||
readline: ^1.3.0
|
||||
selenium-webdriver: ^4.8.1
|
||||
serve: ^14.0.1
|
||||
snarkjs: "git+https://github.com/vb7401/snarkjs.git#24981febe8826b6ab76ae4d76cf7f9142919d2b8"
|
||||
snarkjs: latest
|
||||
sshpk: ^1.17.0
|
||||
styled-components: ^5.3.5
|
||||
ts-node: ^10.9.1
|
||||
@@ -10519,13 +10502,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fastfile@npm:0.0.19, fastfile@npm:^0.0.19":
|
||||
version: 0.0.19
|
||||
resolution: "fastfile@npm:0.0.19"
|
||||
checksum: 6179bdd7c21be9882294dae66103795c099594098b51958bcf08a4545c91387321b43511730d0542a5a9ed8c5ec9069c065e065fd67255453ac900a23895dac1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fastfile@npm:0.0.20":
|
||||
version: 0.0.20
|
||||
resolution: "fastfile@npm:0.0.20"
|
||||
@@ -10607,18 +10583,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ffjavascript@npm:0.2.48":
|
||||
version: 0.2.48
|
||||
resolution: "ffjavascript@npm:0.2.48"
|
||||
dependencies:
|
||||
big-integer: ^1.6.48
|
||||
wasmbuilder: ^0.0.12
|
||||
wasmcurves: 0.1.0
|
||||
web-worker: ^1.2.0
|
||||
checksum: 68beae9a4f642c06656685353b84fd7655020ca0e628ea046e94452ab779587953cc45cde106d74b68be7177b49c8f19b105d6552c4a1d715e784ae9e7c9ed34
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ffjavascript@npm:0.2.56":
|
||||
version: 0.2.56
|
||||
resolution: "ffjavascript@npm:0.2.56"
|
||||
@@ -10630,7 +10594,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ffjavascript@npm:^0.2.45":
|
||||
"ffjavascript@npm:0.2.57, ffjavascript@npm:^0.2.45":
|
||||
version: 0.2.57
|
||||
resolution: "ffjavascript@npm:0.2.57"
|
||||
dependencies:
|
||||
@@ -18002,18 +17966,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"r1csfile@npm:0.0.35":
|
||||
version: 0.0.35
|
||||
resolution: "r1csfile@npm:0.0.35"
|
||||
dependencies:
|
||||
"@iden3/bigarray": 0.0.2
|
||||
"@iden3/binfileutils": 0.0.10
|
||||
fastfile: 0.0.19
|
||||
ffjavascript: 0.2.48
|
||||
checksum: 84f7b4eab5bcdd6a3f6d699998c9479a5eff8d670383d4f0c5afc08431f45353abab9a8b07eeabaef89807e24b0ba50611d4d6280eb6c3a7483e1487a91f0ac6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"r1csfile@npm:0.0.41, r1csfile@npm:^0.0.41":
|
||||
version: 0.0.41
|
||||
resolution: "r1csfile@npm:0.0.41"
|
||||
@@ -18026,6 +17978,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"r1csfile@npm:0.0.45":
|
||||
version: 0.0.45
|
||||
resolution: "r1csfile@npm:0.0.45"
|
||||
dependencies:
|
||||
"@iden3/bigarray": 0.0.2
|
||||
"@iden3/binfileutils": 0.0.11
|
||||
fastfile: 0.0.20
|
||||
ffjavascript: 0.2.57
|
||||
checksum: ae2d7ab3f2c37640aea2b4f45753d1f2258f5d904a51d7aaff67c32a931c3e90d22d257e8f10752044fa36b3ac31516f60e503f858913a625015b9b05575ba47
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"raf@npm:^3.4.1":
|
||||
version: 3.4.1
|
||||
resolution: "raf@npm:3.4.1"
|
||||
@@ -19778,26 +19742,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"snarkjs@git+https://github.com/vb7401/snarkjs.git#24981febe8826b6ab76ae4d76cf7f9142919d2b8":
|
||||
version: 0.4.12
|
||||
resolution: "snarkjs@https://github.com/vb7401/snarkjs.git#commit=24981febe8826b6ab76ae4d76cf7f9142919d2b8"
|
||||
dependencies:
|
||||
"@iden3/binfileutils": 0.0.10
|
||||
blake2b-wasm: ^2.4.0
|
||||
circom_runtime: 0.1.17
|
||||
ejs: ^3.1.6
|
||||
fastfile: ^0.0.19
|
||||
ffjavascript: 0.2.48
|
||||
js-sha3: ^0.8.0
|
||||
logplease: ^1.2.15
|
||||
r1csfile: 0.0.35
|
||||
readline: ^1.3.0
|
||||
bin:
|
||||
snarkjs: build/cli.cjs
|
||||
checksum: 9011df4b58475a0b4ae988f8b459a9a4d2bb5d2b60221d0ec370a10f2492c88909768215f3b22e514b2cf24dca79818790447005a33ed6aee177b9fda6948a75
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"snarkjs@npm:0.5.0":
|
||||
version: 0.5.0
|
||||
resolution: "snarkjs@npm:0.5.0"
|
||||
@@ -19818,6 +19762,26 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"snarkjs@npm:latest":
|
||||
version: 0.6.11
|
||||
resolution: "snarkjs@npm:0.6.11"
|
||||
dependencies:
|
||||
"@iden3/binfileutils": 0.0.11
|
||||
bfj: ^7.0.2
|
||||
blake2b-wasm: ^2.4.0
|
||||
circom_runtime: 0.1.22
|
||||
ejs: ^3.1.6
|
||||
fastfile: 0.0.20
|
||||
ffjavascript: 0.2.57
|
||||
js-sha3: ^0.8.0
|
||||
logplease: ^1.2.15
|
||||
r1csfile: 0.0.45
|
||||
bin:
|
||||
snarkjs: build/cli.cjs
|
||||
checksum: 692508b6f8048b6879975844cae4b9a6713713e20fec488ebd21a4b224b7e0318f6aba59ce06d332728d184148c943fa04e3a49e0af173d325011f506e42363e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"sockjs-client@npm:^1.5.0":
|
||||
version: 1.6.1
|
||||
resolution: "sockjs-client@npm:1.6.1"
|
||||
@@ -21997,25 +21961,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"wasmbuilder@npm:^0.0.12":
|
||||
version: 0.0.12
|
||||
resolution: "wasmbuilder@npm:0.0.12"
|
||||
dependencies:
|
||||
big-integer: ^1.6.48
|
||||
checksum: 327b3c50b0e1e5e3aac9e218e0f96fdc638b7952ab86acc2ad53960371996826dbb0a8095edce482cf1d9c245d96884449701909bc962920aa7ec8241db01214
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"wasmcurves@npm:0.1.0":
|
||||
version: 0.1.0
|
||||
resolution: "wasmcurves@npm:0.1.0"
|
||||
dependencies:
|
||||
big-integer: ^1.6.42
|
||||
blakejs: ^1.1.0
|
||||
checksum: 6bf6719e659a88904af0b98d152316e3b22435ca6a2cfc8bbf4530576806f17b2776b2c7d91d1a678fe0d51485a0d1748efcd080808c181c7977bee50b26efa9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"wasmcurves@npm:0.2.0":
|
||||
version: 0.2.0
|
||||
resolution: "wasmcurves@npm:0.2.0"
|
||||
|
||||
Reference in New Issue
Block a user