@@ -28,7 +28,6 @@ import (
2828 "github.com/ethereum/go-ethereum/core"
2929 "github.com/ethereum/go-ethereum/core/state"
3030 "github.com/ethereum/go-ethereum/crypto"
31- "github.com/ethereum/go-ethereum/ethdb"
3231 "github.com/ethereum/go-ethereum/log"
3332 "github.com/ethereum/go-ethereum/rlp"
3433 "github.com/ethereum/go-ethereum/trie"
@@ -42,16 +41,14 @@ type Builder interface {
4241}
4342
4443type builder struct {
45- chainDB ethdb.Database
4644 config Config
4745 blockChain * core.BlockChain
4846 stateCache state.Database
4947}
5048
5149// NewBuilder is used to create a statediff builder
52- func NewBuilder (db ethdb. Database , blockChain * core.BlockChain , config Config ) Builder {
50+ func NewBuilder (blockChain * core.BlockChain , config Config ) Builder {
5351 return & builder {
54- chainDB : db ,
5552 config : config ,
5653 blockChain : blockChain ,
5754 }
@@ -71,17 +68,13 @@ func (sdb *builder) BuildStateDiff(oldStateRoot, newStateRoot common.Hash, block
7168 }
7269
7370 // Find created accounts
74- oldIt := oldTrie .NodeIterator ([]byte {})
75- newIt := newTrie .NodeIterator ([]byte {})
76- creations , err := sdb .collectDiffNodes (oldIt , newIt )
71+ creations , err := sdb .collectDiffNodes (oldTrie .NodeIterator ([]byte {}), newTrie .NodeIterator ([]byte {}))
7772 if err != nil {
7873 return StateDiff {}, fmt .Errorf ("error collecting creation diff nodes: %v" , err )
7974 }
8075
8176 // Find deleted accounts
82- oldIt = oldTrie .NodeIterator ([]byte {})
83- newIt = newTrie .NodeIterator ([]byte {})
84- deletions , err := sdb .collectDiffNodes (newIt , oldIt )
77+ deletions , err := sdb .collectDiffNodes (newTrie .NodeIterator ([]byte {}), oldTrie .NodeIterator ([]byte {}))
8578 if err != nil {
8679 return StateDiff {}, fmt .Errorf ("error collecting deletion diff nodes: %v" , err )
8780 }
@@ -131,58 +124,62 @@ func (sdb *builder) isWatchedAddress(hashKey []byte) bool {
131124}
132125
133126func (sdb * builder ) collectDiffNodes (a , b trie.NodeIterator ) (AccountsMap , error ) {
134- var diffAccounts = make (AccountsMap )
127+ diffAccounts : = make (AccountsMap )
135128 it , _ := trie .NewDifferenceIterator (a , b )
136- for {
137- log .Debug ("Current Path and Hash" , "path" , pathToStr (it ), "old hash" , it .Hash ())
138- if it .Leaf () && sdb .isWatchedAddress (it .LeafKey ()) {
139- leafKey := make ([]byte , len (it .LeafKey ()))
140- copy (leafKey , it .LeafKey ())
141- leafKeyHash := common .BytesToHash (leafKey )
142- leafValue := make ([]byte , len (it .LeafBlob ()))
143- copy (leafValue , it .LeafBlob ())
144- // lookup account state
129+ for it .Next (true ) {
130+ // skip value nodes
131+ if it .Leaf () {
132+ continue
133+ }
134+ if bytes .Equal (nullNode , it .Hash ().Bytes ()) {
135+ continue
136+ }
137+ nodePath := make ([]byte , len (it .Path ()))
138+ copy (nodePath , it .Path ())
139+ node , err := sdb .stateCache .TrieDB ().Node (it .Hash ())
140+ if err != nil {
141+ return nil , err
142+ }
143+ var nodeElements []interface {}
144+ if err := rlp .DecodeBytes (node , & nodeElements ); err != nil {
145+ return nil , err
146+ }
147+ ty , err := CheckKeyType (nodeElements )
148+ if err != nil {
149+ return nil , err
150+ }
151+ switch ty {
152+ case Leaf :
145153 var account state.Account
146- if err := rlp .DecodeBytes (leafValue , & account ); err != nil {
147- return nil , fmt .Errorf ("error looking up account via address %s\r \n error: %v" , leafKeyHash .Hex (), err )
148- }
149- aw := accountWrapper {
150- Leaf : true ,
151- Account : & account ,
152- RawKey : leafKey ,
153- RawValue : leafValue ,
154+ if err := rlp .DecodeBytes (nodeElements [1 ].([]byte ), & account ); err != nil {
155+ return nil , fmt .Errorf ("error decoding account for leaf node at path %x\r \n error: %v\r \n " , nodePath , err )
154156 }
155- if sdb .config .PathsAndProofs {
156- leafProof := make ([][]byte , len (it .LeafProof ()))
157- copy (leafProof , it .LeafProof ())
158- leafPath := make ([]byte , len (it .Path ()))
159- copy (leafPath , it .Path ())
160- aw .Proof = leafProof
161- aw .Path = leafPath
157+ partialPath := trie .CompactToHex (nodeElements [0 ].([]byte ))
158+ valueNodePath := append (nodePath , partialPath ... )
159+ encodedPath := trie .HexToCompact (valueNodePath )
160+ leafKey := encodedPath [1 :]
161+ if sdb .isWatchedAddress (leafKey ) {
162+ aw := accountWrapper {
163+ NodeType : ty ,
164+ Path : nodePath ,
165+ NodeValue : node ,
166+ LeafKey : leafKey ,
167+ Account : & account ,
168+ }
169+ diffAccounts [common .BytesToHash (encodedPath )] = aw
162170 }
163- // record account to diffs (creation if we are looking at new - old; deletion if old - new)
164- log .Debug ("Account lookup successful" , "address" , leafKeyHash , "account" , account )
165- diffAccounts [leafKeyHash ] = aw
166- } else if sdb .config .IntermediateNodes && ! bytes .Equal (nullNode , it .Hash ().Bytes ()) {
167- nodeKey := it .Hash ()
168- node , err := sdb .stateCache .TrieDB ().Node (nodeKey )
169- if err != nil {
170- return nil , fmt .Errorf ("error looking up intermediate state trie node %s\r \n error: %v" , nodeKey .Hex (), err )
171+ case Extension , Branch :
172+ if sdb .config .IntermediateNodes {
173+ diffAccounts [common .BytesToHash (nodePath )] = accountWrapper {
174+ NodeType : ty ,
175+ Path : nodePath ,
176+ NodeValue : node ,
177+ }
171178 }
172- aw := accountWrapper {
173- Leaf : false ,
174- RawKey : nodeKey .Bytes (),
175- RawValue : node ,
176- }
177- log .Debug ("intermediate state trie node lookup successful" , "key" , nodeKey .Hex (), "value" , node )
178- diffAccounts [nodeKey ] = aw
179- }
180- cont := it .Next (true )
181- if ! cont {
182- break
179+ default :
180+ return nil , fmt .Errorf ("unexpected node type %s" , ty )
183181 }
184182 }
185-
186183 return diffAccounts , nil
187184}
188185
@@ -195,16 +192,15 @@ func (sdb *builder) buildDiffEventual(accounts AccountsMap) ([]AccountDiff, erro
195192 if val .Account != nil {
196193 storageDiffs , err = sdb .buildStorageDiffsEventual (val .Account .Root )
197194 if err != nil {
198- return nil , fmt .Errorf ("failed building eventual storage diffs for %s \r \n error: %v" , common . BytesToHash ( val .RawKey ) , err )
195+ return nil , fmt .Errorf ("failed building eventual storage diffs for node %x \r \n error: %v" , val .Path , err )
199196 }
200197 }
201198 accountDiffs = append (accountDiffs , AccountDiff {
202- Leaf : val .Leaf ,
203- Key : val .RawKey ,
204- Value : val .RawValue ,
205- Proof : val .Proof ,
206- Path : val .Path ,
207- Storage : storageDiffs ,
199+ NodeType : val .NodeType ,
200+ Path : val .Path ,
201+ LeafKey : val .LeafKey ,
202+ NodeValue : val .NodeValue ,
203+ Storage : storageDiffs ,
208204 })
209205 }
210206
@@ -228,12 +224,11 @@ func (sdb *builder) buildDiffIncremental(creations AccountsMap, deletions Accoun
228224 }
229225 }
230226 updatedAccounts = append (updatedAccounts , AccountDiff {
231- Leaf : createdAcc .Leaf ,
232- Key : createdAcc .RawKey ,
233- Value : createdAcc .RawValue ,
234- Proof : createdAcc .Proof ,
235- Path : createdAcc .Path ,
236- Storage : storageDiffs ,
227+ NodeType : createdAcc .NodeType ,
228+ Path : createdAcc .Path ,
229+ NodeValue : createdAcc .NodeValue ,
230+ LeafKey : createdAcc .LeafKey ,
231+ Storage : storageDiffs ,
237232 })
238233 delete (creations , common .HexToHash (val ))
239234 delete (deletions , common .HexToHash (val ))
@@ -275,46 +270,52 @@ func (sdb *builder) buildStorageDiffsIncremental(oldSR common.Hash, newSR common
275270
276271func (sdb * builder ) buildStorageDiffsFromTrie (it trie.NodeIterator ) ([]StorageDiff , error ) {
277272 storageDiffs := make ([]StorageDiff , 0 )
278- for {
279- log . Debug ( "Iterating over state at path " , "path" , pathToStr ( it ))
273+ for it . Next ( true ) {
274+ // skip value nodes
280275 if it .Leaf () {
281- log .Debug ("Found leaf in storage" , "path" , pathToStr (it ))
282- leafKey := make ([]byte , len (it .LeafKey ()))
283- copy (leafKey , it .LeafKey ())
284- leafValue := make ([]byte , len (it .LeafBlob ()))
285- copy (leafValue , it .LeafBlob ())
276+ continue
277+ }
278+ if bytes .Equal (nullNode , it .Hash ().Bytes ()) {
279+ continue
280+ }
281+ nodePath := make ([]byte , len (it .Path ()))
282+ copy (nodePath , it .Path ())
283+ node , err := sdb .stateCache .TrieDB ().Node (it .Hash ())
284+ if err != nil {
285+ return nil , err
286+ }
287+ var nodeElements []interface {}
288+ if err := rlp .DecodeBytes (node , & nodeElements ); err != nil {
289+ return nil , err
290+ }
291+ ty , err := CheckKeyType (nodeElements )
292+ if err != nil {
293+ return nil , err
294+ }
295+ switch ty {
296+ case Leaf :
297+ partialPath := trie .CompactToHex (nodeElements [0 ].([]byte ))
298+ valueNodePath := append (nodePath , partialPath ... )
299+ encodedPath := trie .HexToCompact (valueNodePath )
300+ leafKey := encodedPath [1 :]
286301 sd := StorageDiff {
287- Leaf : true ,
288- Key : leafKey ,
289- Value : leafValue ,
290- }
291- if sdb .config .PathsAndProofs {
292- leafProof := make ([][]byte , len (it .LeafProof ()))
293- copy (leafProof , it .LeafProof ())
294- leafPath := make ([]byte , len (it .Path ()))
295- copy (leafPath , it .Path ())
296- sd .Proof = leafProof
297- sd .Path = leafPath
302+ NodeType : ty ,
303+ Path : nodePath ,
304+ NodeValue : node ,
305+ LeafKey : leafKey ,
298306 }
299307 storageDiffs = append (storageDiffs , sd )
300- } else if sdb .config .IntermediateNodes && ! bytes .Equal (nullNode , it .Hash ().Bytes ()) {
301- nodeKey := it .Hash ()
302- node , err := sdb .stateCache .TrieDB ().Node (nodeKey )
303- if err != nil {
304- return nil , fmt .Errorf ("error looking up intermediate storage trie node %s\r \n error: %v" , nodeKey .Hex (), err )
308+ case Extension , Branch :
309+ if sdb .config .IntermediateNodes {
310+ storageDiffs = append (storageDiffs , StorageDiff {
311+ NodeType : ty ,
312+ Path : nodePath ,
313+ NodeValue : node ,
314+ })
305315 }
306- storageDiffs = append (storageDiffs , StorageDiff {
307- Leaf : false ,
308- Key : nodeKey .Bytes (),
309- Value : node ,
310- })
311- log .Debug ("intermediate storage trie node lookup successful" , "key" , nodeKey .Hex (), "value" , node )
312- }
313- cont := it .Next (true )
314- if ! cont {
315- break
316+ default :
317+ return nil , fmt .Errorf ("unexpected node type %s" , ty )
316318 }
317319 }
318-
319320 return storageDiffs , nil
320321}
0 commit comments