zkjson 0.1.10 → 0.1.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|