@@ -109,6 +109,54 @@ library PatriciaTree {
109109 }
110110 }
111111
112+ function getNonInclusionProof (Tree storage tree , bytes key ) internal view returns (
113+ bytes32 potentialSiblingLabel ,
114+ bytes32 potentialSiblingValue ,
115+ uint branchMask ,
116+ bytes32 [] _siblings
117+ ){
118+ uint length;
119+ uint numSiblings;
120+
121+ // Start from root edge
122+ D.Label memory label = D.Label (keccak256 (key), 256 );
123+ D.Edge memory e = tree.rootEdge;
124+ bytes32 [256 ] memory siblings;
125+
126+ while (true ) {
127+ // Find at edge
128+ require (label.length >= e.label.length );
129+ D.Label memory prefix;
130+ D.Label memory suffix;
131+ (prefix, suffix) = Utils.splitCommonPrefix (label, e.label);
132+
133+ // suffix.length == 0 means that the key exists. Thus the length of the suffix should be not zero
134+ require (suffix.length != 0 );
135+
136+ if (prefix.length >= e.label.length ) {
137+ // Partial matched, keep finding
138+ length += prefix.length ;
139+ branchMask |= uint (1 ) << (255 - length);
140+ length += 1 ;
141+ uint head;
142+ (head, label) = Utils.chopFirstBit (suffix);
143+ siblings[numSiblings++ ] = edgeHash (tree.nodes[e.node].children[1 - head]);
144+ e = tree.nodes[e.node].children[head];
145+ } else {
146+ // Found the potential sibling. Set data to return
147+ potentialSiblingLabel = e.label.data;
148+ potentialSiblingValue = e.node;
149+ break ;
150+ }
151+ }
152+ if (numSiblings > 0 )
153+ {
154+ _siblings = new bytes32 [](numSiblings);
155+ for (uint i = 0 ; i < numSiblings; i++ )
156+ _siblings[i] = siblings[i];
157+ }
158+ }
159+
112160 function verifyProof (bytes32 rootHash , bytes key , bytes value , uint branchMask , bytes32 [] siblings ) public pure {
113161 D.Label memory k = D.Label (keccak256 (key), 256 );
114162 D.Edge memory e;
@@ -128,6 +176,29 @@ library PatriciaTree {
128176 require (rootHash == edgeHash (e));
129177 }
130178
179+ function verifyNonInclusionProof (bytes32 rootHash , bytes key , bytes32 potentialSiblingLabel , bytes32 potentialSiblingValue , uint branchMask , bytes32 [] siblings ) public pure {
180+ D.Label memory k = D.Label (keccak256 (key), 256 );
181+ D.Edge memory e;
182+ for (uint i = 0 ; branchMask != 0 ; i++ ) {
183+ uint bitSet = Utils.lowestBitSet (branchMask);
184+ branchMask &= ~ (uint (1 ) << bitSet);
185+ (k, e.label) = Utils.splitAt (k, 255 - bitSet);
186+ uint bit;
187+ (bit, e.label) = Utils.chopFirstBit (e.label);
188+ bytes32 [2 ] memory edgeHashes;
189+ if (i == 0 ) {
190+ e.label.length = bitSet;
191+ e.label.data = potentialSiblingLabel;
192+ e.node = potentialSiblingValue;
193+ }
194+ edgeHashes[bit] = edgeHash (e);
195+ edgeHashes[1 - bit] = siblings[siblings.length - i - 1 ];
196+ e.node = keccak256 (abi.encode (edgeHashes[0 ], edgeHashes[1 ]));
197+ }
198+ e.label = k;
199+ require (rootHash == edgeHash (e));
200+ }
201+
131202 // TODO also return the proof
132203 function insert (Tree storage tree , bytes key , bytes value ) internal {
133204 D.Label memory k = D.Label (keccak256 (key), 256 );
0 commit comments