@@ -64,6 +64,56 @@ library PartialMerkleTree {
64
64
tree.rootEdge = e;
65
65
}
66
66
67
+ function commitBranchOfNonInclusion (
68
+ Tree storage tree ,
69
+ bytes key ,
70
+ bytes32 potentialSiblingLabel ,
71
+ bytes32 potentialSiblingValue ,
72
+ uint branchMask ,
73
+ bytes32 [] siblings
74
+ ) internal {
75
+ D.Label memory k = D.Label (keccak256 (key), 256 );
76
+ D.Edge memory e;
77
+ // e.node(0x083d)
78
+ for (uint i = 0 ; branchMask != 0 ; i++ ) {
79
+ // retrieve edge data with branch mask
80
+ uint bitSet = Utils.lowestBitSet (branchMask);
81
+ branchMask &= ~ (uint (1 ) << bitSet);
82
+ (k, e.label) = Utils.splitAt (k, 255 - bitSet);
83
+ uint bit;
84
+ (bit, e.label) = Utils.chopFirstBit (e.label);
85
+
86
+ if (i == 0 ) {
87
+ e.label.length = bitSet;
88
+ e.label.data = potentialSiblingLabel;
89
+ e.node = potentialSiblingValue;
90
+ }
91
+
92
+ // find upper node with retrieved edge & sibling
93
+ bytes32 [2 ] memory edgeHashes;
94
+ edgeHashes[bit] = edgeHash (e);
95
+ edgeHashes[1 - bit] = siblings[siblings.length - i - 1 ];
96
+ bytes32 upperNode = keccak256 (abi.encode (edgeHashes[0 ], edgeHashes[1 ]));
97
+
98
+ // Update sibling information
99
+ D.Node storage parentNode = tree.nodes[upperNode];
100
+
101
+
102
+ // Put edge
103
+ parentNode.children[bit] = e;
104
+ // Put sibling edge if needed
105
+ if (parentNode.children[1 - bit].isEmpty ()) {
106
+ parentNode.children[1 - bit].header = siblings[siblings.length - i - 1 ];
107
+ }
108
+ // go to upper edge
109
+ e.node = keccak256 (abi.encode (edgeHashes[0 ], edgeHashes[1 ]));
110
+ }
111
+ e.label = k;
112
+ require (tree.root == edgeHash (e));
113
+ tree.root = edgeHash (e);
114
+ tree.rootEdge = e;
115
+ }
116
+
67
117
function insert (Tree storage tree , bytes key , bytes value ) internal {
68
118
D.Label memory k = D.Label (keccak256 (key), 256 );
69
119
bytes32 valueHash = keccak256 (value);
@@ -164,6 +214,54 @@ library PartialMerkleTree {
164
214
}
165
215
}
166
216
217
+ function getNonInclusionProof (Tree storage tree , bytes key ) internal view returns (
218
+ bytes32 potentialSiblingLabel ,
219
+ bytes32 potentialSiblingValue ,
220
+ uint branchMask ,
221
+ bytes32 [] _siblings
222
+ ){
223
+ uint length;
224
+ uint numSiblings;
225
+
226
+ // Start from root edge
227
+ D.Label memory label = D.Label (keccak256 (key), 256 );
228
+ D.Edge memory e = tree.rootEdge;
229
+ bytes32 [256 ] memory siblings;
230
+
231
+ while (true ) {
232
+ // Find at edge
233
+ require (label.length >= e.label.length );
234
+ D.Label memory prefix;
235
+ D.Label memory suffix;
236
+ (prefix, suffix) = Utils.splitCommonPrefix (label, e.label);
237
+
238
+ // suffix.length == 0 means that the key exists. Thus the length of the suffix should be not zero
239
+ require (suffix.length != 0 );
240
+
241
+ if (prefix.length >= e.label.length ) {
242
+ // Partial matched, keep finding
243
+ length += prefix.length ;
244
+ branchMask |= uint (1 ) << (255 - length);
245
+ length += 1 ;
246
+ uint head;
247
+ (head, label) = Utils.chopFirstBit (suffix);
248
+ siblings[numSiblings++ ] = edgeHash (tree.nodes[e.node].children[1 - head]);
249
+ e = tree.nodes[e.node].children[head];
250
+ } else {
251
+ // Found the potential sibling. Set data to return
252
+ potentialSiblingLabel = e.label.data;
253
+ potentialSiblingValue = e.node;
254
+ break ;
255
+ }
256
+ }
257
+ if (numSiblings > 0 )
258
+ {
259
+ _siblings = new bytes32 [](numSiblings);
260
+ for (uint i = 0 ; i < numSiblings; i++ )
261
+ _siblings[i] = siblings[i];
262
+ }
263
+ }
264
+
167
265
function verifyProof (bytes32 rootHash , bytes key , bytes value , uint branchMask , bytes32 [] siblings ) public pure {
168
266
D.Label memory k = D.Label (keccak256 (key), 256 );
169
267
D.Edge memory e;
@@ -183,6 +281,29 @@ library PartialMerkleTree {
183
281
require (rootHash == edgeHash (e));
184
282
}
185
283
284
+ function verifyNonInclusionProof (bytes32 rootHash , bytes key , bytes32 potentialSiblingLabel , bytes32 potentialSiblingValue , uint branchMask , bytes32 [] siblings ) public pure {
285
+ D.Label memory k = D.Label (keccak256 (key), 256 );
286
+ D.Edge memory e;
287
+ for (uint i = 0 ; branchMask != 0 ; i++ ) {
288
+ uint bitSet = Utils.lowestBitSet (branchMask);
289
+ branchMask &= ~ (uint (1 ) << bitSet);
290
+ (k, e.label) = Utils.splitAt (k, 255 - bitSet);
291
+ uint bit;
292
+ (bit, e.label) = Utils.chopFirstBit (e.label);
293
+ bytes32 [2 ] memory edgeHashes;
294
+ if (i == 0 ) {
295
+ e.label.length = bitSet;
296
+ e.label.data = potentialSiblingLabel;
297
+ e.node = potentialSiblingValue;
298
+ }
299
+ edgeHashes[bit] = edgeHash (e);
300
+ edgeHashes[1 - bit] = siblings[siblings.length - i - 1 ];
301
+ e.node = keccak256 (abi.encode (edgeHashes[0 ], edgeHashes[1 ]));
302
+ }
303
+ e.label = k;
304
+ require (rootHash == edgeHash (e));
305
+ }
306
+
186
307
function newEdge (bytes32 node , D.Label label ) internal pure returns (D.Edge memory e ){
187
308
e.node = node;
188
309
e.label = label;
0 commit comments