Browse Source

Update to SMTProcessor for deposits

master
arnaucube 4 years ago
parent
commit
6d0a595525
6 changed files with 95 additions and 174 deletions
  1. +35
    -74
      circuits/deposit.circom
  2. +11
    -11
      contracts/deposit-verifier.sol
  3. +10
    -10
      contracts/withdraw-verifier.sol
  4. +13
    -38
      src/miksi.ts
  5. +14
    -26
      test/circuits/deposit.test.ts
  6. +12
    -15
      test/contracts/miksi.test.ts

+ 35
- 74
circuits/deposit.circom

@ -1,41 +1,38 @@
/* /*
# deposit.circom # deposit.circom
+----------+ +----------+
| | | |
PRI_secret+--------->+ Poseidon +<----+PUB_key PRI_secret+--------->+ Poseidon +<----+PUB_key
| | | + | | | +
| +----------+ |
| nullifier |
| + |
| | | +----------+
| v | | |
| +----+-----+ +---->+ SMT |
+--------->+ | | Poseidon +<------+PUB_rootOld
| +-----+------->+ Verifier |
PUB_coinCode+------->+ Poseidon | | | Non |
| | | | Existance+<------+PRI_siblings
PUB_amount+--------->+ | | | | +
+----------+ | +----------+ |
| |
| |
| +----------+ |
| | | |
| | | |
+----+ | | SMT +<---------+
PUB_commitment+----> == +<------------+------->+ Poseidon |
+----+ | Verifier |
| +<------+PUB_rootNew
| |
+----------+
| +----------+ | +----------+
| nullifier | | +<------+PUB_rootOld
| + | | |
| | | | +<------+PUB_rootNew
| v | | SMT |
| +----+-----+ +---->+ Poseidon +<------+PRI_oldKey
+--------->+ | | Verifier |
| +-----+------->+ (insert) +<------+PRI_oldValue
PUB_coinCode+------->+ Poseidon | | | |
| | | | +<------+PRI_isOld0
PUB_amount+--------->+ | | | |
+----------+ | | +<------+PRI_siblings
| +----------+
|
|
|
|
+----+ |
PUB_commitment+----> == +<------------+
+----+
*/ */
include "../node_modules/circomlib/circuits/comparators.circom"; include "../node_modules/circomlib/circuits/comparators.circom";
include "../node_modules/circomlib/circuits/poseidon.circom"; include "../node_modules/circomlib/circuits/poseidon.circom";
include "../node_modules/circomlib/circuits/smt/smtverifier.circom";
include "../node_modules/circomlib/circuits/smt/smtprocessor.circom";
template Deposit(nLevels) { template Deposit(nLevels) {
signal input coinCode; signal input coinCode;
@ -43,8 +40,8 @@ template Deposit(nLevels) {
signal private input secret; signal private input secret;
signal private input oldKey; signal private input oldKey;
signal private input oldValue; signal private input oldValue;
signal private input siblingsOld[nLevels];
signal private input siblingsNew[nLevels];
signal private input isOld0;
signal private input siblings[nLevels];
signal input rootOld; signal input rootOld;
signal input rootNew; signal input rootNew;
signal input commitment; signal input commitment;
@ -65,54 +62,18 @@ template Deposit(nLevels) {
comCheck.in[1] <== commitment; comCheck.in[1] <== commitment;
comCheck.out === 1; comCheck.out === 1;
// TODO instead of 2 siblings input, get siblingsOld from
// siblingsNew[len-1] both siblingsOld & siblingsNew have same values
// except for one, can be merged into one, to ensure that the circuit
// checks that the leaf non existing under rootOld is in the same
// position than the check that the leaf exists under the rootNew
// check that nLevels-1 siblings match from siblingsOld & siblingsNew
component siblEq[nLevels];
signal count[nLevels];
for (var i=0; i<nLevels; i++) {
siblEq[i] = IsEqual();
siblEq[i].in[0] <== siblingsOld[i];
siblEq[i].in[1] <== siblingsNew[i];
if (i==0) {
count[0] <== siblEq[i].out;
} else {
count[i] <== siblEq[i].out + count[i-1];
}
}
component countCheck = IsEqual();
countCheck.in[0] <== count[nLevels-1];
countCheck.in[1] <== nLevels-1;
countCheck.out === 1;
component smtOld = SMTVerifier(nLevels);
smtOld.enabled <== 1;
smtOld.fnc <== 1;
smtOld.root <== rootOld;
for (var i=0; i<nLevels; i++) {
smtOld.siblings[i] <== siblingsOld[i];
}
/* smtOld.oldKey <== 1; */
smtOld.oldKey <== oldKey;
smtOld.oldValue <== oldValue;
smtOld.isOld0 <== 0;
smtOld.key <== key;
smtOld.value <== hash.out;
component smtNew = SMTVerifier(nLevels);
smtNew.enabled <== 1;
smtNew.fnc <== 0;
smtNew.root <== rootNew;
component smtProcessor = SMTProcessor(nLevels);
smtProcessor.oldRoot <== rootOld;
smtProcessor.newRoot <== rootNew;
for (var i=0; i<nLevels; i++) { for (var i=0; i<nLevels; i++) {
smtNew.siblings[i] <== siblingsNew[i];
smtProcessor.siblings[i] <== siblings[i];
} }
smtNew.oldKey <== 0;
smtNew.oldValue <== 0;
smtNew.isOld0 <== 0;
smtNew.key <== key;
smtNew.value <== hash.out;
smtProcessor.oldKey <== oldKey;
smtProcessor.oldValue <== oldValue;
smtProcessor.isOld0 <== isOld0;
smtProcessor.newKey <== key;
smtProcessor.newValue <== hash.out;
smtProcessor.fnc[0] <== 1;
smtProcessor.fnc[1] <== 0;
} }

+ 11
- 11
contracts/deposit-verifier.sol

@ -174,18 +174,18 @@ contract DepositVerifier {
DepositPairing.G1Point C; DepositPairing.G1Point C;
} }
function verifyingKey() internal pure returns (VerifyingKey memory vk) { function verifyingKey() internal pure returns (VerifyingKey memory vk) {
vk.alfa1 = DepositPairing.G1Point(1258740466619721561764848263868948885256868728083361044431705704250200328469,21429540617461013763355995827369015728574005711708554964620455716559845665960);
vk.beta2 = DepositPairing.G2Point([1970073964470939152021048511578236383128106002002646214631675246653310717957,12712064789215987207311676617832240483534887569403229725706661660234806079568], [6870389010384618580426191051449467588139581765956292544372582938359353782255,6848532171529839105686210172312789080165730008667873614736656943070291514440]);
vk.gamma2 = DepositPairing.G2Point([13025863801027866036957367957812995765980137647543971093801580955580158571874,20814717907036542939719692573804299830237034748270287956482979656634810999797], [16865748738430061541889111484860607300264882791091260395585977539280926944744,6582452541423888885538277642620939176084115646218892470412691713075803269496]);
vk.delta2 = DepositPairing.G2Point([2706422800377368885835489037908110628648159507031013921848827952225418230859,10128511868105727233071317029928430873590267714292386130186788090735888000654], [9307796408359964981598578123726621566221091904060802593884747535035317267698,10229229177642547369193569171638060693529620333185044332089881198521466285102]);
vk.alfa1 = DepositPairing.G1Point(10436172469864824943122622365866160700766733691225663281391281399768281792432,10013775164986556699748903408611044888497001527952485046148029488621290228585);
vk.beta2 = DepositPairing.G2Point([6309523382050532091541080192957876574321484650081637658047902580386546515396,598834447583522476960665277503297970300165165045517679601275023833966991516], [8590716082440680164063032894460567742684770930570712765827215325137514538101,8041644809937488578904117444377291033263514510643299840024598892542107423696]);
vk.gamma2 = DepositPairing.G2Point([9311246197523953352532181966516779338770754131311966565889991048533281336416,6806964349269168717187105400316621885061786836448630111519958812764418920687], [10418082789039162869629793611095143462256777121787211694416776365709854018377,2614882643262384713393249449267079986774540400035726921223478458896104844344]);
vk.delta2 = DepositPairing.G2Point([19463756687631889938064438479781340527651301127382710593277385995401455789273,5164844382488576476366820908935907641518972821410840304322777611633491225058], [1020816115565590040942442095524606749442650898898841431006540382809871657232,8002327941064179861874658273740677379359751566880314418854454428845710739907]);
vk.IC = new DepositPairing.G1Point[](7); vk.IC = new DepositPairing.G1Point[](7);
vk.IC[0] = DepositPairing.G1Point(8397052292217400695143537066445367917145410240792913306851228502454937821366,12671160300014072845850036020940585445323243765280661661695708986287317615875);
vk.IC[1] = DepositPairing.G1Point(6596045848853057767878231551177724402312499873808498125139673743823045037250,7534954341042032271738328495861493195651777182379101357540540106554292796757);
vk.IC[2] = DepositPairing.G1Point(4901276071960695759302493242818574371230833857454046609753730934715589681877,13809211544158082674160387144353489098197497336900883805464212924786897695399);
vk.IC[3] = DepositPairing.G1Point(2284803743046947681824176654599433605185583055184533094933575326747068384159,2284200205123294415907017338355314014204105239362681972585077325269318233489);
vk.IC[4] = DepositPairing.G1Point(21716095221104104663235558033723097977851973293891360765306880852225906302195,18269386656024591769800450266310198804152899431728523144697352898486771309144);
vk.IC[5] = DepositPairing.G1Point(4423411107516450238605209094503652145439393246493785143531883737456094986038,12516994610092142480164396204315951248730163354266253105562761854742484119787);
vk.IC[6] = DepositPairing.G1Point(7796439859607328142065987214031690144742541126385291233968361100031127756853,21735884364940330079209527729232705812864156681957672956585478889553770695530);
vk.IC[0] = DepositPairing.G1Point(21411647262666990764495559661063800205412974836302731545741620815490889151788,17058251660887350087753253493452815562464770070825790645851768476857448866823);
vk.IC[1] = DepositPairing.G1Point(4489528793234590408821674557567146513622182220068033318168722641066148346294,431598837137007722498041835307629832903486854852266353342117557231453915769);
vk.IC[2] = DepositPairing.G1Point(12971765444327743169844725525786836847696064637452390413371071884747166637236,3928687943489294077114641274461068607167702548289196354483089718285113877074);
vk.IC[3] = DepositPairing.G1Point(12188561213237719926849297698058632981780639967205666726128154962327519981564,20114624967037178164888953191668790590572692999526275989752914457005714918783);
vk.IC[4] = DepositPairing.G1Point(9854055718096834032036282773533182355739137615821259876399996424552780097072,12998738893454613301889157021682490687033682582512707471705403431995499740210);
vk.IC[5] = DepositPairing.G1Point(3546128512065154825135784403453313722058122770291688746941788810443755482819,1292937756460425419713531469722969064281949505806489771298471758510194029601);
vk.IC[6] = DepositPairing.G1Point(14884424934208839787266016288287746147730611302255501430594188536611873187312,4845001161750391503145769631284113687171234179175451959574268797554475015601);
} }
function verify(uint[] memory input, Proof memory proof) internal view returns (uint) { function verify(uint[] memory input, Proof memory proof) internal view returns (uint) {

+ 10
- 10
contracts/withdraw-verifier.sol

@ -174,17 +174,17 @@ contract WithdrawVerifier {
WithdrawPairing.G1Point C; WithdrawPairing.G1Point C;
} }
function verifyingKey() internal pure returns (VerifyingKey memory vk) { function verifyingKey() internal pure returns (VerifyingKey memory vk) {
vk.alfa1 = WithdrawPairing.G1Point(11409068853756798814936124347751329073714060701740446597478422218560206445758,16307887919185411074461162514565293539798560629762151895981933912918907095458);
vk.beta2 = WithdrawPairing.G2Point([7251220013464197846241844721359309776896763036272826930712901410316354650148,14916303478359187735015641670440403429698869473868729048212546922914077002474], [18211498819199508460251069486886384399731840516685342748931656167756056543712,8874050391988730461899098188033396090287848116848581254042468820295115019769]);
vk.gamma2 = WithdrawPairing.G2Point([18243312913217582213671285532303762373614349407613660426190623713836205041234,8002499263366987790694142114137942554246563360100993171567470892470253717715], [5101789453622522636051816103606254513585817263100408629732625784631019392110,11103980668176400594372381484148071708850113352167680748055027633945382594250]);
vk.delta2 = WithdrawPairing.G2Point([16098761043629001805465286169491044916675831324018099734204712260649588341703,19769730035350773990203390501439447961424668221404762178293701706197745545740], [8688701351437626790357916288760375351147435444896067675241357486671215251369,8455256066870861595443543932211829056699959252725383991522357896994317226602]);
vk.alfa1 = WithdrawPairing.G1Point(16122224429361360165495896710323717556817569717927664220395352936364188773809,19308821304069049805487909812845259701152237731090531599799296719817622808649);
vk.beta2 = WithdrawPairing.G2Point([15742195186009531957683019244119866265169218554156270986820785035986979675495,17971786283595192108143850323405651860279660450956743538933099503822871223695], [18812379374022613981626542441491307179275052911278345098663956354563845387572,18166637814736053124356707300125551037167460242150070094683100763475625606778]);
vk.gamma2 = WithdrawPairing.G2Point([3804309165560051998936028570496335352199751706740247109147439328005396808068,7726080157922178985549115604237760997638511814566094495324846590011010856487], [21887078455765841214810112476742456197556360040327347118496184669249559407265,11401770191552387201812623678675357713046330086038195382201988942087404791489]);
vk.delta2 = WithdrawPairing.G2Point([12243584111877061836716328913839833000586664963497033512825182569139003987731,8515800110697566978083812163696401201110574051431329986371537532265314142798], [2936747634621792880292543256875975432268117684295820963043335114030947834550,2292076667648256500415679715482741933702823709162129642292800969344670318170]);
vk.IC = new WithdrawPairing.G1Point[](6); vk.IC = new WithdrawPairing.G1Point[](6);
vk.IC[0] = WithdrawPairing.G1Point(2196244256820986567690679996736462451552129559361830175635841659301698130240,165089131243676339464114487098255787822583319468395307669959484414351728542);
vk.IC[1] = WithdrawPairing.G1Point(17268765234743108265652438016645776441257441044491122918862662638109371886622,16271655515517205557815838795170378396691506771170200642570141877418298560999);
vk.IC[2] = WithdrawPairing.G1Point(2948780275473397242543570881784329151300936590175851800649409338551940794103,7459991620945381798521094109942977024582184419006796838077427417326367418494);
vk.IC[3] = WithdrawPairing.G1Point(14126068401014488583026867986497891029401323572850638120219902210320665079121,12837383067484111352928338327694584489849366255365568904250423854761877284524);
vk.IC[4] = WithdrawPairing.G1Point(4035053269905941448869990955467912804643642147479323759450659886610920901687,16351688143022086978492392339555394524864154460935065484258649758201836006417);
vk.IC[5] = WithdrawPairing.G1Point(18802458565488979046369094260543220868642937974211915451306988597267942099055,12108624098056255328526306317129377211653789160060445574749682563859873858540);
vk.IC[0] = WithdrawPairing.G1Point(14113527843581317846786703524552352381462322135459069507318558830385257137643,5614687195709328189878978350488979314716330427373364361007458973144390766292);
vk.IC[1] = WithdrawPairing.G1Point(10032336890966582629140836569190647598887172603885567890570620005848208915120,21266628694840328335966552182319322762834504474929837514822383825392202865679);
vk.IC[2] = WithdrawPairing.G1Point(14351386369434505794664484682373329305740548482313796656557460426999048651406,9608572135874020459230326980104286369084126574215093271251307101873937457997);
vk.IC[3] = WithdrawPairing.G1Point(17909736313133173174561604257312484946038490730388421060722551408626742680017,738642998879078751355623433014691460474547902353491836703558504393487768986);
vk.IC[4] = WithdrawPairing.G1Point(8888450468048395100956572038184224797797919519092828590980891271655319302112,11549925395015303561525669850790742277156425046747348004261961575019205503500);
vk.IC[5] = WithdrawPairing.G1Point(13567140135630962392180038295130654407516739677152840364794668209842724088609,21376772650052813881737297934707256387080009318463006972324308269531606627970);
} }
function verify(uint[] memory input, Proof memory proof) internal view returns (uint) { function verify(uint[] memory input, Proof memory proof) internal view returns (uint) {

+ 13
- 38
src/miksi.ts

@ -39,51 +39,26 @@ exports.calcDepositWitness = async (wasm, nLevels, key, secret, commitments) =>
await tree.insert(i+1, commitments[i]); await tree.insert(i+1, commitments[i]);
} }
// old root
const rootOld = tree.root;
const resOld = await tree.find(key);
console.log("FIND old", resOld);
let oldKey = "0";
let oldValue = "0";
if (!resOld.found) {
oldKey = resOld.notFoundKey.toString();
oldValue = resOld.notFoundValue.toString();
}
console.log("oldKey", oldKey);
console.log("oldValue", oldValue);
// if (resOld.found) {
// console.error("leaf expect to not exist but exists");
// }
let siblingsOld = resOld.siblings;
while (siblingsOld.length < nLevels) {
siblingsOld.push("0");
};
await tree.insert(key, commitment);
let res = await tree.insert(key, commitment);
// new root // new root
const rootNew = tree.root;
const resNew = await tree.find(key);
console.log("FIND new", resNew);
if (!resNew.found) {
console.error("leaf with the new commitment expect to exist but not exists");
}
let siblingsNew = resNew.siblings;
while (siblingsNew.length < nLevels) {
siblingsNew.push("0");
};
let siblings = res.siblings;
console.log(res);
// while (siblings.length < nLevels) {
// siblings.push("0");
// };
// calculate witness // calculate witness
const input = unstringifyBigInts({ const input = unstringifyBigInts({
"coinCode": coinCode, "coinCode": coinCode,
"amount": amount, "amount": amount,
"secret": secret, "secret": secret,
"oldKey": oldKey,
"oldValue": oldValue,
"siblingsOld": siblingsOld,
"siblingsNew": siblingsNew,
"rootOld": rootOld,
"rootNew": rootNew,
"oldKey": res.isOld0 ? 0 : res.oldKey,
"oldValue": res.isOld0 ? 0 : res.oldValue,
"isOld0": res.isOld0 ? 1 : 0,
"siblings": siblings,
"rootOld": res.oldRoot,
"rootNew": res.newRoot,
"commitment": commitment, "commitment": commitment,
"key": key "key": key
}); });
@ -113,7 +88,7 @@ exports.calcDepositWitness = async (wasm, nLevels, key, secret, commitments) =>
witness: wBuff, witness: wBuff,
publicInputs: { publicInputs: {
commitment:commitment, commitment:commitment,
root:rootNew
root:res.newRoot
} }
}; };
} }

