working with some errors yet
This commit is contained in:
parent
38fc4b7396
commit
ccaa7ff23b
@ -94,6 +94,15 @@ Insert to a used leaf.
|
||||
na ┃ Hash ┃ ┃ Hash ┃
|
||||
┗━━━━━━━┛ ┗━━━━━━━┛
|
||||
|
||||
|
||||
Fnction
|
||||
fnc[0] fnc[1]
|
||||
0 0 NOP
|
||||
0 1 UPDATE
|
||||
1 0 INSERT
|
||||
1 1 DELETE
|
||||
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
include "../gates.circom";
|
||||
@ -114,6 +123,11 @@ template SMTInsert(nLevels) {
|
||||
signal input isOld0;
|
||||
signal input newKey;
|
||||
signal input newValue;
|
||||
signal input fnc[2];
|
||||
|
||||
signal enabled;
|
||||
|
||||
enabled <== fnc[0] + fnc[1] - fnc[0]*fnc[1]
|
||||
|
||||
component hash1Old = SMTHash1();
|
||||
hash1Old.key <== oldKey;
|
||||
@ -131,6 +145,7 @@ template SMTInsert(nLevels) {
|
||||
|
||||
component smtLevIns = SMTLevIns(nLevels);
|
||||
for (var i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
|
||||
smtLevIns.enabled <== enabled;
|
||||
|
||||
component xors[nLevels];
|
||||
for (var i=0; i<nLevels; i++) {
|
||||
@ -143,12 +158,13 @@ template SMTInsert(nLevels) {
|
||||
for (var i=0; i<nLevels; i++) {
|
||||
sm[i] = SMTInsertSM();
|
||||
if (i==0) {
|
||||
sm[i].prev_top <== 1;
|
||||
sm[i].prev_top <== enabled;
|
||||
sm[i].prev_old1 <== 0;
|
||||
sm[i].prev_old0 <== 0;
|
||||
sm[i].prev_bot <== 0;
|
||||
sm[i].prev_new1 <== 0;
|
||||
sm[i].prev_na <== 0;
|
||||
sm[i].prev_na <== 1-enabled;
|
||||
sm[i].prev_upd <== 0;
|
||||
} else {
|
||||
sm[i].prev_top <== sm[i-1].st_top;
|
||||
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_new1 <== sm[i-1].st_new1;
|
||||
sm[i].prev_na <== sm[i-1].st_na;
|
||||
sm[i].prev_upd <== sm[i-1].st_upd;
|
||||
}
|
||||
sm[i].is0 <== isOld0;
|
||||
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[nLevels-1].st_na === 1;
|
||||
@ -172,7 +191,8 @@ template SMTInsert(nLevels) {
|
||||
levels[i].st_old0 <== sm[i].st_old0;
|
||||
levels[i].st_bot <== sm[i].st_bot;
|
||||
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].old1leaf <== hash1Old.out;
|
||||
@ -188,6 +208,12 @@ template SMTInsert(nLevels) {
|
||||
}
|
||||
}
|
||||
|
||||
levels[0].oldRoot === oldRoot;
|
||||
levels[0].newRoot === newRoot;
|
||||
component topSwitcher = Switcher();
|
||||
|
||||
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)
|
||||
na 0 0
|
||||
|
||||
upd old1leaf new1leaf
|
||||
|
||||
H' is the Hash function with the inputs shifted acordingly.
|
||||
|
||||
*****/
|
||||
@ -29,6 +31,7 @@ template SMTInsertLevel() {
|
||||
signal input st_bot;
|
||||
signal input st_new1;
|
||||
signal input st_na;
|
||||
signal input st_upd;
|
||||
|
||||
signal output oldRoot;
|
||||
signal output newRoot;
|
||||
@ -56,7 +59,7 @@ template SMTInsertLevel() {
|
||||
oldProofHash.L <== oldSwitcher.outL;
|
||||
oldProofHash.R <== oldSwitcher.outR;
|
||||
|
||||
aux[0] <== old1leaf * st_old1;
|
||||
aux[0] <== old1leaf * (st_old1 + st_upd);
|
||||
oldRoot <== aux[0] + oldProofHash.out * st_top;
|
||||
|
||||
// New side
|
||||
@ -72,5 +75,5 @@ template SMTInsertLevel() {
|
||||
newProofHash.R <== newSwitcher.outR;
|
||||
|
||||
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
|
||||
┌─────┐ │ ## ## │ ┌──────┐
|
||||
│ │ │ ######### │ any │ │
|
||||
│ ▼ │ │ ▼ │
|
||||
│ ########### │ │ ########### │
|
||||
│ # # ────────────┘ └────────▶# #│
|
||||
└──# top # # na #
|
||||
## ## ────┐ ┌──▶## ##
|
||||
######### │ │ #########
|
||||
│ │
|
||||
│ ########### ########### │ any
|
||||
levIns=1 │ # # xor=1 # # │
|
||||
is0=0 └───▶# old1 #─────────────▶# new1 #──┘
|
||||
## ## ## ##
|
||||
#########│ #########
|
||||
│ ▲
|
||||
└───┐ ┌─────┘
|
||||
xor=0 │ ###########│ xor=1
|
||||
│ # #
|
||||
▼# btn #
|
||||
## ##
|
||||
#########◀───────┐
|
||||
│ │
|
||||
│ │
|
||||
└────────────┘
|
||||
xor=0
|
||||
# #
|
||||
┌────────────────────────────▶# upd #─────────────────────┐
|
||||
│ ## ## │
|
||||
│ ######### │
|
||||
levIns=1 │ │
|
||||
fnc[0]=0 │ │ any
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ ########### │
|
||||
│ levIns=1 # # │
|
||||
levIns=0 │ is0=1 ┌────────────▶# old0 #────────┐ │ any
|
||||
┌─────┐ │ fnc[0]=1│ ## ## │ │ ┌──────┐
|
||||
│ │ │ │ ######### │ any │ │ │
|
||||
│ ▼ │ │ │ ▼ ▼ │
|
||||
│ ########### │ │ ########### │
|
||||
│ # # ────────────┘ └────────▶# #│
|
||||
└──# top # # na #
|
||||
## ## ────┐ ┌──▶## ##
|
||||
######### │ │ #########
|
||||
│ │
|
||||
│ ########### ########### │ any
|
||||
levIns=1 │ # # xor=1 # # │
|
||||
is0=0 └───▶# old1 #─────────────▶# new1 #──┘
|
||||
fnc[0]=1 ## ## ## ##
|
||||
#########│ #########
|
||||
│ ▲
|
||||
└───┐ ┌─────┘
|
||||
xor=0 │ ###########│ xor=1
|
||||
│ # #
|
||||
▼# btn #
|
||||
## ##
|
||||
#########◀───────┐
|
||||
│ │
|
||||
│ │
|
||||
└────────────┘
|
||||
xor=0
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
@ -67,8 +77,7 @@ template SMTInsertSM() {
|
||||
signal input xor;
|
||||
signal input is0;
|
||||
signal input levIns;
|
||||
signal input fnc[0];
|
||||
signal input fnc[1];
|
||||
signal input fnc[2];
|
||||
|
||||
signal input prev_top;
|
||||
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) =
|
||||
// = - prev_old1*xor -prev_bot*xor + 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]) =
|
||||
// = aux1 * (1-fnc[0])
|
||||
|
||||
|
@ -55,6 +55,7 @@ a parent with a sibling != 0.
|
||||
*/
|
||||
|
||||
template SMTLevIns(nLevels) {
|
||||
signal input enabled;
|
||||
signal input siblings[nLevels];
|
||||
signal output levIns[nLevels];
|
||||
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.
|
||||
isZero[nLevels-2].out === 1;
|
||||
(isZero[nLevels-2].out - 1) * enabled === 0;
|
||||
|
||||
levIns[nLevels-1] <== (1-isZero[nLevels-2].out);
|
||||
done[nLevels-2] <== levIns[nLevels-1];
|
||||
|
88
package-lock.json
generated
88
package-lock.json
generated
@ -2446,7 +2446,8 @@
|
||||
"bindings": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz",
|
||||
"integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw=="
|
||||
"integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==",
|
||||
"dev": true
|
||||
},
|
||||
"bip39": {
|
||||
"version": "2.5.0",
|
||||
@ -2465,6 +2466,7 @@
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz",
|
||||
"integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
@ -2499,7 +2501,8 @@
|
||||
"bn.js": {
|
||||
"version": "4.11.8",
|
||||
"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": {
|
||||
"version": "1.18.3",
|
||||
@ -2542,12 +2545,14 @@
|
||||
"brorand": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
|
||||
"integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
|
||||
"integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
|
||||
"dev": true
|
||||
},
|
||||
"browserify-aes": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
|
||||
"integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-xor": "^1.0.3",
|
||||
"cipher-base": "^1.0.0",
|
||||
@ -2704,7 +2709,8 @@
|
||||
"buffer-xor": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
|
||||
"integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
|
||||
"integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
|
||||
"dev": true
|
||||
},
|
||||
"builtin-modules": {
|
||||
"version": "1.1.1",
|
||||
@ -2802,6 +2808,7 @@
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
|
||||
"integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
@ -2961,6 +2968,7 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
|
||||
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cipher-base": "^1.0.1",
|
||||
"inherits": "^2.0.1",
|
||||
@ -2973,6 +2981,7 @@
|
||||
"version": "1.1.7",
|
||||
"resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
|
||||
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cipher-base": "^1.0.3",
|
||||
"create-hash": "^1.1.0",
|
||||
@ -3272,6 +3281,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz",
|
||||
"integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"browserify-aes": "^1.0.6",
|
||||
"create-hash": "^1.1.2",
|
||||
@ -3310,6 +3320,7 @@
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
|
||||
"integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bn.js": "^4.4.0",
|
||||
"brorand": "^1.0.1",
|
||||
@ -3600,17 +3611,8 @@
|
||||
"integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
|
||||
"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": {
|
||||
@ -3622,6 +3624,7 @@
|
||||
"ethereumjs-abi": {
|
||||
"version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
|
||||
"from": "git+https://github.com/ethereumjs/ethereumjs-abi.git",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bn.js": "^4.10.0",
|
||||
"ethereumjs-util": "^5.0.0"
|
||||
@ -3816,6 +3819,7 @@
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
|
||||
"integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bn.js": "^4.11.0",
|
||||
"create-hash": "^1.1.2",
|
||||
@ -3905,6 +3909,7 @@
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz",
|
||||
"integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-hex-prefixed": "1.0.0",
|
||||
"strip-hex-prefix": "1.0.0"
|
||||
@ -3926,6 +3931,7 @@
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
|
||||
"integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"md5.js": "^1.3.4",
|
||||
"safe-buffer": "^5.1.1"
|
||||
@ -4336,6 +4342,7 @@
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
|
||||
"integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
@ -4345,6 +4352,7 @@
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz",
|
||||
"integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"minimalistic-assert": "^1.0.1"
|
||||
@ -4372,6 +4380,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
||||
"integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hash.js": "^1.0.3",
|
||||
"minimalistic-assert": "^1.0.0",
|
||||
@ -4539,7 +4548,8 @@
|
||||
"is-hex-prefixed": {
|
||||
"version": "1.0.0",
|
||||
"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": {
|
||||
"version": "4.0.1",
|
||||
@ -4593,7 +4603,8 @@
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
|
||||
"dev": true
|
||||
},
|
||||
"is-utf8": {
|
||||
"version": "0.2.1",
|
||||
@ -4739,6 +4750,7 @@
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz",
|
||||
"integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bindings": "^1.2.1",
|
||||
"inherits": "^2.0.3",
|
||||
@ -5038,6 +5050,7 @@
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||
"integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hash-base": "^3.0.0",
|
||||
"inherits": "^2.0.1",
|
||||
@ -5197,12 +5210,14 @@
|
||||
"minimalistic-assert": {
|
||||
"version": "1.0.1",
|
||||
"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": {
|
||||
"version": "1.0.1",
|
||||
"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": {
|
||||
"version": "3.0.4",
|
||||
@ -5254,7 +5269,8 @@
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||
"dev": true
|
||||
},
|
||||
"mz": {
|
||||
"version": "2.7.0",
|
||||
@ -5271,7 +5287,8 @@
|
||||
"nan": {
|
||||
"version": "2.10.0",
|
||||
"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": {
|
||||
"version": "0.1.2",
|
||||
@ -5938,6 +5955,7 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
|
||||
"integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hash-base": "^3.0.0",
|
||||
"inherits": "^2.0.1"
|
||||
@ -5947,6 +5965,7 @@
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/rlp/-/rlp-2.1.0.tgz",
|
||||
"integrity": "sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.1"
|
||||
}
|
||||
@ -5960,7 +5979,8 @@
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"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": {
|
||||
"version": "1.0.1",
|
||||
@ -6012,6 +6032,7 @@
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.2.tgz",
|
||||
"integrity": "sha512-iin3kojdybY6NArd+UFsoTuapOF7bnJNf2UbcWXaY3z+E1sJDipl60vtzB5hbO/uquBu7z0fd4VC4Irp+xoFVQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bindings": "^1.2.1",
|
||||
"bip66": "^1.1.3",
|
||||
@ -6143,6 +6164,7 @@
|
||||
"version": "2.4.11",
|
||||
"resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
|
||||
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
@ -6353,6 +6375,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz",
|
||||
"integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-hex-prefixed": "1.0.0"
|
||||
}
|
||||
@ -6596,6 +6619,7 @@
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
||||
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
@ -7038,22 +7062,14 @@
|
||||
"integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
|
||||
"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": {
|
||||
"version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
|
||||
"from": "git+https://github.com/ethereumjs/ethereumjs-abi.git",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bn.js": "^4.10.0",
|
||||
"ethereumjs-util": "^5.0.0"
|
||||
@ -7098,20 +7114,23 @@
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"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": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"websocket": {
|
||||
"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": {
|
||||
"debug": "^2.2.0",
|
||||
"nan": "^2.3.3",
|
||||
@ -7290,7 +7309,8 @@
|
||||
"yaeti": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
|
||||
"integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc="
|
||||
"integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=",
|
||||
"dev": true
|
||||
},
|
||||
"yargs": {
|
||||
"version": "4.8.1",
|
||||
|
29
src/mimc7.js
29
src/mimc7.js
@ -3,35 +3,34 @@ const bigInt = require("snarkjs").bigInt;
|
||||
const Web3 = require("web3");
|
||||
const F = bn128.Fr;
|
||||
|
||||
module.exports.hash = MiMC7Hash;
|
||||
module.exports.getConstants = getConstants;
|
||||
|
||||
const SEED = "iden3_mimc";
|
||||
const nRounds = 91;
|
||||
|
||||
function getConstants(seed, nRounds) {
|
||||
|
||||
exports.getConstants = (seed, nRounds) => {
|
||||
const cts = new Array(nRounds);
|
||||
let c = Web3.utils.keccak256(SEED);
|
||||
for (let i=1; i<nRounds; i++) {
|
||||
c = Web3.utils.keccak256(c);
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
function MiMC7Hash(_x_in, _k, nRounds) {
|
||||
const cts = exports.getConstants(SEED, 91);
|
||||
|
||||
exports.hash = (_x_in, _k) =>{
|
||||
const x_in = bigInt(_x_in);
|
||||
const k = bigInt(_k);
|
||||
const cts = getConstants(SEED, nRounds);
|
||||
let r;
|
||||
for (let i=0; i<nRounds; i++) {
|
||||
const c = bigInt(Web3.utils.toBN(cts[i]).toString());
|
||||
let t = (i==0) ? F.add(x_in, k) : F.add(F.add(r, k), c);
|
||||
let t2 = F.square(t);
|
||||
let t4 = F.square(t2);
|
||||
r = F.mul(F.mul(t4, t2), t);
|
||||
const c = cts[i];
|
||||
const t = (i==0) ? F.add(x_in, k) : F.add(F.add(r, k), c);
|
||||
r = F.exp(t, 7);
|
||||
}
|
||||
return F.affine(F.add(r, k));
|
||||
}
|
||||
};
|
||||
|
144
src/smt.js
144
src/smt.js
@ -1,12 +1,12 @@
|
||||
const bigInt = require("snarkjs").bigInt;
|
||||
|
||||
const SMTMemDB = require("./smt_memdb");
|
||||
const mimc7 = require("./mimc7");
|
||||
const mimc7 = require("./mimc7").hash;
|
||||
|
||||
function smtHash(arr) {
|
||||
let r = bigInt(0);
|
||||
for (let i=0; i<arr.length; i++) {
|
||||
r = mimc7.hash(r, bigInt(arr[i]), 91 );
|
||||
r = mimc7(r, bigInt(arr[i]));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@ -37,6 +37,92 @@ class SMT {
|
||||
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) {
|
||||
const key = bigInt(_key);
|
||||
const value = bigInt(_value);
|
||||
@ -44,34 +130,60 @@ class SMT {
|
||||
const res = {};
|
||||
res.oldRoot = this.root;
|
||||
const newKeyBits = this._splitBits(key);
|
||||
|
||||
let rtOld;
|
||||
|
||||
const resFind = await this.find(key);
|
||||
|
||||
if (resFind.found) throw new Error("Key already exists");
|
||||
|
||||
res.sibblings = resFind.sibblings;
|
||||
let mixed;
|
||||
|
||||
if (!resFind.isOld0) {
|
||||
const oldKeyits = this._splitBits(resFind.notFoundKey);
|
||||
for (let i= res.sibblings.length; oldKeyits[i] == newKeyBits[i]; i++) {
|
||||
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;
|
||||
mixed = false;
|
||||
} else if (res.sibblings.length >0) {
|
||||
mixed = true;
|
||||
rtOld = bigInt.zero;
|
||||
}
|
||||
|
||||
const inserts = [];
|
||||
const dels = [];
|
||||
|
||||
let rt = smtHash([1, key, value]);
|
||||
inserts.push([rt,[1, key, value]] );
|
||||
|
||||
for (let i=res.sibblings.length-1; i>=0; i--) {
|
||||
if (newKeyBits[i]) {
|
||||
rt = smtHash([res.sibblings[i], rt]);
|
||||
inserts.push([rt,[res.sibblings[i], rt]] );
|
||||
} else {
|
||||
rt = smtHash([rt, res.sibblings[i]]);
|
||||
inserts.push([rt,[rt, res.sibblings[i]]] );
|
||||
if ((i<res.sibblings.length-1)&&(!res.sibblings[i].isZero())) {
|
||||
mixed = true;
|
||||
}
|
||||
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();
|
||||
@ -83,9 +195,11 @@ class SMT {
|
||||
res.newRoot = rt;
|
||||
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;
|
||||
}
|
||||
@ -131,11 +245,11 @@ class SMT {
|
||||
}
|
||||
} else {
|
||||
if (keyBits[level] == 0) {
|
||||
const res = await this.find(key, keyBits, record[1], level+1);
|
||||
res.sibblings.unshift(record[2]);
|
||||
} else {
|
||||
res = await this.find(key, keyBits, record[2], level+1);
|
||||
res = await this._find(key, keyBits, record[0], level+1);
|
||||
res.sibblings.unshift(record[1]);
|
||||
} else {
|
||||
res = await this._find(key, keyBits, record[1], level+1);
|
||||
res.sibblings.unshift(record[0]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
@ -10,21 +10,40 @@ class SMTMemDb {
|
||||
return this.root;
|
||||
}
|
||||
|
||||
async get(key) {
|
||||
const res = [];
|
||||
const keyS = bigInt(key).leInt2Buff(32).toString("hex");
|
||||
for (let i=0; i<this.nodes[keyS].length; i++) {
|
||||
res.push(bigInt(this.nodes[keyS][i]));
|
||||
}
|
||||
return res;
|
||||
_key2str(k) {
|
||||
// const keyS = bigInt(key).leInt2Buff(32).toString("hex");
|
||||
const keyS = bigInt(k).toString();
|
||||
return keyS;
|
||||
}
|
||||
|
||||
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++) {
|
||||
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.root = root;
|
||||
}
|
||||
|
||||
async multiDel(dels) {
|
||||
for (let i=0; i<dels.length; i++) {
|
||||
const keyS = this._key2str(dels[i]);
|
||||
delete this.nodes[keyS];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
177
test/smt.js
177
test/smt.js
@ -13,6 +13,52 @@ function print(circuit, w, 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 () {
|
||||
let circuit;
|
||||
@ -34,55 +80,110 @@ describe("SMT test", function () {
|
||||
const key = bigInt(111);
|
||||
const value = bigInt(222);
|
||||
|
||||
const res = await tree.insert(key,value);
|
||||
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));
|
||||
await testInsert(tree, key, value, circuit);
|
||||
});
|
||||
|
||||
it("It should add another element", async () => {
|
||||
const key = bigInt(333);
|
||||
const value = bigInt(444);
|
||||
|
||||
const res = await tree.insert(key,value);
|
||||
let siblings = res.sibblings;
|
||||
while (siblings.length<10) siblings.push(bigInt(0));
|
||||
await testInsert(tree, key, value, circuit);
|
||||
});
|
||||
|
||||
|
||||
|
||||
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({
|
||||
oldRoot: res.oldRoot,
|
||||
newRoot: res.newRoot,
|
||||
fnc: [0,0],
|
||||
oldRoot: 11,
|
||||
newRoot: 22,
|
||||
siblings: siblings,
|
||||
oldKey: res.oldKey,
|
||||
oldValue: res.oldValue,
|
||||
isOld0: res.isOld0 ? 1 : 0,
|
||||
newKey: key,
|
||||
newValue: value
|
||||
oldKey: 33,
|
||||
oldValue: 44,
|
||||
isOld0: 55,
|
||||
newKey: 66,
|
||||
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));
|
||||
|
||||
});
|
||||
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
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);
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in New Issue
Block a user