1
1
package witness
2
2
3
3
import (
4
+ "fmt"
4
5
"log"
5
6
6
7
"github.com/ethereum/go-ethereum/rlp"
7
8
)
8
9
10
+ func PrepareBranchNode (branch1 , branch2 , extNode1 , extNode2 , extListRlpBytes []byte , extValues [][]byte , key , driftedInd byte ,
11
+ isBranchSPlaceholder , isBranchCPlaceholder , isExtension bool ) Node {
12
+ return prepareBranchNode (branch1 , branch2 , extNode1 , extNode2 , extListRlpBytes , extValues , key , driftedInd ,
13
+ isBranchSPlaceholder , isBranchCPlaceholder , isExtension )
14
+ }
15
+
9
16
// isBranch takes GetProof element and returns whether the element is a branch.
10
17
func isBranch (proofEl []byte ) bool {
11
18
elems , _ , err := rlp .SplitList (proofEl )
12
19
check (err )
13
20
c , err1 := rlp .CountValues (elems )
14
21
check (err1 )
15
- if c != 2 && c != 17 {
16
- log .Fatal ("Proof element is neither leaf or branch" )
22
+ // 9: for tx (Nonce, Gas, GasPrice, Value, To, Data, r, s, v)
23
+ if c != 2 && c != 17 && c != 9 {
24
+ log .Fatal ("Proof element is neither leaf or branch " , c , proofEl , elems )
17
25
}
18
26
return c == 17
19
27
}
20
28
29
+ func isTxLeaf (proofEl []byte ) bool {
30
+ elems , _ , err := rlp .SplitList (proofEl )
31
+ check (err )
32
+ c , err1 := rlp .CountValues (elems )
33
+ check (err1 )
34
+ fmt .Println ("ISLEAF:" , c )
35
+ // 9: for tx (Nonce, Gas, GasPrice, Value, To, Data, r, s, v)
36
+ return c == 9
37
+ }
38
+
21
39
// prepareBranchWitness takes the rows that are to be filled with branch data and it takes
22
40
// a branch as returned by GetProof. There are 19 rows for a branch and prepareBranchWitness
23
41
// fills the rows from index 1 to index 16 (index 0 is init, index 17 and 18 are for extension
@@ -29,6 +47,7 @@ func prepareBranchWitness(rows [][]byte, branch []byte, branchStart int, branchR
29
47
rowInd := 1
30
48
colInd := branchNodeRLPLen - 1
31
49
50
+ // TODO: if input branch is a leaf node, it'll work abnormally
32
51
i := 0
33
52
insideInd := - 1
34
53
for {
@@ -154,12 +173,23 @@ func prepareBranchNode(branch1, branch2, extNode1, extNode2, extListRlpBytes []b
154
173
func getDriftedPosition (leafKeyRow []byte , numberOfNibbles int ) byte {
155
174
var nibbles []byte
156
175
if leafKeyRow [0 ] != 248 {
157
- keyLen := int (leafKeyRow [1 ] - 128 )
158
- if (leafKeyRow [2 ] != 32 ) && (leafKeyRow [2 ] != 0 ) { // second term is for extension node
159
- if leafKeyRow [2 ] < 32 { // extension node
160
- nibbles = append (nibbles , leafKeyRow [2 ]- 16 )
161
- } else { // leaf
162
- nibbles = append (nibbles , leafKeyRow [2 ]- 48 )
176
+ keyLen := 0
177
+ if leafKeyRow [0 ] == 226 {
178
+ // In this case, we only have 1 nibble
179
+ // Prove: 226 - 192 = 34, the payload is 34 bytes and the 1st byte is RLP byte (aka 226)
180
+ // So, 33 bytes left, hash occupies 32 bytes in the end of the payload.
181
+ // 33 - 32 = 1, which is the nibble.
182
+ keyLen = 1
183
+ nibbles = append (nibbles , leafKeyRow [1 ]- 16 )
184
+ numberOfNibbles = 0
185
+ } else {
186
+ keyLen = int (leafKeyRow [1 ] - 128 )
187
+ if (leafKeyRow [2 ] != 32 ) && (leafKeyRow [2 ] != 0 ) { // second term is for extension node
188
+ if leafKeyRow [2 ] < 32 { // extension node
189
+ nibbles = append (nibbles , leafKeyRow [2 ]- 16 )
190
+ } else { // leaf
191
+ nibbles = append (nibbles , leafKeyRow [2 ]- 48 )
192
+ }
163
193
}
164
194
}
165
195
for i := 0 ; i < keyLen - 1 ; i ++ { // -1 because the first byte doesn't have any nibbles
@@ -192,12 +222,12 @@ func getDriftedPosition(leafKeyRow []byte, numberOfNibbles int) byte {
192
222
193
223
// addBranchAndPlaceholder adds to the rows a branch and its placeholder counterpart
194
224
// (used when one of the proofs have one branch more than the other).
195
- func addBranchAndPlaceholder (proof1 , proof2 ,
196
- extNibblesS , extNibblesC [][]byte ,
225
+ func addBranchAndPlaceholder (proof1 , proof2 , extNibblesS , extNibblesC [][]byte ,
197
226
leafRow0 , key , neighbourNode []byte ,
198
227
keyIndex , extensionNodeInd int ,
199
- additionalBranch , isAccountProof , nonExistingAccountProof ,
200
- isShorterProofLastLeaf bool , toBeHashed * [][]byte ) (bool , bool , int , Node ) {
228
+ additionalBranch , isAccountProof , nonExistingAccountProof , isShorterProofLastLeaf bool ,
229
+ toBeHashed * [][]byte ) (bool , bool , int , Node ) {
230
+
201
231
len1 := len (proof1 )
202
232
len2 := len (proof2 )
203
233
@@ -210,14 +240,29 @@ func addBranchAndPlaceholder(proof1, proof2,
210
240
extValues = append (extValues , make ([]byte , valueLen ))
211
241
}
212
242
243
+ // FIXME have a 'isExtension' function
244
+ // For stack trie
245
+ // if 1 st node of proof2 is a branch node and 1st node of Proof1 is an ext node
246
+ need_placeholder_ext := isBranch (proof2 [0 ]) && (! isTxLeaf (proof1 [0 ]) && ! isBranch (proof1 [0 ]))
247
+
213
248
isExtension := (len1 == len2 + 2 ) || (len2 == len1 + 2 )
214
- if isExtension {
249
+ if isExtension || need_placeholder_ext {
215
250
var numNibbles byte
216
- if len1 > len2 {
217
- numNibbles , extListRlpBytes , extValues = prepareExtensions (extNibblesS , extensionNodeInd , proof1 [len1 - 3 ], proof1 [len1 - 3 ])
251
+ var proof []byte
252
+ var extNibbles [][]byte
253
+ if need_placeholder_ext {
254
+ extNibbles = extNibblesS
255
+ proof = proof1 [0 ]
218
256
} else {
219
- numNibbles , extListRlpBytes , extValues = prepareExtensions (extNibblesC , extensionNodeInd , proof2 [len2 - 3 ], proof2 [len2 - 3 ])
257
+ if len1 > len2 {
258
+ extNibbles = extNibblesS
259
+ proof = proof1 [len1 - 3 ]
260
+ } else {
261
+ extNibbles = extNibblesC
262
+ proof = proof2 [len2 - 3 ]
263
+ }
220
264
}
265
+ numNibbles , extListRlpBytes , extValues = prepareExtensions (extNibbles , extensionNodeInd , proof , proof )
221
266
numberOfNibbles = int (numNibbles )
222
267
}
223
268
@@ -254,35 +299,33 @@ func addBranchAndPlaceholder(proof1, proof2,
254
299
255
300
// TODO: fix
256
301
var extNode []byte
257
- if isExtension {
258
- if len1 > len2 {
259
- extNode = proof1 [len1 - 3 ]
260
- } else {
261
- extNode = proof2 [len2 - 3 ]
302
+ if need_placeholder_ext {
303
+ extNode = proof1 [0 ]
304
+ } else {
305
+ if isExtension {
306
+ if len1 > len2 {
307
+ extNode = proof1 [len1 - 3 ]
308
+ } else {
309
+ extNode = proof2 [len2 - 3 ]
310
+ }
262
311
}
263
312
}
264
313
314
+ // FIXME should move to above and need to avoid above [len-3] operation
315
+ isExtension = need_placeholder_ext
316
+
265
317
// Note that isModifiedExtNode happens also when we have a branch instead of shortExtNode
266
- isModifiedExtNode := ! isBranch (longExtNode ) && ! isShorterProofLastLeaf
318
+ isModifiedExtNode := ( ! isBranch (longExtNode ) && ! isShorterProofLastLeaf ) || need_placeholder_ext
267
319
320
+ // We now get the first nibble of the leaf that was turned into branch.
321
+ // This first nibble presents the position of the leaf once it moved
322
+ // into the new branch.
323
+ driftedInd := getDriftedPosition (leafRow0 , numberOfNibbles )
268
324
if len1 > len2 {
269
- // We now get the first nibble of the leaf that was turned into branch.
270
- // This first nibble presents the position of the leaf once it moved
271
- // into the new branch.
272
- driftedInd := getDriftedPosition (leafRow0 , numberOfNibbles )
273
-
274
325
node = prepareBranchNode (proof1 [len1 - 2 ], proof1 [len1 - 2 ], extNode , extNode , extListRlpBytes , extValues ,
275
326
key [keyIndex + numberOfNibbles ], driftedInd , false , true , isExtension )
276
327
277
- // We now get the first nibble of the leaf that was turned into branch.
278
- // This first nibble presents the position of the leaf once it moved
279
- // into the new branch.
280
328
} else {
281
- // We now get the first nibble of the leaf that was turned into branch.
282
- // This first nibble presents the position of the leaf once it moved
283
- // into the new branch.
284
- driftedInd := getDriftedPosition (leafRow0 , numberOfNibbles )
285
-
286
329
node = prepareBranchNode (proof2 [len2 - 2 ], proof2 [len2 - 2 ], extNode , extNode , extListRlpBytes , extValues ,
287
330
key [keyIndex + numberOfNibbles ], driftedInd , true , false , isExtension )
288
331
}
0 commit comments