+ 14
- 26
test/circuits/deposit.test.ts

@ -22,7 +22,6 @@ describe("deposit test", function () {
const coinCode = "0"; const coinCode = "0";
const amount = '1000000000000000000'; const amount = '1000000000000000000';
// const nullifier = "567891234";
const poseidon = circomlib.poseidon.createHash(6, 8, 57); const poseidon = circomlib.poseidon.createHash(6, 8, 57);
const nullifier = poseidon([2, secret]); const nullifier = poseidon([2, secret]);
@ -31,42 +30,31 @@ describe("deposit test", function () {
// add commitment into SMT // add commitment into SMT
let tree = await smt.newMemEmptyTrie(); let tree = await smt.newMemEmptyTrie();
await tree.insert(1, 0); await tree.insert(1, 0);
// await tree.insert(2, 0);
let rootOld = tree.root; let rootOld = tree.root;
let res = await tree.find(2);
// console.log(res);
assert(!res.found);
let siblingsOld = res.siblings;
while (siblingsOld.length < nLevels) {
siblingsOld.push("0");
};
console.log("siblingsOld", siblingsOld);
await tree.insert(2, commitment);
let res = await tree.insert(2, commitment);
console.log("INSERT", res);
let rootNew = tree.root; let rootNew = tree.root;
res = await tree.find(2);
// console.log(res);
assert(res.found);
let siblingsNew = res.siblings;
while (siblingsNew.length < nLevels) {
siblingsNew.push("0");
let siblings = res.siblings;
while (siblings.length < nLevels) {
siblings.push("0");
}; };
console.log("siblingsNew", siblingsNew);
console.log("rootOld", rootOld);
console.log("rootNew", rootNew);
console.log("siblings", siblings);
console.log(res);
const witness = await circuit.calculateWitness({ const witness = await circuit.calculateWitness({
"coinCode": coinCode, "coinCode": coinCode,
"amount": amount, "amount": amount,
"secret": secret, "secret": secret,
"oldKey": "1",
"oldValue": "0",
"siblingsOld": siblingsOld,
"siblingsNew": siblingsNew,
"rootOld": rootOld,
"rootNew": rootNew,
"oldKey": res.isOld0 ? 0 : res.oldKey,
"oldValue": res.isOld0 ? 0 : res.oldValue,
"isOld0": res.isOld0 ? 1 : 0,
"siblings": siblings,
"rootOld": res.oldRoot,
"rootNew": res.newRoot,
"commitment": commitment, "commitment": commitment,
"key": 2 "key": 2
}); });

+ 12
- 15
test/contracts/miksi.test.ts

@ -77,11 +77,11 @@ contract("miksi", (accounts) => {
// expect(balance_wei).to.be.equal('98993526980000000000'); // expect(balance_wei).to.be.equal('98993526980000000000');
}); });
it("Make second deposit", async () => { it("Make second deposit", async () => {
await computeTree(1);
// await computeTree(1);
await makeDeposit(1, addr3); await makeDeposit(1, addr3);
}); });
it("Make 3rd deposit", async () => { it("Make 3rd deposit", async () => {
await computeTree(2);
// await computeTree(2);
await makeDeposit(2, addr3); await makeDeposit(2, addr3);
}); });
@ -183,12 +183,9 @@ async function computeTree(u) {
} }
async function makeDeposit(u, addr) { async function makeDeposit(u, addr) {
const resC = await tree.find(currKey);
assert(resC.found);
siblingsNew[u] = resC.siblings;
while (siblingsNew[u].length < nLevels) {
siblingsNew[u].push("0");
};
let resInsert = await tree.insert(currKey+1, commitment[u]);
rootNew[u] = tree.root;
currKey += 1;
// calculate witness // calculate witness
const wasm = await fs.promises.readFile("./test/build/deposit.wasm"); const wasm = await fs.promises.readFile("./test/build/deposit.wasm");
@ -196,12 +193,12 @@ async function makeDeposit(u, addr) {
"coinCode": coinCode, "coinCode": coinCode,
"amount": amount, "amount": amount,
"secret": secret[u], "secret": secret[u],
"oldKey": oldKey[u],
"oldValue": oldValue[u],
"siblingsOld": siblingsOld[u],
"siblingsNew": siblingsNew[u],
"rootOld": rootOld[u],
"rootNew": rootNew[u],
"oldKey": resInsert.isOld0 ? 0 : resInsert.oldKey,
"oldValue": resInsert.isOld0 ? 0 : resInsert.oldValue,
"isOld0": resInsert.isOld0 ? 1 : 0,
"siblings": resInsert.siblings,
"rootOld": resInsert.oldRoot,
"rootNew": resInsert.newRoot,
"commitment": commitment[u], "commitment": commitment[u],
"key": currKey "key": currKey
}); });
@ -220,7 +217,7 @@ async function makeDeposit(u, addr) {
publicSignals[u] = res.publicSignals; publicSignals[u] = res.publicSignals;
const verificationKey = unstringifyBigInts(JSON.parse(fs.readFileSync("./test/build/deposit-verification_key.json", "utf8"))); const verificationKey = unstringifyBigInts(JSON.parse(fs.readFileSync("./test/build/deposit-verification_key.json", "utf8")));
let pubI = unstringifyBigInts([coinCode, amount, rootOld[u].toString(), rootNew[u].toString(), commitment[u], currKey]);
let pubI = unstringifyBigInts([coinCode, amount, res.oldRoot.toString(), res.newRoot.toString(), commitment[u], currKey]);
let validCheck = groth.isValid(verificationKey, proof[u], pubI); let validCheck = groth.isValid(verificationKey, proof[u], pubI);
assert(validCheck); assert(validCheck);
await insMiksi.deposit( await insMiksi.deposit(

Loading…
Cancel
Save