zkjson 0.6.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/README.md +537 -0
  2. package/assets/collection.png +0 -0
  3. package/assets/db.png +0 -0
  4. package/assets/encode.png +0 -0
  5. package/assets/query.png +0 -0
  6. package/assets/rollup.png +0 -0
  7. package/assets/structure.png +0 -0
  8. package/assets/weavedb.png +0 -0
  9. package/assets/zkjson.png +0 -0
  10. package/benchmark/components/ui/avatar.jsx +49 -0
  11. package/benchmark/components/ui/checkbox.jsx +17 -0
  12. package/benchmark/components/ui/close-button.jsx +20 -0
  13. package/benchmark/components/ui/color-mode.jsx +89 -0
  14. package/benchmark/components/ui/dialog.jsx +54 -0
  15. package/benchmark/components/ui/drawer.jsx +44 -0
  16. package/benchmark/components/ui/field.jsx +22 -0
  17. package/benchmark/components/ui/input-group.jsx +39 -0
  18. package/benchmark/components/ui/popover.jsx +49 -0
  19. package/benchmark/components/ui/provider.jsx +12 -0
  20. package/benchmark/components/ui/radio.jsx +17 -0
  21. package/benchmark/components/ui/slider.jsx +107 -0
  22. package/benchmark/components/ui/tooltip.jsx +35 -0
  23. package/benchmark/jsconfig.json +7 -0
  24. package/benchmark/lib/cbor.js +387 -0
  25. package/benchmark/lib/msgpack.js +651 -0
  26. package/benchmark/next.config.mjs +6 -0
  27. package/benchmark/package.json +22 -0
  28. package/benchmark/pages/_app.js +9 -0
  29. package/benchmark/pages/_document.js +13 -0
  30. package/benchmark/pages/api/hello.js +5 -0
  31. package/benchmark/pages/index.js +438 -0
  32. package/benchmark/public/favicon.ico +0 -0
  33. package/benchmark/public/file.svg +1 -0
  34. package/benchmark/public/globe.svg +1 -0
  35. package/benchmark/public/next.svg +1 -0
  36. package/benchmark/public/vercel.svg +1 -0
  37. package/benchmark/public/window.svg +1 -0
  38. package/benchmark/yarn.lock +2448 -0
  39. package/circom/collection/collection.circom +32 -0
  40. package/circom/collection/compile.sh +10 -0
  41. package/circom/collection/gen.js +34 -0
  42. package/circom/collection/generateInput.js +10 -0
  43. package/circom/collection/index.circom +4 -0
  44. package/circom/collection/test.js +21 -0
  45. package/circom/collection/verifier.sol +247 -0
  46. package/circom/db/compile.sh +10 -0
  47. package/circom/db/db.circom +39 -0
  48. package/circom/db/gen.js +30 -0
  49. package/circom/db/generateInput.js +10 -0
  50. package/circom/db/index.circom +4 -0
  51. package/circom/db/test.js +21 -0
  52. package/circom/db/verifier.sol +261 -0
  53. package/circom/ipfs/calculate_total.circom +17 -0
  54. package/circom/ipfs/compile.sh +10 -0
  55. package/circom/ipfs/gen.js +18 -0
  56. package/circom/ipfs/generateInput.js +10 -0
  57. package/circom/ipfs/index.circom +4 -0
  58. package/circom/ipfs/ipfs.circom +62 -0
  59. package/circom/ipfs/parse.circom +289 -0
  60. package/circom/ipfs/sha256.circom +99 -0
  61. package/circom/ipfs/test.js +167 -0
  62. package/circom/ipfs/verifier.sol +261 -0
  63. package/circom/json/compile.sh +10 -0
  64. package/circom/json/gen.js +22 -0
  65. package/circom/json/gen2.js +21 -0
  66. package/circom/json/generateInput.js +20 -0
  67. package/circom/json/index.circom +4 -0
  68. package/circom/json/json.circom +81 -0
  69. package/circom/json/test.js +100 -0
  70. package/circom/json/verifier.sol +247 -0
  71. package/circom/query/compile.sh +10 -0
  72. package/circom/query/gen.js +28 -0
  73. package/circom/query/generateInput.js +11 -0
  74. package/circom/query/index.circom +4 -0
  75. package/circom/query/query.circom +58 -0
  76. package/circom/query/test.js +20 -0
  77. package/circom/query/verifier.sol +177 -0
  78. package/circom/rollup/compile.sh +10 -0
  79. package/circom/rollup/gen.js +36 -0
  80. package/circom/rollup/generateInput.js +11 -0
  81. package/circom/rollup/index.circom +4 -0
  82. package/circom/rollup/rollup.circom +43 -0
  83. package/circom/rollup/test.js +35 -0
  84. package/circom/rollup/verifier.sol +240 -0
  85. package/circom/scripts/ceremony.js +39 -0
  86. package/circom/scripts/ceremony.sh +6 -0
  87. package/circom/scripts/compile.js +113 -0
  88. package/circom/scripts/compile.sh +16 -0
  89. package/circom/utils/uint.circom +512 -0
  90. package/circom/utils/utils.circom +628 -0
  91. package/demos/arweave/jsconfig.json +7 -0
  92. package/demos/arweave/lib/ZKArweave.json +617 -0
  93. package/demos/arweave/lib/encoder.js +375 -0
  94. package/demos/arweave/next.config.js +6 -0
  95. package/demos/arweave/package.json +26 -0
  96. package/demos/arweave/pages/_app.js +9 -0
  97. package/demos/arweave/pages/_document.js +19 -0
  98. package/demos/arweave/pages/api/arweave.js +31 -0
  99. package/demos/arweave/pages/api/hello.js +5 -0
  100. package/demos/arweave/pages/index.js +869 -0
  101. package/demos/arweave/public/circuit.wasm +0 -0
  102. package/demos/arweave/public/circuit_final.zkey +0 -0
  103. package/demos/arweave/public/verification_key.json +149 -0
  104. package/demos/arweave/vercel.json +7 -0
  105. package/demos/arweave/yarn.lock +2510 -0
  106. package/demos/simple/jsconfig.json +7 -0
  107. package/demos/simple/lib/encoder.js +375 -0
  108. package/demos/simple/next.config.js +6 -0
  109. package/demos/simple/package.json +24 -0
  110. package/demos/simple/pages/_app.js +9 -0
  111. package/demos/simple/pages/_document.js +13 -0
  112. package/demos/simple/pages/api/hello.js +5 -0
  113. package/demos/simple/pages/index.js +342 -0
  114. package/demos/simple/public/circuit.wasm +0 -0
  115. package/demos/simple/public/circuit_final.zkey +0 -0
  116. package/demos/simple/public/verification_key.json +149 -0
  117. package/demos/simple/yarn.lock +2519 -0
  118. package/docs/README.md +17 -0
  119. package/docs/simple-zkjson.md +210 -0
  120. package/docs/solidity-contracts.md +216 -0
  121. package/docs/zk-circuits.md +125 -0
  122. package/docs/zkdb-rollup.md +218 -0
  123. package/docs/zkjson-sdk.md +254 -0
  124. package/docs/zkjson-v1_5.md +365 -0
  125. package/package.json +16 -7
  126. package/sdk/contracts/NORollup.sol +13 -0
  127. package/sdk/package.json +15 -0
  128. package/sdk/yarn.lock +881 -0
  129. package/solidity/README.md +13 -0
  130. package/solidity/arguments.js +4 -0
  131. package/solidity/contracts/NORollup.sol +13 -0
  132. package/solidity/contracts/OPRollup.sol +14 -0
  133. package/solidity/contracts/ZKIPFS.sol +95 -0
  134. package/solidity/contracts/ZKJson.sol +21 -0
  135. package/solidity/contracts/ZKQuery.sol +286 -0
  136. package/solidity/contracts/ZKRollup.sol +35 -0
  137. package/solidity/contracts/apps/NORU.sol +66 -0
  138. package/solidity/contracts/apps/SimpleJSON.sol +64 -0
  139. package/solidity/contracts/apps/SimpleOPRU.sol +67 -0
  140. package/solidity/contracts/apps/SimpleRU.sol +67 -0
  141. package/solidity/contracts/apps/Token.sol +12 -0
  142. package/solidity/contracts/apps/ZKArweave.sol +89 -0
  143. package/solidity/contracts/apps/ZKBridge.sol +74 -0
  144. package/solidity/contracts/apps/ZKNFT.sol +63 -0
  145. package/solidity/contracts/verifiers/verifier_db.sol +275 -0
  146. package/solidity/contracts/verifiers/verifier_ipfs.sol +464 -0
  147. package/solidity/contracts/verifiers/verifier_json.sol +261 -0
  148. package/solidity/contracts/verifiers/verifier_rollup.sol +240 -0
  149. package/solidity/package.json +27 -0
  150. package/solidity/scripts/deploy.js +33 -0
  151. package/solidity/test/NORU.js +66 -0
  152. package/solidity/test/ZKArweave.js +97 -0
  153. package/solidity/test/arweave.js +55 -0
  154. package/solidity/test/bridge.js +71 -0
  155. package/solidity/test/simple.js +76 -0
  156. package/solidity/test/simpleOPRU.js +98 -0
  157. package/solidity/test/simpleRU.js +94 -0
  158. package/solidity/test/zknft.js +98 -0
  159. package/solidity/yarn.lock +4152 -0
  160. package/test/test.js +304 -0
  161. /package/{circomlibjs.js → sdk/circomlibjs.js} +0 -0
  162. /package/{collection.js → sdk/collection.js} +0 -0
  163. /package/{contracts → sdk/contracts}/OPRollup.sol +0 -0
  164. /package/{contracts → sdk/contracts}/ZKIPFS.sol +0 -0
  165. /package/{contracts → sdk/contracts}/ZKJson.sol +0 -0
  166. /package/{contracts → sdk/contracts}/ZKQuery.sol +0 -0
  167. /package/{contracts → sdk/contracts}/ZKRollup.sol +0 -0
  168. /package/{contracts → sdk/contracts}/apps/SimpleJSON.sol +0 -0
  169. /package/{contracts → sdk/contracts}/apps/SimpleOPRU.sol +0 -0
  170. /package/{contracts → sdk/contracts}/apps/SimpleRU.sol +0 -0
  171. /package/{contracts → sdk/contracts}/apps/Token.sol +0 -0
  172. /package/{contracts → sdk/contracts}/apps/ZKArweave.sol +0 -0
  173. /package/{contracts → sdk/contracts}/apps/ZKBridge.sol +0 -0
  174. /package/{contracts → sdk/contracts}/apps/ZKNFT.sol +0 -0
  175. /package/{contracts → sdk/contracts}/verifiers/verifier_db.sol +0 -0
  176. /package/{contracts → sdk/contracts}/verifiers/verifier_ipfs.sol +0 -0
  177. /package/{contracts → sdk/contracts}/verifiers/verifier_json.sol +0 -0
  178. /package/{contracts → sdk/contracts}/verifiers/verifier_rollup.sol +0 -0
  179. /package/{db.js → sdk/db.js} +0 -0
  180. /package/{doc.js → sdk/doc.js} +0 -0
  181. /package/{encoder-v1_5.js → sdk/encoder-v1_5.js} +0 -0
  182. /package/{encoder.js → sdk/encoder.js} +0 -0
  183. /package/{index.js → sdk/index.js} +0 -0
  184. /package/{json.js → sdk/json.js} +0 -0
  185. /package/{nft.js → sdk/nft.js} +0 -0
  186. /package/{parse.js → sdk/parse.js} +0 -0
  187. /package/{uint.js → sdk/uint.js} +0 -0
