Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.

Commit 799a02d

Browse files
committed
feat: working (only for some cases) but ugly version
1 parent 43add22 commit 799a02d

File tree

7 files changed

+478
-75
lines changed

7 files changed

+478
-75
lines changed

geth-utils/gethutil/mpt/trie/stacktrie.go

+77-13
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ func (st *StackTrie) getDiffIndex(key []byte) int {
230230

231231
// Helper function to that inserts a (key, value) pair into
232232
// the trie.
233+
// https://github.dev/ethereum/go-ethereum/blob/00905f7dc406cfb67f64cd74113777044fb886d8/core/types/hashing.go#L105-L134
233234
func (st *StackTrie) insert(key, value []byte) {
234235
switch st.nodeType {
235236
case branchNode: /* Branch */
@@ -619,8 +620,10 @@ func (st *StackTrie) getNodeFromBranchRLP(branch []byte, idx int) []byte {
619620
}
620621

621622
type StackProof struct {
622-
proofS [][]byte
623-
proofC [][]byte
623+
proofS [][]byte
624+
proofC [][]byte
625+
nibblesS [][]byte
626+
nibblesC [][]byte
624627
}
625628

626629
func (sp *StackProof) GetProofS() [][]byte {
@@ -630,21 +633,61 @@ func (sp *StackProof) GetProofS() [][]byte {
630633
func (sp *StackProof) GetProofC() [][]byte {
631634
return sp.proofC
632635
}
636+
func (sp *StackProof) GetNibblesS() [][]byte {
637+
return sp.nibblesS
638+
}
639+
func (sp *StackProof) GetNibblesC() [][]byte {
640+
return sp.nibblesC
641+
}
642+
643+
func printProof(ps [][]byte) {
644+
645+
fmt.Print(" ")
646+
for _, p := range ps {
647+
if p[0] == 226 && p[1] == 16 && p[2] == 160 {
648+
fmt.Print("EXT - ")
649+
} else if p[0] == 248 || p[0] == 249 {
650+
offset := p[0] - 248 + 1
651+
if ((p[offset]-81)%32 == 0) && (p[offset+1] == 128 || p[offset+1] == 160) {
652+
fmt.Print("BRANCH - ")
653+
} else {
654+
fmt.Print("LEAF - ")
655+
// fmt.Println(" ", p)
656+
}
657+
} else {
658+
fmt.Print("LEAF -")
659+
fmt.Println(" ", p)
660+
}
661+
}
662+
fmt.Println(" ")
663+
664+
}
633665

634666
func (st *StackTrie) UpdateAndGetProof(db ethdb.KeyValueReader, indexBuf, value []byte) (StackProof, error) {
635-
proofS, err := st.GetProof(db, indexBuf)
667+
fmt.Println("====")
668+
proofS, nibblesS, err := st.GetProof(db, indexBuf)
636669
if err != nil {
637670
return StackProof{}, err
638671
}
672+
len1 := len(proofS)
673+
printProof(proofS)
639674

640675
st.Update(indexBuf, value)
641676

642-
proofC, err := st.GetProof(db, indexBuf)
677+
proofC, nibblesC, err := st.GetProof(db, indexBuf)
643678
if err != nil {
644679
return StackProof{}, err
645680
}
681+
len2 := len(proofC)
682+
fmt.Println(" Proof S C ", len1, len2)
683+
printProof(proofC)
646684

647-
return StackProof{proofS, proofC}, nil
685+
// fmt.Println(len1, len2)
686+
if len1 >= len2 {
687+
fmt.Println(KeybytesToHex(indexBuf))
688+
}
689+
690+
return StackProof{proofS, proofC, nibblesS, nibblesC}, nil
648691
}
649692

650693
// We refer to the link below for this function.
@@ -690,14 +733,16 @@ func (st *StackTrie) UpdateAndGetProofs(db ethdb.KeyValueReader, list types.Deri
690733
}
691734
proofs = append(proofs, proof)
692735
}
736+
// fmt.Println("* ROOT", root)
693737

694738
return proofs, nil
695739
}
696740

697-
func (st *StackTrie) GetProof(db ethdb.KeyValueReader, key []byte) ([][]byte, error) {
741+
func (st *StackTrie) GetProof(db ethdb.KeyValueReader, key []byte) ([][]byte, [][]byte, error) {
698742
k := KeybytesToHex(key)
743+
fmt.Println("k", k)
699744
if st.nodeType == emptyNode {
700-
return [][]byte{}, nil
745+
return [][]byte{}, nil, nil
701746
}
702747

703748
// Note that when root is a leaf, this leaf should be returned even if you ask for a different key (than the key of
@@ -709,9 +754,10 @@ func (st *StackTrie) GetProof(db ethdb.KeyValueReader, key []byte) ([][]byte, er
709754
// in the S proof (another reason is that the S proof with a placeholder leaf would be an empty trie and thus with
710755
// a root of an empty trie - which is not the case in S proof).
711756
if st.nodeType == leafNode {
712-
return [][]byte{st.val}, nil
757+
return [][]byte{st.val}, nil, nil
713758
}
714759

760+
var nibbles [][]byte
715761
var proof [][]byte
716762
var nodes []*StackTrie
717763
c := st
@@ -760,7 +806,6 @@ func (st *StackTrie) GetProof(db ethdb.KeyValueReader, key []byte) ([][]byte, er
760806
lNodes := len(nodes)
761807
for i := lNodes - 1; i >= 0; i-- {
762808
node := nodes[i]
763-
764809
if node.nodeType == leafNode {
765810
rlp, error := db.Get(node.val)
766811
if error != nil { // TODO: avoid error when RLP
@@ -771,11 +816,26 @@ func (st *StackTrie) GetProof(db ethdb.KeyValueReader, key []byte) ([][]byte, er
771816
} else if node.nodeType == branchNode || node.nodeType == extNode {
772817
node.hash(false)
773818

774-
rlp, error := db.Get(node.val)
819+
raw_rlp, error := db.Get(node.val)
775820
if error != nil {
776-
return nil, error
821+
return nil, nil, error
822+
}
823+
proof = append(proof, raw_rlp)
824+
if node.nodeType == extNode {
825+
826+
rlp_flag := uint(raw_rlp[0])
827+
if rlp_flag < 192 || rlp_flag >= 248 {
828+
panic("should not happen!")
829+
}
830+
831+
element, _, _ := rlp.SplitList(raw_rlp)
832+
// fmt.Println("** ", element)
833+
834+
// FIXME only one nibble case
835+
nibble := element[0]
836+
// fmt.Println(" Ext nibble:", nibble)
837+
nibbles = append(nibbles, []byte{nibble})
777838
}
778-
proof = append(proof, rlp)
779839
}
780840

781841
}
@@ -784,5 +844,9 @@ func (st *StackTrie) GetProof(db ethdb.KeyValueReader, key []byte) ([][]byte, er
784844
slices.Reverse(proof)
785845
}
786846

787-
return proof, nil
847+
// given a default value
848+
if len(nibbles) == 0 {
849+
nibbles = append(nibbles, []byte{0})
850+
}
851+
return proof, nibbles, nil
788852
}

geth-utils/gethutil/mpt/witness/branch.go

+78-35
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,41 @@
11
package witness
22

33
import (
4+
"fmt"
45
"log"
56

67
"github.com/ethereum/go-ethereum/rlp"
78
)
89

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+
916
// isBranch takes GetProof element and returns whether the element is a branch.
1017
func isBranch(proofEl []byte) bool {
1118
elems, _, err := rlp.SplitList(proofEl)
1219
check(err)
1320
c, err1 := rlp.CountValues(elems)
1421
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)
1725
}
1826
return c == 17
1927
}
2028

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+
2139
// prepareBranchWitness takes the rows that are to be filled with branch data and it takes
2240
// a branch as returned by GetProof. There are 19 rows for a branch and prepareBranchWitness
2341
// 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
2947
rowInd := 1
3048
colInd := branchNodeRLPLen - 1
3149

50+
// TODO: if input branch is a leaf node, it'll work abnormally
3251
i := 0
3352
insideInd := -1
3453
for {
@@ -154,12 +173,23 @@ func prepareBranchNode(branch1, branch2, extNode1, extNode2, extListRlpBytes []b
154173
func getDriftedPosition(leafKeyRow []byte, numberOfNibbles int) byte {
155174
var nibbles []byte
156175
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+
}
163193
}
164194
}
165195
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 {
192222

193223
// addBranchAndPlaceholder adds to the rows a branch and its placeholder counterpart
194224
// (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,
197226
leafRow0, key, neighbourNode []byte,
198227
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+
201231
len1 := len(proof1)
202232
len2 := len(proof2)
203233

@@ -210,14 +240,29 @@ func addBranchAndPlaceholder(proof1, proof2,
210240
extValues = append(extValues, make([]byte, valueLen))
211241
}
212242

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+
213248
isExtension := (len1 == len2+2) || (len2 == len1+2)
214-
if isExtension {
249+
if isExtension || need_placeholder_ext {
215250
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]
218256
} 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+
}
220264
}
265+
numNibbles, extListRlpBytes, extValues = prepareExtensions(extNibbles, extensionNodeInd, proof, proof)
221266
numberOfNibbles = int(numNibbles)
222267
}
223268

@@ -254,35 +299,33 @@ func addBranchAndPlaceholder(proof1, proof2,
254299

255300
// TODO: fix
256301
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+
}
262311
}
263312
}
264313

314+
// FIXME should move to above and need to avoid above [len-3] operation
315+
isExtension = need_placeholder_ext
316+
265317
// 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
267319

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)
268324
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-
274325
node = prepareBranchNode(proof1[len1-2], proof1[len1-2], extNode, extNode, extListRlpBytes, extValues,
275326
key[keyIndex+numberOfNibbles], driftedInd, false, true, isExtension)
276327

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.
280328
} 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-
286329
node = prepareBranchNode(proof2[len2-2], proof2[len2-2], extNode, extNode, extListRlpBytes, extValues,
287330
key[keyIndex+numberOfNibbles], driftedInd, true, false, isExtension)
288331
}

