@@ -202,7 +202,8 @@ func (sdb *builder) buildStateDiffWithIntermediateStateNodes(args types2.StateRo
202202 // a map of their leafkey to all the accounts that were touched and exist at A
203203 diffAccountsAtA , err := sdb .deletedOrUpdatedState (
204204 oldTrie .NodeIterator ([]byte {}), newTrie .NodeIterator ([]byte {}),
205- diffPathsAtB , params .watchedAddressesLeafKeys , output )
205+ diffPathsAtB , params .watchedAddressesLeafKeys ,
206+ params .IntermediateStorageNodes , output )
206207 if err != nil {
207208 return fmt .Errorf ("error collecting deletedOrUpdatedNodes: %v" , err )
208209 }
@@ -256,7 +257,8 @@ func (sdb *builder) buildStateDiffWithoutIntermediateStateNodes(args types2.Stat
256257 // a map of their leafkey to all the accounts that were touched and exist at A
257258 diffAccountsAtA , err := sdb .deletedOrUpdatedState (
258259 oldTrie .NodeIterator ([]byte {}), newTrie .NodeIterator ([]byte {}),
259- diffPathsAtB , params .watchedAddressesLeafKeys , output )
260+ diffPathsAtB , params .watchedAddressesLeafKeys ,
261+ params .IntermediateStorageNodes , output )
260262 if err != nil {
261263 return fmt .Errorf ("error collecting deletedOrUpdatedNodes: %v" , err )
262264 }
@@ -386,7 +388,7 @@ func (sdb *builder) createdAndUpdatedStateWithIntermediateNodes(a, b trie.NodeIt
386388
387389// deletedOrUpdatedState returns a slice of all the pathes that are emptied at B
388390// and a mapping of their leafkeys to all the accounts that exist in a different state at A than B
389- func (sdb * builder ) deletedOrUpdatedState (a , b trie.NodeIterator , diffPathsAtB map [string ]bool , watchedAddressesLeafKeys map [common.Hash ]struct {}, output types2.StateNodeSink ) (types2.AccountMap , error ) {
391+ func (sdb * builder ) deletedOrUpdatedState (a , b trie.NodeIterator , diffPathsAtB map [string ]bool , watchedAddressesLeafKeys map [common.Hash ]struct {}, intermediateStorageNodes bool , output types2.StateNodeSink ) (types2.AccountMap , error ) {
390392 diffAccountAtA := make (types2.AccountMap )
391393 it , _ := trie .NewDifferenceIterator (b , a )
392394 for it .Next (true ) {
@@ -420,13 +422,23 @@ func (sdb *builder) deletedOrUpdatedState(a, b trie.NodeIterator, diffPathsAtB m
420422 // if this node's path did not show up in diffPathsAtB
421423 // that means the node at this path was deleted (or moved) in B
422424 // emit an empty "removed" diff to signify as such
425+ // emit emtpy "removed" diff for all storage nodes
423426 if _ , ok := diffPathsAtB [common .Bytes2Hex (node .Path )]; ! ok {
424- if err := output (types2.StateNode {
425- Path : node .Path ,
426- NodeValue : []byte {},
427+ diff := types2.StateNode {
427428 NodeType : types2 .Removed ,
429+ Path : node .Path ,
428430 LeafKey : leafKey ,
429- }); err != nil {
431+ NodeValue : []byte {},
432+ }
433+
434+ var storageDiffs []types2.StorageNode
435+ err := sdb .buildRemovedAccountStorageNodes (account .Root , intermediateStorageNodes , storageNodeAppender (& storageDiffs ))
436+ if err != nil {
437+ return nil , fmt .Errorf ("failed building storage diffs for removed node %x\r \n error: %v" , node .Path , err )
438+ }
439+ diff .StorageNodes = storageDiffs
440+
441+ if err := output (diff ); err != nil {
430442 return nil , err
431443 }
432444 }
@@ -548,7 +560,6 @@ func (sdb *builder) buildStorageNodesEventual(sr common.Hash, intermediateNodes
548560}
549561
550562// buildStorageNodesFromTrie returns all the storage diff node objects in the provided node interator
551- // if any storage keys are provided it will only return those leaf nodes
552563// including intermediate nodes can be turned on or off
553564func (sdb * builder ) buildStorageNodesFromTrie (it trie.NodeIterator , intermediateNodes bool , output types2.StorageNodeSink ) error {
554565 for it .Next (true ) {
@@ -591,6 +602,68 @@ func (sdb *builder) buildStorageNodesFromTrie(it trie.NodeIterator, intermediate
591602 return it .Error ()
592603}
593604
605+ // buildRemovedAccountStorageNodes builds the "removed" diffs for all the storage nodes for a destroyed account
606+ func (sdb * builder ) buildRemovedAccountStorageNodes (sr common.Hash , intermediateNodes bool , output types2.StorageNodeSink ) error {
607+ if bytes .Equal (sr .Bytes (), emptyContractRoot .Bytes ()) {
608+ return nil
609+ }
610+ log .Debug ("Storage Root For Removed Diffs" , "root" , sr .Hex ())
611+ sTrie , err := sdb .stateCache .OpenTrie (sr )
612+ if err != nil {
613+ log .Info ("error in build removed account storage diffs" , "error" , err )
614+ return err
615+ }
616+ it := sTrie .NodeIterator (make ([]byte , 0 ))
617+ err = sdb .buildRemovedStorageNodesFromTrie (it , intermediateNodes , output )
618+ if err != nil {
619+ return err
620+ }
621+ return nil
622+ }
623+
624+ // buildRemovedStorageNodesFromTrie returns diffs for all the storage nodes in the provided node interator
625+ // including intermediate nodes can be turned on or off
626+ func (sdb * builder ) buildRemovedStorageNodesFromTrie (it trie.NodeIterator , intermediateNodes bool , output types2.StorageNodeSink ) error {
627+ for it .Next (true ) {
628+ // skip value nodes
629+ if it .Leaf () || bytes .Equal (nullHashBytes , it .Hash ().Bytes ()) {
630+ continue
631+ }
632+ node , nodeElements , err := trie_helpers .ResolveNode (it , sdb .stateCache .TrieDB ())
633+ if err != nil {
634+ return err
635+ }
636+ switch node .NodeType {
637+ case types2 .Leaf :
638+ partialPath := trie .CompactToHex (nodeElements [0 ].([]byte ))
639+ valueNodePath := append (node .Path , partialPath ... )
640+ encodedPath := trie .HexToCompact (valueNodePath )
641+ leafKey := encodedPath [1 :]
642+ if err := output (types2.StorageNode {
643+ NodeType : types2 .Removed ,
644+ Path : node .Path ,
645+ NodeValue : []byte {},
646+ LeafKey : leafKey ,
647+ }); err != nil {
648+ return err
649+ }
650+ case types2 .Extension , types2 .Branch :
651+ if intermediateNodes {
652+ if err := output (types2.StorageNode {
653+ NodeType : types2 .Removed ,
654+ Path : node .Path ,
655+ NodeValue : []byte {},
656+ }); err != nil {
657+ return err
658+ }
659+ }
660+ default :
661+ return fmt .Errorf ("unexpected node type %s" , node .NodeType )
662+ }
663+ }
664+ return it .Error ()
665+ }
666+
594667// buildStorageNodesIncremental builds the storage diff node objects for all nodes that exist in a different state at B than A
595668func (sdb * builder ) buildStorageNodesIncremental (oldSR common.Hash , newSR common.Hash , intermediateNodes bool , output types2.StorageNodeSink ) error {
596669 if bytes .Equal (newSR .Bytes (), oldSR .Bytes ()) {
0 commit comments