@@ -0,0 +1,365 @@
1
+ # zkJSON v1.5
2
+
3
+ zkJSON v1.5 drastically improves space efficiency with new value type definitions and prepended dictionary to remove path redundancy.
4
+
5
+ ## Encoding
6
+
7
+ ### Paths
8
+
9
+ zk circuits can neither handle objects nor dynamically nested arrays. So we first need to flatten all the paths into a simple array.
10
+
11
+ ```js
12
+ {
13
+ "a": 1,
14
+ "c": false,
15
+ "b": { "e": null, "d": "four" },
16
+ "f": 3.14,
17
+ "ghi": [ 5, 6, 7 ],
18
+ }
19
+ ```
20
+
21
+ becomes
22
+
23
+ ```js
24
+ [
25
+ [ [ "a" ], 1 ],
26
+ [ [ "c" ], false ]
27
+ [ [ "b", "e" ], null ],
28
+ [ [ "b", "d" ], "four" ],
29
+ [ [ "f" ], 3.14 ],
30
+ [ [ "ghi", 0 ], 5 ],
31
+ [ [ "ghi", 1 ], 6 ],
32
+ [ [ "ghi", 2 ], 7 ],
33
+ ]
34
+ ```
35
+
36
+ Each path will be converted to an unicode number.
37
+
38
+ ```js
39
+ [
40
+ [ [ [ 97 ] ], 1 ],
41
+ [ [ [ 99 ] ], false ]
42
+ [ [ [ 98 ], [ 101 ] ], null ],
43
+ [ [ [ 98 ], [ 100 ] ], "four" ],
44
+ [ [ [ 102 ] ], 3.14 ],
45
+ [ [ [ 103, 104, 105 ], 0 ], 5 ],
46
+ [ [ [ 103, 104, 105 ], 1 ], 6 ],
47
+ [ [ [ 103, 104, 105 ], 2 ], 7 ],
48
+ ]
49
+ ```
50
+
51
+ To make it deterministic, items must be lexicographically sorted by the paths.
52
+
53
+ ```js
54
+ [
55
+ [ [ [ 97 ] ], 1 ],
56
+ [ [ [ 98 ], [ 100 ] ], "four" ],
57
+ [ [ [ 98 ], [ 101 ] ], null ],
58
+ [ [ [ 99 ] ], false ],
59
+ [ [ [ 102 ] ], 3.14 ],
60
+ [ [ [ 103, 104, 105 ], 0 ], 5 ],
61
+ [ [ [ 103, 104, 105 ], 1 ], 6 ],
62
+ [ [ [ 103, 104, 105 ], 2 ], 7 ],
63
+ ]
64
+ ```
65
+
66
+ Here's a tricky part, if the value is an array, we need to create a path for each element, but we need to tell the difference between `ghi.0` and `ghi[0]` with just numbers. `ghi.0` is a path to an object, `ghi[0]` is a path to an array element. Also there is a case where the key is empty like `{ "" : "empty" }`. Another case to note is that just a primitive value without the top level element being an object is also a valid JSON, such as `null`, `true`, `[ 1, 2, 3]`, `1`. You can express the paths with empty string ` `, or something like `a..b` for `{ "a" : { "" : { "b" : 1 } } }`.
67
+
68
+ To address all these edge cases, we prefix each array key with the number of characters that follow, or `0` if the key is empty (followed by `1`) or an array index (followed by another`0`).
69
+
70
+ ```js
71
+ [
72
+ [ [ 1, 97 ] ], 1 ],
73
+ [ [ [ 1, 98 ], [ 1, 100 ] ], "four" ],
74
+ [ [ [ 1, 98 ], [ 1, 101 ] ], null ],
75
+ [ [ [ 1, 99 ] ], false ],
76
+ [ [ [ 1, 102 ] ], 3.14 ],
77
+ [ [ [ 3, 103, 104, 105 ], [ 0, 0, 0 ] ], 5 ],
78
+ [ [ [ 3, 103, 104, 105 ], [ 0, 0, 1 ] ], 6 ],
79
+ [ [ [ 3, 103, 104, 105 ], [ 0, 0, 2 ] ], 7 ],
80
+ ]
81
+ ```
82
+
83
+ Now we flatten the paths but also prefix them with how many nested keys each path contains.
84
+
85
+ ```js
86
+ [
87
+ [ [ 1, 1, 97 ], 1 ],
88
+ [ [ 2, 1, 98 , 1, 100 ], "four" ],
89
+ [ [ 2, 1, 98 , 1, 101 ], null ],
90
+ [ [ 1, 1, 99 ], false ],
91
+ [ [ 1, 1, 102 ], 3.14 ],
92
+ [ [ 2, 3, 103, 104, 105, 0, 0, 0 ], 5 ],
93
+ [ [ 2, 3, 103, 104, 105, 0, 0, 1 ], 6 ],
94
+ [ [ 2, 3, 103, 104, 105, 0, 0, 2 ] ], 7 ],
95
+ ]
96
+ ```
97
+
98
+ If the top level is a non-object value such as `1` and `null`, the flattened path is always `[ 0 ]`.
99
+
100
+
101
+ ### Dictionary
102
+
103
+ Here is the biggest improvement from v1. We create a dictionary for redundant paths.
104
+
105
+ ```js
106
+ [ "b" , "ghi" ]
107
+ ```
108
+
109
+ And replace the redundant paths with dictionary indexes.
110
+
111
+ ```js
112
+ [
113
+ [ [ "a" ], 1 ],
114
+ [ [ [ 0 ], "d" ], "four" ],
115
+ [ [ [ 0 ], "e" ], null ],
116
+ [ [ "c" ], false ],
117
+ [ [ "f" ], 3.14 ],
118
+ [ [ [ 1 ], 0 ], 5 ],
119
+ [ [ [ 1 ], 1 ], 6 ],
120
+ [ [ [ 1 ], 2 ], 7 ],
121
+ ]
122
+ ```
123
+
124
+ Dictionary references are prefixed with `[ 0, 3 ]` for a single reference, `[ 0, 4 ]` for multiple references.
125
+
126
+ ```js
127
+ [
128
+ [ [ 1, 97 ] ], 1 ],
129
+ [ [ [ 0, 3, 0 ], [ 1, 100 ] ], "four" ],
130
+ [ [ [ 0, 3, 0 ], [ 1, 101 ] ], null ],
131
+ [ [ [ 1, 99 ] ], false ],
132
+ [ [ [ 1, 102 ] ], 3.14 ],
133
+ [ [ [ 0, 3, 1 ], [ 0, 0, 0 ] ], 5 ],
134
+ [ [ [ 0, 3, 1 ], [ 0, 0, 1 ] ], 6 ],
135
+ [ [ [ 0, 3, 1 ], [ 0, 0, 2 ] ], 7 ],
136
+ ]
137
+ ```
138
+ Now flattened paths will become,
139
+
140
+ ```js
141
+ [
142
+ [ [ 1, 1, 97 ], 1 ],
143
+ [ [ 2, 0, 3, 0 , 1, 100 ], "four" ],
144
+ [ [ 2, 0, 3, 0 , 1, 101 ], null ],
145
+ [ [ 1, 1, 99 ], false ],
146
+ [ [ 1, 1, 102 ], 3.14 ],
147
+ [ [ 2, 0, 3, 1, 0, 0, 0 ], 5 ],
148
+ [ [ 2, 0, 3, 1, 0, 0, 1 ], 6 ],
149
+ [ [ 2, 0, 3, 1, 0, 0, 2 ] ], 7 ],
150
+ ]
151
+ ```
152
+
153
+ And dictionary itself will be encoded.
154
+
155
+ ```js
156
+ [ [ 1, 98 ], [ 3, 103, 104, 105] ] ]
157
+ ```
158
+
159
+ Each entry will be prefix by the value type and number of keys in the set.
160
+
161
+ ```js
162
+ [ [ 1, [ 7, 1, 98 ] ], [ 1, [ 7, 3, 103, 104, 105 ] ] ] ]
163
+ ```
164
+ The entire dictionary will be flattened and prefixed by `[1, 0, 2, number_of_entries ]`, and prepended to the rest of the encoding.
165
+
166
+ ```js
167
+ [
168
+ [ 1, 0, 2, 2, 1, 7, 1, 98, 1, 7, 3, 103, 104, 105 ],
169
+ [ [ 1, 1, 97 ], 1 ],
170
+ [ [ 2, 0, 3, 0 , 1, 100 ], "four" ],
171
+ [ [ 2, 0, 3, 0 , 1, 101 ], null ],
172
+ [ [ 1, 1, 99 ], false ],
173
+ [ [ 1, 1, 102 ], 3.14 ],
174
+ [ [ 2, 0, 3, 1, 0, 0, 0 ], 5 ],
175
+ [ [ 2, 0, 3, 1, 0, 0, 1 ], 6 ],
176
+ [ [ 2, 0, 3, 1, 0, 0, 2 ] ], 7 ],
177
+ ]
178
+ ```
179
+
180
+ Dictionary reduces the number of digits in the encoded data, which matters a lot when dealing with zk circuit signals (explained later). We don't consider uint8 (256bits) optimizations for byte sizes, but we count the digits to optimize for zk circuits. So `[ 3, 103, 104, 105 ]` counts as `10`, not `4`.
181
+
182
+ [MessagePack](https://msgpack.org/) does a great job optimizing for small byte sizes. But it's too complex and computationally heavy to process with zk circuits due to its dynamically nested nature to save spaces. zk curtuits cannot handle dynamic variables very well. Circuits handle pre-determined fixed size signals and variables.
183
+
184
+ For example, 3 of `[ 3, 103, 104, 105 ]` were replaced with `[ 0, 3, 1 ]` and `[ 1, 7, 3, 103, 104, 105 ]`, which reduced the digits from `30` to `21`. The saving becomes bigger with deeply nested arrays and objects.
185
+
186
+ There are only 3 types used in a dictionary. A more comprehensive example is the following.
187
+
188
+ - `3` : positibe integer
189
+ - `7` : string
190
+ - `9` : reference to another entry
191
+
192
+ ```js
193
+ [ "abc" , [ "abc", 1, "def" ], [ "abc", 1, "def", "ghi", "abc" ] ]
194
+ ```
195
+
196
+ will be represented as,
197
+
198
+ ```js
199
+ [
200
+ [ 1, [ 7, 97, 98, 99 ] ],
201
+ [ 3, [ 9, 0 ], [ 3, 1 ], [ 7, 100, 101, 102 ] ],
202
+ [ 3, [ 9, 1 ], [ 7, 103, 104, 105 ], [ 9, 0 ] ]
203
+ ]
204
+ ```
205
+
206
+ and the rest is the same.
207
+
208
+ ### Values
209
+
210
+ Let's numerify the values in a similar fashion. There are only 6 valid data types in JSON ( `null` / `boolean` / `number` / `string` / `array` / `object` ), and since the paths are flattened, we need to handle only 4 primitive types. We assign a type number to each.
211
+
212
+ - null (`0`)
213
+ - boolean | true (`1`)
214
+ - boolean | false (`2`)
215
+ - number | positive integer (`3`)
216
+ - number | negative integer (`4`)
217
+ - number | positive float (`5`)
218
+ - number | negative float (`6`)
219
+ - string (`7`)
220
+ - array & object (`8`)
221
+ - dictionary reference (`9`)
222
+
223
+ The first digit will always be the type number.
224
+
225
+ ###### null (0)
226
+
227
+ `null` is always `[ 0 ]` as there's nothing else to tell.
228
+
229
+ ###### boolean (1|2)
230
+
231
+ There are only 2 cases. `true` is `[ 1 ]` and `false` is `[ 2 ]`.
232
+
233
+ ###### number (3|4|5|6)
234
+
235
+ `number` is a bit tricky as we need to differentiate integers and floats, and also positive numbers and negative ones. Remember that circuits can only handle natural numbers. A number contains 4 elements.
236
+
237
+ - 1st element
238
+ - `3` : positive integer
239
+ - `4` : negative integer
240
+ - `5` : positive float
241
+ - `6` : negative float
242
+ - 2nd - how many digits after `.`, omitted in case of an integer
243
+ - 3rd (or 2nd) - actual number without `.`
244
+
245
+ for instance,
246
+
247
+ - `1` : `[ 3, 1 ]`
248
+ - `-1` : `[ 4, 1 ]`
249
+ - `3.14` : `[ 5, 2, 314 ]`
250
+ - `-3.14` : `[ 6, 2, 314 ]`
251
+
252
+ ###### string (7)
253
+
254
+ The first digit is the type `7` and the second digit tells how many characters, then each character is converted to a unicode number (e.g. `abc` = `[ 7, 3, 97, 98, 99 ]`).
255
+
256
+ ###### array | object (8)
257
+
258
+ In the case of an array and object, it prefixes `8` and recursively encodes all the nested values. The final array includes internal paths too.
259
+
260
+ - `[ 1, 2 ]` : `[ 8, 1, 0, 0, 0, 2, 1, 0, 1, 1, 0, 0, 1, 2, 1, 0, 2 ]`
261
+
262
+ Note that the path to `1` is `1, 0, 0, 0` and the path to `2` is `1, 0, 0, 1`, and they are included.
263
+
264
+ Now let's convert the values in our original JSON example.
265
+
266
+ ```js
267
+ [
268
+ [ 1, 0, 2, 2, 1, 7, 1, 98, 1, 7, 3, 103, 104, 105 ],
269
+ [ [ 1, 1, 97 ], [ 3, 1 ] ],
270
+ [ [ 2, 0, 3, 0, 1, 100 ], [ 7, 4, 102, 111, 117, 114 ] ],
271
+ [ [ 2, 0, 3, 0, 1, 101 ], [ 0 ] ],
272
+ [ [ 1, 1, 99 ], [ 2 ] ],
273
+ [ [ 1, 1, 102 ], [ 5, 314 ] ],
274
+ [ [ 2, 0, 3, 1, 0 ], [ 3, 5 ] ],
275
+ [ [ 2, 0, 3, 1, 1 ], [ 3, 6 ] ],
276
+ [ [ 2, 0, 3, 1, 2 ], [ 3, 7 ] ],
277
+ ]
278
+ ```
279
+
280
+ ### Flattening
281
+
282
+ Now we are to flatten the entire nested arrays, but each number must be prefixed by the number of digits that contains, otherwise, there's no way to tell where to partition the series of digits. And here's another tricky part, if the number contains more than 9 digits, you cannot prefix it with 10, 11, 12 ... because when all the numbers are concatenated later, `10` doesn't mean that `10` digits follow, but it means `1` digit follows and it's `0`. So we allow max 8 digits in each partition and `9` means there will be another partition(s) following the current one.
283
+
284
+ - `123` : `[ 3, 123 ]`
285
+ - `12345678` : `[ 8, 12345678 ]`
286
+ - `1234567890` : `[ 9, 12345678, 2, 90 ]`
287
+
288
+ By the way, digits are in fact stored as strings, so a leading 0 won't disappear.
289
+
290
+ - `1234567809` : `[ "9", "12345678", "2", "09" ]`
291
+
292
+
293
+ This is the prefixed version.
294
+
295
+ ```js
296
+ [
297
+ [ 1, 1, 1, 0, 1, 2, 1, 2, 1, 1, 1, 7, 1, 1, 2, 98, 1, 1, 1, 7, 1, 3, 3, 103, 3, 104, 3, 105 ],
298
+ [ [ 1, 1, 1, 1, 2, 97 ], [ 1, 3, 1, 1 ] ],
299
+ [ [ 1, 2, 1, 0, 1, 3, 1, 0, 1, 1, 3, 100 ], [ 1, 7, 1, 4, 3, 102, 3, 111, 3, 117, 3, 114 ] ],
300
+ [ [ 1, 2, 1, 0, 1, 3, 1, 0, 1, 1, 3, 101 ], [ 1, 0 ] ],
301
+ [ [ 1, 1, 1, 1, 2, 99 ], [ 2, 2 ] ],
302
+ [ [ 1, 1, 1, 1, 3, 102 ], [ 1, 5, 3, 314 ] ],
303
+ [ [ 1, 2, 1, 0, 1, 3, 1, 1, 1, 0 ], [ 1, 3, 1, 5 ] ],
304
+ [ [ 1, 2, 1, 0, 1, 3, 1, 1, 1, 1 ], [ 1, 3, 1, 6 ] ],
305
+ [ [ 1, 2, 1, 0, 1, 3, 1, 1, 1, 2 ], [ 1, 3, 1, 7 ] ],
306
+ ]
307
+ ```
308
+
309
+ Then this is the final form all flattened.
310
+
311
+ ```js
312
+ [ 1, 1, 1, 0, 1, 2, 1, 2, 1, 1, 1, 7, 1, 1, 2, 98, 1, 1, 1, 7, 1, 3, 3, 103, 3, 104, 3, 105, 1, 1, 1, 1, 2, 97, 1, 3, 1, 1, 1, 2, 1, 0, 1, 3, 1, 0, 1, 1, 3, 100, 1, 7, 1, 4, 3, 102, 3, 111, 3, 117, 3, 114, 1, 2, 1, 0, 1, 3, 1, 0, 1, 1, 3, 101, 1, 0, 1, 1, 1, 1, 2, 99, 2, 2, 1, 1, 1, 1, 3, 102, 1, 5, 3, 314, 1, 2, 1, 0, 1, 3, 1, 1, 1, 0, 1, 3, 1, 5, 1, 2, 1, 0, 1, 3, 1, 1, 1, 1, 1, 3, 1, 6, 1, 2, 1, 0, 1, 3, 1, 1, 1, 2, 1, 3, 1, 7 ]
313
+ ```
314
+
315
+ ### ZK Circuit Signals
316
+
317
+ It's 144 integers, or 182 digits. The original JSON was 66 character long when JSON.stringified, so it's not too bad considering integer vs character (let's say one ascii char takes up 3 digits and one unicode char takes up 7 digits). And zk circuits and Solidity cannot handle just stringified JSONs anyway. But it gets better.
318
+
319
+ When passed to a circuit, all digits will be concatenated into one integer. [Circom](https://docs.circom.io/circom-language/basic-operators/) by default uses a modulo with
320
+
321
+ `21888242871839275222246405745257275088548364400416034343698204186575808495617` (77 digits)
322
+
323
+ which means up to 76 digits are safe and a 77-digit number could overflow, which is also within the range of `uint / uint256` in Solidity.
324
+
325
+ So to convert the encoded array to a circuit signal, it becomes
326
+
327
+ ```js
328
+ [
329
+ 111012121117112981117133103310431051111297131112101310113100171431023111311,
330
+ 731141210131011310110111129922111131021533141210131110131512101311111316121,
331
+ 01311121317
332
+ ]
333
+ ```
334
+
335
+ If you observe carefully, there's room for more compression. Most digits are a single digit with a prefix of `1`, so we can remove the prefixes and join the succession of single digits, and we can use `0` and the number of single digits in the succession. For instance `121110111211` becomes `06210121`, and we save 4 digits.
336
+
337
+ We will prefix each integer with `1`, since now `0` could come at the beginning and it disappears without the prefix. So for example,
338
+
339
+ `032123314121331033104310509000210523310331043105090012106233103310431051010`
340
+
341
+ will be prefixed with `1` and become
342
+
343
+ `1032123314121331033104310509000210523310331043105090012106233103310431051010`
344
+
345
+ otherwise the first `0` will disapper when being evaluated as a number.
346
+
347
+ ```js
348
+ [
349
+ 1071022171298031733103310431051111297073120301310017143102311131173114042030,
350
+ 11131010301129903211310215123314092031000350920310013609203100237
351
+ ]
352
+ ```
353
+
354
+ Now it's much shorter than before. What's surprising here is that the entire JSON is compressed into just 2 integers in the end. It's just `uint[2]` in Solidity. This indeed is extreme efficiency! The zkJSON circuit by default allows up to 256 integers (256 * 76 safe digits), which can contain a huge JSON data size, and Solidity handles it efficiently with a dynamic array `uint[]`, which is optimized with [Yul](https://docs.soliditylang.org/en/latest/yul.html) assembly language. What's even better is that the only bits passed to Solidity is the tiny bits of the value at the queried path, and not the entire JSON bits. So if you are querying the value at the path `a`, `11111297`(path: "a") and `11311`(value: 1) are the only digits passed to Solidity as public signals of zkp.
355
+
356
+
357
+ To compare with zkJSON v1, v1 generates `uint[3]` for the same data. v1.5 is much more compact with dictionary and new value types.
358
+
359
+ ```js
360
+ [
361
+ 1111129706210121298113100131431023111311731141211298113101030112990410113102,
362
+ 1032123314121331033104310509000210523310331043105090012106233103310431051010,
363
+ 10522107
364
+ ]
365
+ ```
package/package.json CHANGED
@@ -1,15 +1,24 @@
1
1
  {
2
2
  "name": "zkjson",
3
- "version": "0.6.0",
4
- "description": "Zero Knowledge Provable JSON",
3
+ "version": "1.0.2",
5
4
  "main": "index.js",
6
5
  "license": "MIT",
6
+ "scripts": {
7
+ "ceremony": "node circom/scripts/ceremony.js",
8
+ "compile": "node circom/scripts/compile.js"
9
+ },
7
10
  "dependencies": {
8
- "blake-hash": "^2.0.0",
9
- "blake2b": "^2.1.3",
10
- "ethers": "^5.5.1",
11
- "ffjavascript": "^0.2.45",
11
+ "chai": "^4",
12
+ "circom_tester": "^0.0.20",
13
+ "circomlib": "^2.0.5",
14
+ "circomlibjs": "^0.1.7",
15
+ "mocha": "^10.2.0",
16
+ "multiformats": "^13.0.1",
12
17
  "ramda": "^0.29.1",
13
- "snarkjs": "^0.7.3"
18
+ "uuid": "^9.0.1",
19
+ "yargs": "^17.7.2"
20
+ },
21
+ "devDependencies": {
22
+ "@msgpack/msgpack": "^3.0.1"
14
23
  }
15
24
  }
@@ -0,0 +1,13 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity >=0.7.0 <0.9.0;
4
+ import "./ZKQuery.sol";
5
+
6
+ contract NORollup is ZKQuery {
7
+ function _validateQuery(uint[] memory zkp, uint size_path, uint size_val) internal view returns(uint[] memory){
8
+ require(zkp[8] == 1, "value doesn't exist");
9
+ uint[] memory value = new uint[](size_val);
10
+ for(uint i = 9 + size_path; i < 9 + size_path + size_val; i++) value[i - (9 + size_path)] = zkp[i];
11
+ return toArr(value);
12
+ }
13
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "zkjson",
3
+ "version": "0.6.1",
4
+ "description": "Zero Knowledge Provable JSON",
5
+ "main": "index.js",
6
+ "license": "MIT",
7
+ "dependencies": {
8
+ "blake-hash": "^2.0.0",
9
+ "blake2b": "^2.1.3",
10
+ "ethers": "^5.5.1",
11
+ "ffjavascript": "^0.2.45",
12
+ "ramda": "^0.29.1",
13
+ "snarkjs": "^0.7.3"
14
+ }
15
+ }