geth-utils/gethutil/mpt/witness/gen_witness_transactions_test.go

+11-8
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,10 @@ func transactionsStackTrieInsertionTemplate(t *testing.T, n int) {
120120
}
121121
}
122122

123-
// func TestJson(t *testing.T, n int) {
124-
// txs := makeTransactions(n)
125-
// db := rawdb.NewMemoryDatabase()
126-
// stackTrie := trie.NewStackTrie(db)
127-
128-
// proofs, _ := stackTrie.UpdateAndGetProofs(db, types.Transactions(txs))
129-
// }
123+
func TestTransactionInsertion(t *testing.T) {
124+
txs := makeTransactions(4)
125+
prepareStackTrieWitness("TransactionInsertion", types.Transactions(txs))
126+
}
130127

131128
func TestStackTrieInsertion_1Tx(t *testing.T) {
132129
// Only one leaf
@@ -166,6 +163,12 @@ func TestStackTrieInsertion_33Txs(t *testing.T) {
166163
transactionsStackTrieInsertionTemplate(t, 33)
167164
}
168165

166+
func TestStackTrieInsertion_129Txs(t *testing.T) {
167+
// The first tx (index 0) is inserted into position 8 of the top branch
168+
// Th 129th tx is the neighbor of the first tx
169+
transactionsStackTrieInsertionTemplate(t, 129)
170+
}
171+
169172
func TestStackTrieInsertion_ManyTxs(t *testing.T) {
170173
// Just randomly picking a large number.
171174
// The cap of block gas limit is 30M, the minimum gas cost of a tx is 21k
@@ -190,7 +193,7 @@ func batchedTransactionsStackTrieProofTemplate(n int) {
190193
var indexBuf []byte
191194
indexBuf = rlp.AppendUint64(indexBuf[:0], uint64(1))
192195

193-
proofS, err := stackTrie.GetProof(db, indexBuf)
196+
proofS, _, err := stackTrie.GetProof(db, indexBuf)
194197
if err != nil {
195198
fmt.Println(err)
196199
return

0 commit comments

Comments
 (0)