working with some errors yet

This commit is contained in:
Jordi Baylina 2018-12-13 19:53:32 +01:00
parent 38fc4b7396
commit ccaa7ff23b
No known key found for this signature in database
GPG Key ID: 7480C80C1BE43112
11 changed files with 24599 additions and 150 deletions

@ -94,6 +94,15 @@ Insert to a used leaf.
na ┃ Hash ┃ ┃ Hash ┃ na ┃ Hash ┃ ┃ Hash ┃
┗━━━━━━━┛ ┗━━━━━━━┛ ┗━━━━━━━┛ ┗━━━━━━━┛
Fnction
fnc[0] fnc[1]
0 0 NOP
0 1 UPDATE
1 0 INSERT
1 1 DELETE
***************************************************************************************************/ ***************************************************************************************************/
include "../gates.circom"; include "../gates.circom";
@ -114,6 +123,11 @@ template SMTInsert(nLevels) {
signal input isOld0; signal input isOld0;
signal input newKey; signal input newKey;
signal input newValue; signal input newValue;
signal input fnc[2];
signal enabled;
enabled <== fnc[0] + fnc[1] - fnc[0]*fnc[1]
component hash1Old = SMTHash1(); component hash1Old = SMTHash1();
hash1Old.key <== oldKey; hash1Old.key <== oldKey;
@ -131,6 +145,7 @@ template SMTInsert(nLevels) {
component smtLevIns = SMTLevIns(nLevels); component smtLevIns = SMTLevIns(nLevels);
for (var i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i]; for (var i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
smtLevIns.enabled <== enabled;
component xors[nLevels]; component xors[nLevels];
for (var i=0; i<nLevels; i++) { for (var i=0; i<nLevels; i++) {
@ -143,12 +158,13 @@ template SMTInsert(nLevels) {
for (var i=0; i<nLevels; i++) { for (var i=0; i<nLevels; i++) {
sm[i] = SMTInsertSM(); sm[i] = SMTInsertSM();
if (i==0) { if (i==0) {
sm[i].prev_top <== 1; sm[i].prev_top <== enabled;
sm[i].prev_old1 <== 0; sm[i].prev_old1 <== 0;
sm[i].prev_old0 <== 0; sm[i].prev_old0 <== 0;
sm[i].prev_bot <== 0; sm[i].prev_bot <== 0;
sm[i].prev_new1 <== 0; sm[i].prev_new1 <== 0;
sm[i].prev_na <== 0; sm[i].prev_na <== 1-enabled;
sm[i].prev_upd <== 0;
} else { } else {
sm[i].prev_top <== sm[i-1].st_top; sm[i].prev_top <== sm[i-1].st_top;
sm[i].prev_old1 <== sm[i-1].st_old1; sm[i].prev_old1 <== sm[i-1].st_old1;
@ -156,9 +172,12 @@ template SMTInsert(nLevels) {
sm[i].prev_bot <== sm[i-1].st_bot; sm[i].prev_bot <== sm[i-1].st_bot;
sm[i].prev_new1 <== sm[i-1].st_new1; sm[i].prev_new1 <== sm[i-1].st_new1;
sm[i].prev_na <== sm[i-1].st_na; sm[i].prev_na <== sm[i-1].st_na;
sm[i].prev_upd <== sm[i-1].st_upd;
} }
sm[i].is0 <== isOld0; sm[i].is0 <== isOld0;
sm[i].xor <== xors[i].out; sm[i].xor <== xors[i].out;
sm[i].fnc[0] <== fnc[0];
sm[i].fnc[1] <== fnc[1];
sm[i].levIns <== smtLevIns.levIns[i]; sm[i].levIns <== smtLevIns.levIns[i];
} }
sm[nLevels-1].st_na === 1; sm[nLevels-1].st_na === 1;
@ -172,7 +191,8 @@ template SMTInsert(nLevels) {
levels[i].st_old0 <== sm[i].st_old0; levels[i].st_old0 <== sm[i].st_old0;
levels[i].st_bot <== sm[i].st_bot; levels[i].st_bot <== sm[i].st_bot;
levels[i].st_new1 <== sm[i].st_new1; levels[i].st_new1 <== sm[i].st_new1;
levels[i].st_na <==sm[i].st_na; levels[i].st_na <== sm[i].st_na;
levels[i].st_upd <== sm[i].st_upd;
levels[i].sibling <== siblings[i]; levels[i].sibling <== siblings[i];
levels[i].old1leaf <== hash1Old.out; levels[i].old1leaf <== hash1Old.out;
@ -188,6 +208,12 @@ template SMTInsert(nLevels) {
} }
} }
levels[0].oldRoot === oldRoot; component topSwitcher = Switcher();
levels[0].newRoot === newRoot;
topSwitcher.sel <== fnc[0]*fnc[1];
topSwitcher.L <== levels[0].oldRoot;
topSwitcher.R <== levels[0].newRoot;
topSwitcher.outL === oldRoot*enabled;
topSwitcher.outR === newRoot*enabled;
} }

@ -17,6 +17,8 @@ bot 0 H'(newChild, 0)
new1 0 H'(new1leaf, old1leaf) new1 0 H'(new1leaf, old1leaf)
na 0 0 na 0 0
upd old1leaf new1leaf
H' is the Hash function with the inputs shifted acordingly. H' is the Hash function with the inputs shifted acordingly.
*****/ *****/
@ -29,6 +31,7 @@ template SMTInsertLevel() {
signal input st_bot; signal input st_bot;
signal input st_new1; signal input st_new1;
signal input st_na; signal input st_na;
signal input st_upd;
signal output oldRoot; signal output oldRoot;
signal output newRoot; signal output newRoot;
@ -56,7 +59,7 @@ template SMTInsertLevel() {
oldProofHash.L <== oldSwitcher.outL; oldProofHash.L <== oldSwitcher.outL;
oldProofHash.R <== oldSwitcher.outR; oldProofHash.R <== oldSwitcher.outR;
aux[0] <== old1leaf * st_old1; aux[0] <== old1leaf * (st_old1 + st_upd);
oldRoot <== aux[0] + oldProofHash.out * st_top; oldRoot <== aux[0] + oldProofHash.out * st_top;
// New side // New side
@ -72,5 +75,5 @@ template SMTInsertLevel() {
newProofHash.R <== newSwitcher.outR; newProofHash.R <== newSwitcher.outR;
aux[3] <== newProofHash.out * (st_top + st_old1 + st_bot + st_new1); aux[3] <== newProofHash.out * (st_top + st_old1 + st_bot + st_new1);
newRoot <== aux[3] + new1leaf * st_old0; newRoot <== aux[3] + new1leaf * (st_old0 + st_upd);
} }

@ -33,33 +33,43 @@ fnc[0] fnc[1]
########### ###########
levIns=1 # # # #
levIns=0 is0=1 ┌────────────▶# old0 #────────┐ any ┌────────────────────────────▶# upd #─────────────────────┐
┌─────┐ │ ## ## │ ┌──────┐ │ ## ## │
│ │ │ ######### │ any │ │ │ ######### │
│ ▼ │ │ ▼ │ levIns=1 │ │
│ ########### │ │ ########### │ fnc[0]=0 │ │ any
│ # # ────────────┘ └────────▶# #│ │ │
└──# top # # na # │ │
## ## ────┐ ┌──▶## ## │ │
######### │ │ ######### │ ########### │
│ │ │ levIns=1 # # │
│ ########### ########### │ any levIns=0 │ is0=1 ┌────────────▶# old0 #────────┐ │ any
levIns=1 │ # # xor=1 # # │ ┌─────┐ │ fnc[0]=1│ ## ## │ │ ┌──────┐
is0=0 └───▶# old1 #─────────────▶# new1 #──┘ │ │ │ │ ######### │ any │ │ │
## ## ## ## │ ▼ │ │ │ ▼ ▼ │
#########│ ######### │ ########### │ │ ########### │
│ ▲ │ # # ────────────┘ └────────▶# #│
└───┐ ┌─────┘ └──# top # # na #
xor=0 │ ###########│ xor=1 ## ## ────┐ ┌──▶## ##
│ # # ######### │ │ #########
▼# btn # │ │
## ## │ ########### ########### │ any
#########◀───────┐ levIns=1 │ # # xor=1 # # │
│ │ is0=0 └───▶# old1 #─────────────▶# new1 #──┘
│ │ fnc[0]=1 ## ## ## ##
└────────────┘ #########│ #########
xor=0 │ ▲
└───┐ ┌─────┘
xor=0 │ ###########│ xor=1
│ # #
▼# btn #
## ##
#########◀───────┐
│ │
│ │
└────────────┘
xor=0
***************************************************************************************************/ ***************************************************************************************************/
@ -67,8 +77,7 @@ template SMTInsertSM() {
signal input xor; signal input xor;
signal input is0; signal input is0;
signal input levIns; signal input levIns;
signal input fnc[0]; signal input fnc[2];
signal input fnc[1];
signal input prev_top; signal input prev_top;
signal input prev_old0; signal input prev_old0;
@ -102,7 +111,7 @@ template SMTInsertSM() {
st_bot <== -st_new1 + prev_old1 + prev_bot // prev_old1*(1-xor) + prev_bot*(1-xor) = st_bot <== -st_new1 + prev_old1 + prev_bot // prev_old1*(1-xor) + prev_bot*(1-xor) =
// = - prev_old1*xor -prev_bot*xor + prev_old1 + prev_bot = // = - prev_old1*xor -prev_bot*xor + prev_old1 + prev_bot =
// = -st_new1 + prev_old1 + prev_bot // = -st_new1 + prev_old1 + prev_bot
st_na <== prev_new1 + prev_old0 + prev_na + st_upd; st_na <== prev_new1 + prev_old0 + prev_na + prev_upd;
st_upd <== aux1*(1-fnc[0]); // prev_top*levIns*(1-fnc[0]) = st_upd <== aux1*(1-fnc[0]); // prev_top*levIns*(1-fnc[0]) =
// = aux1 * (1-fnc[0]) // = aux1 * (1-fnc[0])

@ -55,6 +55,7 @@ a parent with a sibling != 0.
*/ */
template SMTLevIns(nLevels) { template SMTLevIns(nLevels) {
signal input enabled;
signal input siblings[nLevels]; signal input siblings[nLevels];
signal output levIns[nLevels]; signal output levIns[nLevels];
signal done[nLevels-1]; // Indicates if the insLevel has aready been detecetd. signal done[nLevels-1]; // Indicates if the insLevel has aready been detecetd.
@ -67,7 +68,7 @@ template SMTLevIns(nLevels) {
} }
// The last level must always have a sibling of 0. If not, then it cannot be inserted. // The last level must always have a sibling of 0. If not, then it cannot be inserted.
isZero[nLevels-2].out === 1; (isZero[nLevels-2].out - 1) * enabled === 0;
levIns[nLevels-1] <== (1-isZero[nLevels-2].out); levIns[nLevels-1] <== (1-isZero[nLevels-2].out);
done[nLevels-2] <== levIns[nLevels-1]; done[nLevels-2] <== levIns[nLevels-1];

88
package-lock.json generated

@ -2446,7 +2446,8 @@
"bindings": { "bindings": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz",
"integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==",
"dev": true
}, },
"bip39": { "bip39": {
"version": "2.5.0", "version": "2.5.0",
@ -2465,6 +2466,7 @@
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz",
"integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=",
"dev": true,
"requires": { "requires": {
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
} }
@ -2499,7 +2501,8 @@
"bn.js": { "bn.js": {
"version": "4.11.8", "version": "4.11.8",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
"integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
"dev": true
}, },
"body-parser": { "body-parser": {
"version": "1.18.3", "version": "1.18.3",
@ -2542,12 +2545,14 @@
"brorand": { "brorand": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
"integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
"dev": true
}, },
"browserify-aes": { "browserify-aes": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
"integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
"dev": true,
"requires": { "requires": {
"buffer-xor": "^1.0.3", "buffer-xor": "^1.0.3",
"cipher-base": "^1.0.0", "cipher-base": "^1.0.0",
@ -2704,7 +2709,8 @@
"buffer-xor": { "buffer-xor": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
"integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
"dev": true
}, },
"builtin-modules": { "builtin-modules": {
"version": "1.1.1", "version": "1.1.1",
@ -2802,6 +2808,7 @@
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
"integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
"dev": true,
"requires": { "requires": {
"inherits": "^2.0.1", "inherits": "^2.0.1",
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
@ -2961,6 +2968,7 @@
"version": "1.2.0", "version": "1.2.0",
"resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
"dev": true,
"requires": { "requires": {
"cipher-base": "^1.0.1", "cipher-base": "^1.0.1",
"inherits": "^2.0.1", "inherits": "^2.0.1",
@ -2973,6 +2981,7 @@
"version": "1.1.7", "version": "1.1.7",
"resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
"dev": true,
"requires": { "requires": {
"cipher-base": "^1.0.3", "cipher-base": "^1.0.3",
"create-hash": "^1.1.0", "create-hash": "^1.1.0",
@ -3272,6 +3281,7 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz",
"integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=",
"dev": true,
"requires": { "requires": {
"browserify-aes": "^1.0.6", "browserify-aes": "^1.0.6",
"create-hash": "^1.1.2", "create-hash": "^1.1.2",
@ -3310,6 +3320,7 @@
"version": "6.4.1", "version": "6.4.1",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
"integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==",
"dev": true,
"requires": { "requires": {
"bn.js": "^4.4.0", "bn.js": "^4.4.0",
"brorand": "^1.0.1", "brorand": "^1.0.1",
@ -3600,17 +3611,8 @@
"integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=",
"dev": true, "dev": true,
"requires": { "requires": {
"ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
"ethereumjs-util": "^5.1.1" "ethereumjs-util": "^5.1.1"
},
"dependencies": {
"ethereumjs-abi": {
"version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
"from": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
"requires": {
"bn.js": "^4.10.0",
"ethereumjs-util": "^5.0.0"
}
}
} }
}, },
"ethereum-common": { "ethereum-common": {
@ -3622,6 +3624,7 @@
"ethereumjs-abi": { "ethereumjs-abi": {
"version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799", "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
"from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git",
"dev": true,
"requires": { "requires": {
"bn.js": "^4.10.0", "bn.js": "^4.10.0",
"ethereumjs-util": "^5.0.0" "ethereumjs-util": "^5.0.0"
@ -3816,6 +3819,7 @@
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
"integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==",
"dev": true,
"requires": { "requires": {
"bn.js": "^4.11.0", "bn.js": "^4.11.0",
"create-hash": "^1.1.2", "create-hash": "^1.1.2",
@ -3905,6 +3909,7 @@
"version": "0.1.6", "version": "0.1.6",
"resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz",
"integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==",
"dev": true,
"requires": { "requires": {
"is-hex-prefixed": "1.0.0", "is-hex-prefixed": "1.0.0",
"strip-hex-prefix": "1.0.0" "strip-hex-prefix": "1.0.0"
@ -3926,6 +3931,7 @@
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
"integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
"dev": true,
"requires": { "requires": {
"md5.js": "^1.3.4", "md5.js": "^1.3.4",
"safe-buffer": "^5.1.1" "safe-buffer": "^5.1.1"
@ -4336,6 +4342,7 @@
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
"integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
"dev": true,
"requires": { "requires": {
"inherits": "^2.0.1", "inherits": "^2.0.1",
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
@ -4345,6 +4352,7 @@
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz",
"integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==",
"dev": true,
"requires": { "requires": {
"inherits": "^2.0.3", "inherits": "^2.0.3",
"minimalistic-assert": "^1.0.1" "minimalistic-assert": "^1.0.1"
@ -4372,6 +4380,7 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
"integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
"dev": true,
"requires": { "requires": {
"hash.js": "^1.0.3", "hash.js": "^1.0.3",
"minimalistic-assert": "^1.0.0", "minimalistic-assert": "^1.0.0",
@ -4539,7 +4548,8 @@
"is-hex-prefixed": { "is-hex-prefixed": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz",
"integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=",
"dev": true
}, },
"is-natural-number": { "is-natural-number": {
"version": "4.0.1", "version": "4.0.1",
@ -4593,7 +4603,8 @@
"is-typedarray": { "is-typedarray": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
"dev": true
}, },
"is-utf8": { "is-utf8": {
"version": "0.2.1", "version": "0.2.1",
@ -4739,6 +4750,7 @@
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz",
"integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==",
"dev": true,
"requires": { "requires": {
"bindings": "^1.2.1", "bindings": "^1.2.1",
"inherits": "^2.0.3", "inherits": "^2.0.3",
@ -5038,6 +5050,7 @@
"version": "1.3.5", "version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
"integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
"dev": true,
"requires": { "requires": {
"hash-base": "^3.0.0", "hash-base": "^3.0.0",
"inherits": "^2.0.1", "inherits": "^2.0.1",
@ -5197,12 +5210,14 @@
"minimalistic-assert": { "minimalistic-assert": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
"dev": true
}, },
"minimalistic-crypto-utils": { "minimalistic-crypto-utils": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
"integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
"dev": true
}, },
"minimatch": { "minimatch": {
"version": "3.0.4", "version": "3.0.4",
@ -5254,7 +5269,8 @@
"ms": { "ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
}, },
"mz": { "mz": {
"version": "2.7.0", "version": "2.7.0",
@ -5271,7 +5287,8 @@
"nan": { "nan": {
"version": "2.10.0", "version": "2.10.0",
"resolved": "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz", "resolved": "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
"dev": true
}, },
"nano-json-stream-parser": { "nano-json-stream-parser": {
"version": "0.1.2", "version": "0.1.2",
@ -5938,6 +5955,7 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
"integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
"dev": true,
"requires": { "requires": {
"hash-base": "^3.0.0", "hash-base": "^3.0.0",
"inherits": "^2.0.1" "inherits": "^2.0.1"
@ -5947,6 +5965,7 @@
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/rlp/-/rlp-2.1.0.tgz", "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.1.0.tgz",
"integrity": "sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA==", "integrity": "sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA==",
"dev": true,
"requires": { "requires": {
"safe-buffer": "^5.1.1" "safe-buffer": "^5.1.1"
} }
@ -5960,7 +5979,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true
}, },
"safe-event-emitter": { "safe-event-emitter": {
"version": "1.0.1", "version": "1.0.1",
@ -6012,6 +6032,7 @@
"version": "3.5.2", "version": "3.5.2",
"resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.2.tgz", "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.2.tgz",
"integrity": "sha512-iin3kojdybY6NArd+UFsoTuapOF7bnJNf2UbcWXaY3z+E1sJDipl60vtzB5hbO/uquBu7z0fd4VC4Irp+xoFVQ==", "integrity": "sha512-iin3kojdybY6NArd+UFsoTuapOF7bnJNf2UbcWXaY3z+E1sJDipl60vtzB5hbO/uquBu7z0fd4VC4Irp+xoFVQ==",
"dev": true,
"requires": { "requires": {
"bindings": "^1.2.1", "bindings": "^1.2.1",
"bip66": "^1.1.3", "bip66": "^1.1.3",
@ -6143,6 +6164,7 @@
"version": "2.4.11", "version": "2.4.11",
"resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
"dev": true,
"requires": { "requires": {
"inherits": "^2.0.1", "inherits": "^2.0.1",
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
@ -6353,6 +6375,7 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz",
"integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=",
"dev": true,
"requires": { "requires": {
"is-hex-prefixed": "1.0.0" "is-hex-prefixed": "1.0.0"
} }
@ -6596,6 +6619,7 @@
"version": "3.1.5", "version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
"dev": true,
"requires": { "requires": {
"is-typedarray": "^1.0.0" "is-typedarray": "^1.0.0"
} }
@ -7038,22 +7062,14 @@
"integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=",
"dev": true, "dev": true,
"requires": { "requires": {
"ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
"ethereumjs-util": "^5.1.1" "ethereumjs-util": "^5.1.1"
},
"dependencies": {
"ethereumjs-abi": {
"version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
"from": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
"requires": {
"bn.js": "^4.10.0",
"ethereumjs-util": "^5.0.0"
}
}
} }
}, },
"ethereumjs-abi": { "ethereumjs-abi": {
"version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799", "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
"from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git",
"dev": true,
"requires": { "requires": {
"bn.js": "^4.10.0", "bn.js": "^4.10.0",
"ethereumjs-util": "^5.0.0" "ethereumjs-util": "^5.0.0"
@ -7098,20 +7114,23 @@
"dev": true, "dev": true,
"requires": { "requires": {
"underscore": "1.8.3", "underscore": "1.8.3",
"web3-core-helpers": "1.0.0-beta.35" "web3-core-helpers": "1.0.0-beta.35",
"websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2"
}, },
"dependencies": { "dependencies": {
"debug": { "debug": {
"version": "2.6.9", "version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"requires": { "requires": {
"ms": "2.0.0" "ms": "2.0.0"
} }
}, },
"websocket": { "websocket": {
"version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
"from": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", "from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible",
"dev": true,
"requires": { "requires": {
"debug": "^2.2.0", "debug": "^2.2.0",
"nan": "^2.3.3", "nan": "^2.3.3",
@ -7290,7 +7309,8 @@
"yaeti": { "yaeti": {
"version": "0.0.6", "version": "0.0.6",
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
"integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=",
"dev": true
}, },
"yargs": { "yargs": {
"version": "4.8.1", "version": "4.8.1",

@ -3,35 +3,34 @@ const bigInt = require("snarkjs").bigInt;
const Web3 = require("web3"); const Web3 = require("web3");
const F = bn128.Fr; const F = bn128.Fr;
module.exports.hash = MiMC7Hash;
module.exports.getConstants = getConstants;
const SEED = "iden3_mimc"; const SEED = "iden3_mimc";
const nRounds = 91;
function getConstants(seed, nRounds) {
exports.getConstants = (seed, nRounds) => {
const cts = new Array(nRounds); const cts = new Array(nRounds);
let c = Web3.utils.keccak256(SEED); let c = Web3.utils.keccak256(SEED);
for (let i=1; i<nRounds; i++) { for (let i=1; i<nRounds; i++) {
c = Web3.utils.keccak256(c); c = Web3.utils.keccak256(c);
const n1 = Web3.utils.toBN(c).mod(Web3.utils.toBN(F.q.toString())); const n1 = Web3.utils.toBN(c).mod(Web3.utils.toBN(F.q.toString()));
cts[i] = Web3.utils.padLeft(Web3.utils.toHex(n1), 64); const c2 = Web3.utils.padLeft(Web3.utils.toHex(n1), 64);
cts[i] = bigInt(Web3.utils.toBN(c2).toString());
} }
cts[0] = "0x0000000000000000000000000000000000000000000000000000000000000000"; cts[0] = bigInt(0);
return cts; return cts;
} };
function MiMC7Hash(_x_in, _k, nRounds) { const cts = exports.getConstants(SEED, 91);
exports.hash = (_x_in, _k) =>{
const x_in = bigInt(_x_in); const x_in = bigInt(_x_in);
const k = bigInt(_k); const k = bigInt(_k);
const cts = getConstants(SEED, nRounds);
let r; let r;
for (let i=0; i<nRounds; i++) { for (let i=0; i<nRounds; i++) {
const c = bigInt(Web3.utils.toBN(cts[i]).toString()); const c = cts[i];
let t = (i==0) ? F.add(x_in, k) : F.add(F.add(r, k), c); const t = (i==0) ? F.add(x_in, k) : F.add(F.add(r, k), c);
let t2 = F.square(t); r = F.exp(t, 7);
let t4 = F.square(t2);
r = F.mul(F.mul(t4, t2), t);
} }
return F.affine(F.add(r, k)); return F.affine(F.add(r, k));
} };

@ -1,12 +1,12 @@
const bigInt = require("snarkjs").bigInt; const bigInt = require("snarkjs").bigInt;
const SMTMemDB = require("./smt_memdb"); const SMTMemDB = require("./smt_memdb");
const mimc7 = require("./mimc7"); const mimc7 = require("./mimc7").hash;
function smtHash(arr) { function smtHash(arr) {
let r = bigInt(0); let r = bigInt(0);
for (let i=0; i<arr.length; i++) { for (let i=0; i<arr.length; i++) {
r = mimc7.hash(r, bigInt(arr[i]), 91 ); r = mimc7(r, bigInt(arr[i]));
} }
return r; return r;
} }
@ -37,6 +37,92 @@ class SMT {
return res; return res;
} }
async delete(_key) {
const key = bigInt(_key);
const resFind = await this.find(key);
if (!resFind.found) throw new Error("Key does not exists");
const res = {
sibblings: [],
delKey: key,
delValue: resFind.foundValue
};
const dels = [];
const ins = [];
let rtOld = smtHash([1, key, resFind.foundValue]);
let rtNew;
dels.push(rtOld);
let mixed;
if (resFind.sibblings.length > 0) {
const record = await this.db.get(resFind.sibblings[resFind.sibblings.length - 1]);
if ((record.length == 3)&&(record[0].equals(bigInt.one))) {
mixed = false;
res.oldKey = record[1];
res.oldValue = record[2];
res.isOld0 = false;
rtNew = resFind.sibblings[resFind.sibblings.length - 1];
} else if (record.length == 2) {
mixed = true;
res.oldKey = key;
res.oldValue = bigInt(0);
res.isOld0 = true;
rtNew = bigInt.zero;
} else {
throw new Error("Invalid node. Database corrupted");
}
} else {
rtNew = bigInt.zero;
res.oldKey = key;
res.oldValue = bigInt(0);
res.isOld0 = true;
}
const keyBits = this._splitBits(key);
for (let level = resFind.sibblings.length-1; level >=0; level--) {
let newSibling = resFind.sibblings[level];
if ((level == resFind.sibblings.length-1)&&(!res.isOld0)) {
newSibling = bigInt.zero;
}
const oldSibling = resFind.sibblings[level];
if (keyBits[level]) {
rtOld = smtHash([oldSibling, rtOld]);
} else {
rtOld = smtHash([rtOld, oldSibling]);
}
dels.push(rtOld);
if (!newSibling.isZero()) {
mixed = true;
}
if (mixed) {
res.sibblings.unshift(resFind.sibblings[level]);
let newNode;
if (keyBits[level]) {
newNode = [newSibling, rtNew];
} else {
newNode = [rtNew, newSibling];
}
rtNew = smtHash(newNode);
ins.push([rtNew, newNode]);
}
}
await this.db.multiIns(ins);
await this.db.setRoot(rtNew);
this.root = rtNew;
await this.db.multiDel(dels);
res.newRoot = rtNew;
res.oldRoot = rtOld;
return res;
}
async insert(_key, _value) { async insert(_key, _value) {
const key = bigInt(_key); const key = bigInt(_key);
const value = bigInt(_value); const value = bigInt(_value);
@ -44,34 +130,60 @@ class SMT {
const res = {}; const res = {};
res.oldRoot = this.root; res.oldRoot = this.root;
const newKeyBits = this._splitBits(key); const newKeyBits = this._splitBits(key);
let rtOld;
const resFind = await this.find(key); const resFind = await this.find(key);
if (resFind.found) throw new Error("Key already exists"); if (resFind.found) throw new Error("Key already exists");
res.sibblings = resFind.sibblings; res.sibblings = resFind.sibblings;
let mixed;
if (!resFind.isOld0) { if (!resFind.isOld0) {
const oldKeyits = this._splitBits(resFind.notFoundKey); const oldKeyits = this._splitBits(resFind.notFoundKey);
for (let i= res.sibblings.length; oldKeyits[i] == newKeyBits[i]; i++) { for (let i= res.sibblings.length; oldKeyits[i] == newKeyBits[i]; i++) {
res.sibblings.push(bigInt.zero); res.sibblings.push(bigInt.zero);
} }
res.sibblings.push(smtHash([1, resFind.notFoundKey, resFind.notFoundValue])); rtOld = smtHash([1, resFind.notFoundKey, resFind.notFoundValue]);
res.sibblings.push(rtOld);
addedOne = true; addedOne = true;
mixed = false;
} else if (res.sibblings.length >0) {
mixed = true;
rtOld = bigInt.zero;
} }
const inserts = []; const inserts = [];
const dels = [];
let rt = smtHash([1, key, value]); let rt = smtHash([1, key, value]);
inserts.push([rt,[1, key, value]] ); inserts.push([rt,[1, key, value]] );
for (let i=res.sibblings.length-1; i>=0; i--) { for (let i=res.sibblings.length-1; i>=0; i--) {
if (newKeyBits[i]) { if ((i<res.sibblings.length-1)&&(!res.sibblings[i].isZero())) {
rt = smtHash([res.sibblings[i], rt]); mixed = true;
inserts.push([rt,[res.sibblings[i], rt]] );
} else {
rt = smtHash([rt, res.sibblings[i]]);
inserts.push([rt,[rt, res.sibblings[i]]] );
} }
if (mixed) {
const oldSibling = resFind.sibblings[i];
if (newKeyBits[i]) {
rtOld = smtHash([oldSibling, rtOld]);
} else {
rtOld = smtHash([rtOld, oldSibling]);
}
dels.push(rtOld);
}
let newRt;
if (newKeyBits[i]) {
newRt = smtHash([res.sibblings[i], rt]);
inserts.push([newRt,[res.sibblings[i], rt]] );
} else {
newRt = smtHash([rt, res.sibblings[i]]);
inserts.push([newRt,[rt, res.sibblings[i]]] );
}
rt = newRt;
} }
if (addedOne) res.sibblings.pop(); if (addedOne) res.sibblings.pop();
@ -83,9 +195,11 @@ class SMT {
res.newRoot = rt; res.newRoot = rt;
res.isOld0 = resFind.isOld0; res.isOld0 = resFind.isOld0;
this.root = rt;
await this.db.save(rt, inserts); await this.db.multiIns(inserts);
await this.db.setRoot(rt);
this.root = rt;
await this.db.multiDel(dels);
return res; return res;
} }
@ -131,11 +245,11 @@ class SMT {
} }
} else { } else {
if (keyBits[level] == 0) { if (keyBits[level] == 0) {
const res = await this.find(key, keyBits, record[1], level+1); res = await this._find(key, keyBits, record[0], level+1);
res.sibblings.unshift(record[2]);
} else {
res = await this.find(key, keyBits, record[2], level+1);
res.sibblings.unshift(record[1]); res.sibblings.unshift(record[1]);
} else {
res = await this._find(key, keyBits, record[1], level+1);
res.sibblings.unshift(record[0]);
} }
} }
return res; return res;

@ -10,21 +10,40 @@ class SMTMemDb {
return this.root; return this.root;
} }
async get(key) { _key2str(k) {
const res = []; // const keyS = bigInt(key).leInt2Buff(32).toString("hex");
const keyS = bigInt(key).leInt2Buff(32).toString("hex"); const keyS = bigInt(k).toString();
for (let i=0; i<this.nodes[keyS].length; i++) { return keyS;
res.push(bigInt(this.nodes[keyS][i]));
}
return res;
} }
async save(root, inserts) { _normalize(n) {
for (let i=0; i<n.length; i++) {
n[i] = bigInt(n[i]);
}
}
async get(key) {
const keyS = this._key2str(key);
return this.nodes[keyS];
}
async setRoot(rt) {
this.root = rt;
}
async multiIns(inserts) {
for (let i=0; i<inserts.length; i++) { for (let i=0; i<inserts.length; i++) {
const keyS = bigInt(inserts[i][0]).leInt2Buff(32).toString("hex"); const keyS = this._key2str(inserts[i][0]);
this._normalize(inserts[i][1]);
this.nodes[keyS] = inserts[i][1]; this.nodes[keyS] = inserts[i][1];
} }
this.root = root; }
async multiDel(dels) {
for (let i=0; i<dels.length; i++) {
const keyS = this._key2str(dels[i]);
delete this.nodes[keyS];
}
} }
} }

23994
test.sig Normal file

File diff suppressed because it is too large Load Diff

@ -13,6 +13,52 @@ function print(circuit, w, s) {
console.log(s + ": " + w[circuit.getSignalIdx(s)]); console.log(s + ": " + w[circuit.getSignalIdx(s)]);
} }
async function testInsert(tree, key, value, circuit, log ) {
const res = await tree.insert(key,value);
let siblings = res.sibblings;
while (siblings.length<10) siblings.push(bigInt(0));
const w = circuit.calculateWitness({
fnc: [1,0],
oldRoot: res.oldRoot,
newRoot: res.newRoot,
siblings: siblings,
oldKey: res.oldKey,
oldValue: res.oldValue,
isOld0: res.isOld0 ? 1 : 0,
newKey: key,
newValue: value
}, log);
const root1 = w[circuit.getSignalIdx("main.topSwitcher.outR")];
assert(circuit.checkWitness(w));
assert(root1.equals(res.newRoot));
}
async function testDelete(tree, key, circuit) {
const res = await tree.delete(key);
let siblings = res.sibblings;
while (siblings.length<10) siblings.push(bigInt(0));
const w = circuit.calculateWitness({
fnc: [1,1],
oldRoot: res.oldRoot,
newRoot: res.newRoot,
siblings: siblings,
oldKey: res.oldKey,
oldValue: res.oldValue,
isOld0: res.isOld0 ? 1 : 0,
newKey: res.delKey,
newValue: res.delValue
});
const root1 = w[circuit.getSignalIdx("main.topSwitcher.outR")];
assert(circuit.checkWitness(w));
assert(root1.equals(res.newRoot));
}
describe("SMT test", function () { describe("SMT test", function () {
let circuit; let circuit;
@ -34,55 +80,110 @@ describe("SMT test", function () {
const key = bigInt(111); const key = bigInt(111);
const value = bigInt(222); const value = bigInt(222);
const res = await tree.insert(key,value); await testInsert(tree, key, value, circuit);
let siblings = res.sibblings;
while (siblings.length<10) siblings.push(bigInt(0));
const w = circuit.calculateWitness({
oldRoot: res.oldRoot,
newRoot: res.newRoot,
siblings: siblings,
oldKey: res.oldKey,
oldValue: res.oldValue,
isOld0: res.isOld0 ? 1 : 0,
newKey: key,
newValue: value
});
const root1 = w[circuit.getSignalIdx("main.levels[0].newRoot")];
console.log("root1: " + root1.toString());
console.log("root2: " + res.newRoot.toString());
assert(root1.equals(res.newRoot));
assert(circuit.checkWitness(w));
}); });
it("It should add another element", async () => { it("It should add another element", async () => {
const key = bigInt(333); const key = bigInt(333);
const value = bigInt(444); const value = bigInt(444);
const res = await tree.insert(key,value); await testInsert(tree, key, value, circuit);
let siblings = res.sibblings; });
while (siblings.length<10) siblings.push(bigInt(0));
it("Should remove an element", async () => {
await testDelete(tree, 111, circuit);
await testDelete(tree, 333, circuit);
});
it("Should test convination of adding and removing 3 elements", async () => {
const keys = [bigInt(8), bigInt(9), bigInt(32)];
const values = [bigInt(88), bigInt(99), bigInt(3232)];
const tree1 = await smt.newMemEmptyTrie();
const tree2 = await smt.newMemEmptyTrie();
const tree3 = await smt.newMemEmptyTrie();
const tree4 = await smt.newMemEmptyTrie();
const tree5 = await smt.newMemEmptyTrie();
const tree6 = await smt.newMemEmptyTrie();
await testInsert(tree1,keys[0],values[0], circuit);
await testInsert(tree1,keys[1],values[1], circuit, console.log);
/* await testInsert(tree1,keys[2],values[2], circuit);
await testInsert(tree2,keys[0],values[0], circuit);
await testInsert(tree2,keys[2],values[2], circuit);
await testInsert(tree2,keys[1],values[1], circuit);
await testInsert(tree3,keys[1],values[1], circuit);
await testInsert(tree3,keys[0],values[0], circuit);
await testInsert(tree3,keys[2],values[2], circuit);
await testInsert(tree4,keys[1],values[1], circuit);
await testInsert(tree4,keys[2],values[2], circuit);
await testInsert(tree4,keys[0],values[0], circuit);
await testInsert(tree5,keys[2],values[2], circuit);
await testInsert(tree5,keys[0],values[0], circuit);
await testInsert(tree5,keys[1],values[1], circuit);
await testInsert(tree6,keys[2],values[2], circuit);
await testInsert(tree6,keys[1],values[1], circuit);
await testInsert(tree6,keys[0],values[0], circuit);
await testDelete(tree1, keys[0], circuit);
await testDelete(tree1, keys[1], circuit);
await testDelete(tree2, keys[1], circuit);
await testDelete(tree2, keys[0], circuit);
await testDelete(tree3, keys[0], circuit);
await testDelete(tree3, keys[2], circuit);
await testDelete(tree4, keys[2], circuit);
await testDelete(tree4, keys[0], circuit);
await testDelete(tree5, keys[1], circuit);
await testDelete(tree5, keys[2], circuit);
await testDelete(tree6, keys[2], circuit);
await testDelete(tree6, keys[1], circuit);
await testDelete(tree1, keys[2], circuit);
await testDelete(tree2, keys[2], circuit);
await testDelete(tree3, keys[1], circuit);
await testDelete(tree4, keys[1], circuit);
await testDelete(tree5, keys[0], circuit);
await testDelete(tree6, keys[0], circuit); */
});
it("Should match a NOp with random vals", async () => {
let siblings = [];
while (siblings.length<10) siblings.push(bigInt(88));
const w = circuit.calculateWitness({ const w = circuit.calculateWitness({
oldRoot: res.oldRoot, fnc: [0,0],
newRoot: res.newRoot, oldRoot: 11,
newRoot: 22,
siblings: siblings, siblings: siblings,
oldKey: res.oldKey, oldKey: 33,
oldValue: res.oldValue, oldValue: 44,
isOld0: res.isOld0 ? 1 : 0, isOld0: 55,
newKey: key, newKey: 66,
newValue: value newValue: 77
}); });
const root1 = w[circuit.getSignalIdx("main.levels[0].newRoot")];
console.log("root1: " + root1.toString());
console.log("root2: " + res.newRoot.toString());
assert(root1.equals(res.newRoot));
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
}); });
it("Should update an element", async () => {
});
it("Should verify existance of an element", async () => {
});
it("Should verify non existance of an element", async () => {
});
}); });

163
test/smtjs.js Normal file

@ -0,0 +1,163 @@
const chai = require("chai");
const snarkjs = require("snarkjs");
const smt = require("../src/smt.js");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
function stringifyBigInts(o) {
if ((typeof(o) == "bigint") || (o instanceof bigInt)) {
return o.toString(10);
} else if (Array.isArray(o)) {
return o.map(stringifyBigInts);
} else if (typeof o == "object") {
const res = {};
for (let k in o) {
res[k] = stringifyBigInts(o[k]);
}
return res;
} else {
return o;
}
}
describe("SMT Javascript test", function () {
this.timeout(100000);
before( async () => {
});
it("Should insert 2 elements and empty them", async () => {
const tree = await smt.newMemEmptyTrie();
const key1 = bigInt(111);
const value1 = bigInt(222);
const key2 = bigInt(333);
const value2 = bigInt(444);
await tree.insert(key1,value1);
await tree.insert(key2,value2);
await tree.delete(key2);
await tree.delete(key1);
assert(tree.root.isZero());
});
it("Should insert 3 elements in dferent order and should be the same", async () => {
const keys = [bigInt(8), bigInt(9), bigInt(32)];
const values = [bigInt(88), bigInt(99), bigInt(3232)];
const tree1 = await smt.newMemEmptyTrie();
const tree2 = await smt.newMemEmptyTrie();
const tree3 = await smt.newMemEmptyTrie();
const tree4 = await smt.newMemEmptyTrie();
const tree5 = await smt.newMemEmptyTrie();
const tree6 = await smt.newMemEmptyTrie();
await tree1.insert(keys[0],values[0]);
await tree1.insert(keys[1],values[1]);
await tree1.insert(keys[2],values[2]);
await tree2.insert(keys[0],values[0]);
await tree2.insert(keys[2],values[2]);
await tree2.insert(keys[1],values[1]);
await tree3.insert(keys[1],values[1]);
await tree3.insert(keys[0],values[0]);
await tree3.insert(keys[2],values[2]);
await tree4.insert(keys[1],values[1]);
await tree4.insert(keys[2],values[2]);
await tree4.insert(keys[0],values[0]);
await tree5.insert(keys[2],values[2]);
await tree5.insert(keys[0],values[0]);
await tree5.insert(keys[1],values[1]);
await tree6.insert(keys[2],values[2]);
await tree6.insert(keys[1],values[1]);
await tree6.insert(keys[0],values[0]);
assert(tree1.root.equals(tree2.root));
assert(tree2.root.equals(tree3.root));
assert(tree3.root.equals(tree4.root));
assert(tree4.root.equals(tree5.root));
assert(tree5.root.equals(tree6.root));
assert.equal(Object.keys(tree1.db.nodes).length, Object.keys(tree2.db.nodes).length);
assert.equal(Object.keys(tree2.db.nodes).length, Object.keys(tree3.db.nodes).length);
assert.equal(Object.keys(tree3.db.nodes).length, Object.keys(tree4.db.nodes).length);
assert.equal(Object.keys(tree4.db.nodes).length, Object.keys(tree5.db.nodes).length);
assert.equal(Object.keys(tree5.db.nodes).length, Object.keys(tree6.db.nodes).length);
await tree1.delete(keys[0]);
await tree1.delete(keys[1]);
await tree2.delete(keys[1]);
await tree2.delete(keys[0]);
assert(tree1.root.equals(tree2.root));
await tree3.delete(keys[0]);
await tree3.delete(keys[2]);
await tree4.delete(keys[2]);
await tree4.delete(keys[0]);
assert(tree3.root.equals(tree4.root));
await tree5.delete(keys[1]);
await tree5.delete(keys[2]);
await tree6.delete(keys[2]);
await tree6.delete(keys[1]);
assert(tree5.root.equals(tree6.root));
await tree1.delete(keys[2]);
await tree2.delete(keys[2]);
await tree3.delete(keys[1]);
await tree4.delete(keys[1]);
await tree5.delete(keys[0]);
await tree6.delete(keys[0]);
assert(tree1.root.isZero());
assert(tree2.root.isZero());
assert(tree3.root.isZero());
assert(tree4.root.isZero());
assert(tree5.root.isZero());
assert(tree6.root.isZero());
assert.equal(Object.keys(tree1.db.nodes).length, 0);
assert.equal(Object.keys(tree2.db.nodes).length, 0);
assert.equal(Object.keys(tree3.db.nodes).length, 0);
assert.equal(Object.keys(tree4.db.nodes).length, 0);
assert.equal(Object.keys(tree5.db.nodes).length, 0);
assert.equal(Object.keys(tree6.db.nodes).length, 0);
});
it("Insert and remove 100 numbers randomly", async () => {
function perm(a) {
const arr = a.slice();
const rArr = [];
for (let i=0; i<arr.length; i++) {
let rIdx = Math.floor(Math.random() * (arr.length - i));
rArr.push(arr[rIdx]);
arr[rIdx] = arr[arr.length - i - 1];
}
return rArr;
}
const tree = await smt.newMemEmptyTrie();
const arr = [];
const N = 100;
for (let i=0; i<N; i++) {
arr.push(bigInt(i));
}
const insArr = perm(arr);
for (let i=0; i<N; i++) {
await tree.insert(insArr[i], i);
}
const delArr = perm(insArr);
for (let i=0; i<N; i++) {
await tree.delete(delArr[i]);
}
assert(tree.root.isZero());
assert.equal(Object.keys(tree.db.nodes).length, 0);
});
});