zkjson 0.1.10 → 0.1.11
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.
- package/contracts/ZKRollup.sol +8 -11
- package/db.js +73 -7
- package/encoder.js +5 -0
- package/index.js +2 -1
- package/package.json +1 -1
- package/rollup.js +224 -0
package/contracts/ZKRollup.sol
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
pragma solidity >=0.7.0 <0.9.0;
|
4
4
|
import "hardhat/console.sol";
|
5
|
-
import "./ZKJson.sol";
|
6
5
|
import "./ZKQuery.sol";
|
7
6
|
|
8
7
|
interface VerifierRU {
|
@@ -12,7 +11,7 @@ interface VerifierRU {
|
|
12
11
|
|
13
12
|
contract ZKRollup is ZKQuery {
|
14
13
|
address public verifierRU;
|
15
|
-
address public
|
14
|
+
address public committer;
|
16
15
|
uint public root;
|
17
16
|
|
18
17
|
function _verifyRU(uint[] calldata zkp) internal view returns (bool) {
|
@@ -29,29 +28,27 @@ contract ZKRollup is ZKQuery {
|
|
29
28
|
return true;
|
30
29
|
}
|
31
30
|
|
32
|
-
function _validateQueryRU(uint[] memory path, uint[] calldata zkp, uint
|
31
|
+
function _validateQueryRU(uint[] memory path, uint[] calldata zkp, uint size_path, uint size_val) internal view returns(uint[] memory){
|
33
32
|
require(zkp[19] == root, "root mismatch");
|
34
|
-
require(zkp[
|
35
|
-
require(zkp[
|
33
|
+
require(zkp[size_path + size_val + 10] == path[0], "wrong collection");
|
34
|
+
require(zkp[size_path + size_val + 11] == path[1], "wrong doc");
|
36
35
|
require(zkp[8] == 1, "value doesn't exist");
|
37
|
-
require(path.length <=
|
36
|
+
require(path.length <= size_path + size_val, "path too long");
|
38
37
|
for(uint i = 9; i < 9 + path.length - 2; i++) require(path[i - 7] == zkp[i], "wrong path");
|
39
|
-
uint[] memory value = new uint[](
|
40
|
-
for(uint i = 9 +
|
38
|
+
uint[] memory value = new uint[](size_val);
|
39
|
+
for(uint i = 9 + size_path; i < 9 + size_path + size_val; i++) value[i - (9 + size_path)] = zkp[i];
|
41
40
|
return toArr(value);
|
42
41
|
}
|
43
42
|
|
44
43
|
function commit (uint[] calldata zkp) public returns (uint) {
|
45
44
|
require (zkp[9] == root, "wrong merkle root");
|
46
|
-
require(msg.sender ==
|
45
|
+
require(msg.sender == committer, "sender is not committer");
|
47
46
|
root = zkp[8];
|
48
47
|
verifyRU(zkp);
|
49
48
|
return root;
|
50
|
-
|
51
49
|
}
|
52
50
|
|
53
51
|
function verifyRU(uint[] calldata zkp) public view returns (bool) {
|
54
52
|
return _verifyRU(zkp);
|
55
53
|
}
|
56
|
-
|
57
54
|
}
|
package/db.js
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
const newMemEmptyTrie = require("./circomlibjs").newMemEmptyTrie
|
2
|
+
const snarkjs = require("snarkjs")
|
2
3
|
const { range } = require("ramda")
|
3
4
|
const {
|
4
5
|
pad,
|
@@ -7,7 +8,7 @@ const {
|
|
7
8
|
val2str,
|
8
9
|
id2str,
|
9
10
|
encode,
|
10
|
-
|
11
|
+
toIndex,
|
11
12
|
} = require("./encoder")
|
12
13
|
const Collection = require("./collection")
|
13
14
|
|
@@ -19,7 +20,15 @@ class DB {
|
|
19
20
|
size_json = 256,
|
20
21
|
size_txs = 10,
|
21
22
|
level_col = 8,
|
23
|
+
wasm,
|
24
|
+
zkey,
|
25
|
+
wasmRU,
|
26
|
+
zkeyRU,
|
22
27
|
}) {
|
28
|
+
this.wasm = wasm
|
29
|
+
this.zkey = zkey
|
30
|
+
this.wasmRU = wasmRU
|
31
|
+
this.zkeyRU = zkeyRU
|
23
32
|
this.level_col = level_col
|
24
33
|
this.size = size_val
|
25
34
|
this.size_path = size_path
|
@@ -47,7 +56,63 @@ class DB {
|
|
47
56
|
siblings = siblings.map(s => s.toString())
|
48
57
|
return { isOld0, oldRoot, oldKey, oldValue, siblings, newRoot }
|
49
58
|
}
|
59
|
+
_getVal(j, p) {
|
60
|
+
if (p.length === 0) {
|
61
|
+
return j
|
62
|
+
} else {
|
63
|
+
const sp = p[0].split("[")
|
64
|
+
for (let v of sp) {
|
65
|
+
if (/]$/.test(v)) {
|
66
|
+
j = j[v.replace(/]$/, "") * 1]
|
67
|
+
} else {
|
68
|
+
j = j[v]
|
69
|
+
}
|
70
|
+
}
|
71
|
+
return this._getVal(j, p.slice(1))
|
72
|
+
}
|
73
|
+
}
|
74
|
+
getVal(j, p) {
|
75
|
+
if (p === "") return j
|
76
|
+
return this._getVal(j, p.split("."))
|
77
|
+
}
|
50
78
|
|
79
|
+
async genProof({ json, col_id, path, id }) {
|
80
|
+
const inputs = await this.getInputs({
|
81
|
+
id,
|
82
|
+
col_id,
|
83
|
+
json,
|
84
|
+
path,
|
85
|
+
val: this.getVal(json, path),
|
86
|
+
})
|
87
|
+
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
|
88
|
+
inputs,
|
89
|
+
this.wasm,
|
90
|
+
this.zkey
|
91
|
+
)
|
92
|
+
return [
|
93
|
+
...proof.pi_a.slice(0, 2),
|
94
|
+
...proof.pi_b[0].slice(0, 2).reverse(),
|
95
|
+
...proof.pi_b[1].slice(0, 2).reverse(),
|
96
|
+
...proof.pi_c.slice(0, 2),
|
97
|
+
...publicSignals,
|
98
|
+
]
|
99
|
+
}
|
100
|
+
|
101
|
+
async genRollupProof(txs) {
|
102
|
+
const inputs = await this.getRollupInputs({ queries: txs })
|
103
|
+
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
|
104
|
+
inputs,
|
105
|
+
this.wasmRU,
|
106
|
+
this.zkeyRU
|
107
|
+
)
|
108
|
+
return [
|
109
|
+
...proof.pi_a.slice(0, 2),
|
110
|
+
...proof.pi_b[0].slice(0, 2).reverse(),
|
111
|
+
...proof.pi_b[1].slice(0, 2).reverse(),
|
112
|
+
...proof.pi_c.slice(0, 2),
|
113
|
+
...publicSignals,
|
114
|
+
]
|
115
|
+
}
|
51
116
|
async getRollupInputs({ queries }) {
|
52
117
|
let write, _json
|
53
118
|
let oldRoot = []
|
@@ -79,6 +144,7 @@ class DB {
|
|
79
144
|
siblings.push(range(0, this.level).map(() => "0"))
|
80
145
|
isOld0.push("0")
|
81
146
|
oldRoot_db.push(newRoot_db[i - 1])
|
147
|
+
newRoot_db.push(newRoot_db[i - 1])
|
82
148
|
oldKey_db.push("0")
|
83
149
|
oldValue_db.push("0")
|
84
150
|
siblings_db.push(range(0, this.level_col).map(() => "0"))
|
@@ -92,9 +158,9 @@ class DB {
|
|
92
158
|
const icol = this.parse(res, tree, this.level)
|
93
159
|
const idb = this.parse(res2, this.tree, this.level_col)
|
94
160
|
_res = idb
|
95
|
-
const _newKey =
|
161
|
+
const _newKey = toIndex(v[1])
|
96
162
|
json.push(pad(val2str(encode(_json)), this.size_json))
|
97
|
-
const _newKey_db = v[0]
|
163
|
+
const _newKey_db = v[0].toString()
|
98
164
|
fnc.push(update ? [0, 1] : [1, 0])
|
99
165
|
newRoot.push(idb.newRoot)
|
100
166
|
oldRoot.push(icol.oldRoot)
|
@@ -140,8 +206,8 @@ class DB {
|
|
140
206
|
} = await this.insert(col_id, id, json)
|
141
207
|
const icol = this.parse(res, tree, this.level)
|
142
208
|
const idb = this.parse(res2, this.tree, this.level_col)
|
143
|
-
const newKey =
|
144
|
-
const newKey_db = col_id
|
209
|
+
const newKey = toIndex(id)
|
210
|
+
const newKey_db = col_id.toString()
|
145
211
|
return {
|
146
212
|
fnc: update ? [0, 1] : [1, 0],
|
147
213
|
oldRoot: icol.oldRoot,
|
@@ -179,7 +245,7 @@ class DB {
|
|
179
245
|
json: col_inputs.json,
|
180
246
|
root: col_inputs.root,
|
181
247
|
siblings: col_inputs.siblings,
|
182
|
-
key:
|
248
|
+
key: toIndex(id),
|
183
249
|
col_key,
|
184
250
|
col_siblings,
|
185
251
|
col_root,
|
@@ -244,7 +310,7 @@ class DB {
|
|
244
310
|
return await _col.get(_key)
|
245
311
|
}
|
246
312
|
async getCol(_key) {
|
247
|
-
const id =
|
313
|
+
const id = toIndex(_key)
|
248
314
|
return await this.tree.find(id)
|
249
315
|
}
|
250
316
|
}
|
package/encoder.js
CHANGED
@@ -453,6 +453,9 @@ const fromSignal = str2val
|
|
453
453
|
const toIndex = str2id
|
454
454
|
const fromIndex = id2str
|
455
455
|
|
456
|
+
const path = p => toSignal(encodePath(p))
|
457
|
+
const val = v => toSignal(encodeVal(v))
|
458
|
+
|
456
459
|
module.exports = {
|
457
460
|
encode,
|
458
461
|
decode,
|
@@ -471,4 +474,6 @@ module.exports = {
|
|
471
474
|
fromSignal,
|
472
475
|
toIndex,
|
473
476
|
fromIndex,
|
477
|
+
path,
|
478
|
+
val,
|
474
479
|
}
|
package/index.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
const encoder = require("./encoder")
|
2
2
|
const DB = require("./db")
|
3
3
|
const Doc = require("./doc")
|
4
|
+
const Rollup = require("./rollup")
|
4
5
|
const Collection = require("./collection")
|
5
6
|
|
6
|
-
module.exports = { ...encoder, DB, Collection, Doc }
|
7
|
+
module.exports = { ...encoder, DB, Collection, Doc, Rollup }
|
package/package.json
CHANGED
package/rollup.js
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
const snarkjs = require("snarkjs")
|
2
|
+
const { resolve } = require("path")
|
3
|
+
const { pad, toSignal, encode, encodePath, encodeVal } = require("./encoder")
|
4
|
+
const DB = require("./db")
|
5
|
+
const { range } = require("ramda")
|
6
|
+
|
7
|
+
module.exports = class Rollup {
|
8
|
+
constructor({
|
9
|
+
size_val = 5,
|
10
|
+
size_path = 5,
|
11
|
+
size_json = 256,
|
12
|
+
level = 100,
|
13
|
+
size_txs = 10,
|
14
|
+
level_col = 8,
|
15
|
+
wasm,
|
16
|
+
zkey,
|
17
|
+
}) {
|
18
|
+
this.size_val = size_val
|
19
|
+
this.size_path = size_path
|
20
|
+
this.size_json = size_json
|
21
|
+
this.size_txs = size_txs
|
22
|
+
this.level = level
|
23
|
+
this.level_col = level_col
|
24
|
+
this.wasm = wasm
|
25
|
+
this.zkey = zkey
|
26
|
+
}
|
27
|
+
async init() {
|
28
|
+
this.db = new DB({
|
29
|
+
level: this.level,
|
30
|
+
size_path: this.size_path,
|
31
|
+
size_val: this.size_val,
|
32
|
+
size_json: this.size_json,
|
33
|
+
size_txs: this.size_txs,
|
34
|
+
level_col: this.level_col,
|
35
|
+
})
|
36
|
+
await this.db.init()
|
37
|
+
}
|
38
|
+
async getInputs(queries) {
|
39
|
+
let write, _json
|
40
|
+
let oldRoot = []
|
41
|
+
let newRoot = []
|
42
|
+
let oldKey = []
|
43
|
+
let oldValue = []
|
44
|
+
let siblings = []
|
45
|
+
let isOld0 = []
|
46
|
+
let oldRoot_db = []
|
47
|
+
let newRoot_db = []
|
48
|
+
let oldKey_db = []
|
49
|
+
let oldValue_db = []
|
50
|
+
let siblings_db = []
|
51
|
+
let isOld0_db = []
|
52
|
+
let newKey_db = []
|
53
|
+
let newKey = []
|
54
|
+
let _res
|
55
|
+
let json = []
|
56
|
+
let fnc = []
|
57
|
+
for (let i = 0; i < this.size_txs; i++) {
|
58
|
+
const v = queries[i]
|
59
|
+
if (!v) {
|
60
|
+
json.push(range(0, this.size_json).map(() => "0"))
|
61
|
+
fnc.push([0, 0])
|
62
|
+
newRoot.push(newRoot[i - 1])
|
63
|
+
oldRoot.push("0")
|
64
|
+
oldKey.push("0")
|
65
|
+
oldValue.push("0")
|
66
|
+
siblings.push(range(0, this.level).map(() => "0"))
|
67
|
+
isOld0.push("0")
|
68
|
+
oldRoot_db.push(newRoot_db[i - 1])
|
69
|
+
oldKey_db.push("0")
|
70
|
+
oldValue_db.push("0")
|
71
|
+
siblings_db.push(range(0, this.level_col).map(() => "0"))
|
72
|
+
isOld0_db.push("0")
|
73
|
+
newKey_db.push("0")
|
74
|
+
newKey.push("0")
|
75
|
+
continue
|
76
|
+
}
|
77
|
+
_json = v[2]
|
78
|
+
const { update, tree, col: res2, doc: res } = await this.insert(...v)
|
79
|
+
const icol = this.parse(res, tree, this.level)
|
80
|
+
const idb = this.parse(res2, this.tree, this.level_col)
|
81
|
+
_res = idb
|
82
|
+
const _newKey = str2id(v[1])
|
83
|
+
json.push(pad(val2str(encode(_json)), this.size_json))
|
84
|
+
const _newKey_db = v[0]
|
85
|
+
fnc.push(update ? [0, 1] : [1, 0])
|
86
|
+
newRoot.push(idb.newRoot)
|
87
|
+
oldRoot.push(icol.oldRoot)
|
88
|
+
oldKey.push(icol.oldKey)
|
89
|
+
oldValue.push(icol.oldValue)
|
90
|
+
siblings.push(icol.siblings)
|
91
|
+
isOld0.push(icol.isOld0)
|
92
|
+
oldRoot_db.push(idb.oldRoot)
|
93
|
+
newRoot_db.push(idb.newRoot)
|
94
|
+
oldKey_db.push(idb.oldKey)
|
95
|
+
oldValue_db.push(idb.oldValue)
|
96
|
+
siblings_db.push(idb.siblings)
|
97
|
+
isOld0_db.push(idb.isOld0)
|
98
|
+
newKey_db.push(_newKey_db)
|
99
|
+
newKey.push(_newKey)
|
100
|
+
}
|
101
|
+
|
102
|
+
return {
|
103
|
+
fnc,
|
104
|
+
oldRoot,
|
105
|
+
newRoot,
|
106
|
+
oldKey,
|
107
|
+
oldValue,
|
108
|
+
siblings,
|
109
|
+
isOld0,
|
110
|
+
oldRoot_db,
|
111
|
+
oldKey_db,
|
112
|
+
oldValue_db,
|
113
|
+
siblings_db,
|
114
|
+
isOld0_db,
|
115
|
+
newKey_db,
|
116
|
+
newKey,
|
117
|
+
json,
|
118
|
+
}
|
119
|
+
}
|
120
|
+
async genProof(queries) {
|
121
|
+
const inputs = await this.getInputs(queries)
|
122
|
+
console.log(inputs)
|
123
|
+
return 3
|
124
|
+
}
|
125
|
+
async genProof2(col, doc, tar, path) {
|
126
|
+
const val = this.getVal(tar, path)
|
127
|
+
|
128
|
+
const col_root = this.db.tree.F.toObject(this.db.tree.root).toString()
|
129
|
+
const col_res = await this.db.getCol(doc)
|
130
|
+
|
131
|
+
let col_siblings = col_res.siblings
|
132
|
+
for (let i = 0; i < col_siblings.length; i++)
|
133
|
+
col_siblings[i] = this.db.tree.F.toObject(col_siblings[i])
|
134
|
+
while (col_siblings.length < this.level_col) col_siblings.push(0)
|
135
|
+
col_siblings = col_siblings.map(s => s.toString())
|
136
|
+
const col_key = col
|
137
|
+
|
138
|
+
const _col = this.db.getColTree(col)
|
139
|
+
const root = _col.tree.F.toObject(_col.tree.root).toString()
|
140
|
+
const res = await _col.get(doc)
|
141
|
+
let _siblings = res.siblings
|
142
|
+
for (let i = 0; i < _siblings.length; i++)
|
143
|
+
_siblings[i] = _col.tree.F.toObject(_siblings[i])
|
144
|
+
while (_siblings.length < this.level) _siblings.push(0)
|
145
|
+
_siblings = _siblings.map(s => s.toString())
|
146
|
+
const key = toIndex(doc)
|
147
|
+
|
148
|
+
const _json = pad(toSignal(encode(tar)), this.size_json)
|
149
|
+
const _path = pad(toSignal(encodePath(path)), this.size_path)
|
150
|
+
const _val = pad(toSignal(encodeVal(val)), this.size)
|
151
|
+
const _write = {
|
152
|
+
json: _json,
|
153
|
+
path: _path,
|
154
|
+
val: _val,
|
155
|
+
root,
|
156
|
+
siblings: _siblings,
|
157
|
+
key,
|
158
|
+
col_key,
|
159
|
+
col_siblings,
|
160
|
+
col_root,
|
161
|
+
}
|
162
|
+
const { proof: proof2, publicSignals: sigs } =
|
163
|
+
await snarkjs.groth16.fullProve(
|
164
|
+
_write,
|
165
|
+
resolve(
|
166
|
+
__dirname,
|
167
|
+
"../../circom/build/circuits/db/index_js/index.wasm"
|
168
|
+
),
|
169
|
+
resolve(__dirname, "../../circom/build/circuits/db/index_0001.zkey")
|
170
|
+
)
|
171
|
+
return [
|
172
|
+
...proof2.pi_a.slice(0, 2),
|
173
|
+
...proof2.pi_b[0].slice(0, 2).reverse(),
|
174
|
+
...proof2.pi_b[1].slice(0, 2).reverse(),
|
175
|
+
...proof2.pi_c.slice(0, 2),
|
176
|
+
...sigs,
|
177
|
+
]
|
178
|
+
}
|
179
|
+
|
180
|
+
async getInputs2({ json, path }) {
|
181
|
+
return {
|
182
|
+
json: pad(toSignal(encode(json)), this.size_json),
|
183
|
+
path: pad(toSignal(encodePath(path)), this.size_path),
|
184
|
+
val: pad(toSignal(encodeVal(this.getVal(json, path))), this.size_val),
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
_getVal(j, p) {
|
189
|
+
if (p.length === 0) {
|
190
|
+
return j
|
191
|
+
} else {
|
192
|
+
const sp = p[0].split("[")
|
193
|
+
for (let v of sp) {
|
194
|
+
if (/]$/.test(v)) {
|
195
|
+
j = j[v.replace(/]$/, "") * 1]
|
196
|
+
} else {
|
197
|
+
j = j[v]
|
198
|
+
}
|
199
|
+
}
|
200
|
+
return this._getVal(j, p.slice(1))
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
getVal(j, p) {
|
205
|
+
if (p === "") return j
|
206
|
+
return this._getVal(j, p.split("."))
|
207
|
+
}
|
208
|
+
|
209
|
+
async genProof2(json, path) {
|
210
|
+
const inputs = await this.getInputs(json, path)
|
211
|
+
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
|
212
|
+
inputs,
|
213
|
+
this.wasm,
|
214
|
+
this.zkey
|
215
|
+
)
|
216
|
+
return [
|
217
|
+
...proof.pi_a.slice(0, 2),
|
218
|
+
...proof.pi_b[0].slice(0, 2).reverse(),
|
219
|
+
...proof.pi_b[1].slice(0, 2).reverse(),
|
220
|
+
...proof.pi_c.slice(0, 2),
|
221
|
+
...publicSignals,
|
222
|
+
]
|
223
|
+
}
|
224
|
+
}
|