@@ -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+ diffAccountsAtB , 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+ diffAccountsAtB , 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 , diffAccountsAtB types2. AccountMap , 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 ) {
@@ -419,14 +421,36 @@ func (sdb *builder) deletedOrUpdatedState(a, b trie.NodeIterator, diffPathsAtB m
419421 }
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
422- // emit an empty "removed" diff to signify as such
423424 if _ , ok := diffPathsAtB [common .Bytes2Hex (node .Path )]; ! ok {
424- if err := output (types2.StateNode {
425- Path : node .Path ,
426- NodeValue : []byte {},
427- NodeType : types2 .Removed ,
428- LeafKey : leafKey ,
429- }); err != nil {
425+ var diff types2.StateNode
426+ // if this node's leaf key also did not show up in diffAccountsAtB
427+ // that means the node was deleted
428+ // in that case, emit an empty "removed" diff state node
429+ // include empty "removed" diff storage nodes for all the storage slots
430+ if _ , ok := diffAccountsAtB [common .Bytes2Hex (leafKey )]; ! ok {
431+ diff = types2.StateNode {
432+ NodeType : types2 .Removed ,
433+ Path : node .Path ,
434+ LeafKey : leafKey ,
435+ NodeValue : []byte {},
436+ }
437+
438+ var storageDiffs []types2.StorageNode
439+ err := sdb .buildRemovedAccountStorageNodes (account .Root , intermediateStorageNodes , storageNodeAppender (& storageDiffs ))
440+ if err != nil {
441+ return nil , fmt .Errorf ("failed building storage diffs for removed node %x\r \n error: %v" , node .Path , err )
442+ }
443+ diff .StorageNodes = storageDiffs
444+ } else {
445+ // emit an empty "removed" diff with empty leaf key if the account was moved
446+ diff = types2.StateNode {
447+ NodeType : types2 .Removed ,
448+ Path : node .Path ,
449+ NodeValue : []byte {},
450+ }
451+ }
452+
453+ if err := output (diff ); err != nil {
430454 return nil , err
431455 }
432456 }
@@ -548,7 +572,6 @@ func (sdb *builder) buildStorageNodesEventual(sr common.Hash, intermediateNodes
548572}
549573
550574// 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
552575// including intermediate nodes can be turned on or off
553576func (sdb * builder ) buildStorageNodesFromTrie (it trie.NodeIterator , intermediateNodes bool , output types2.StorageNodeSink ) error {
554577 for it .Next (true ) {
@@ -591,6 +614,68 @@ func (sdb *builder) buildStorageNodesFromTrie(it trie.NodeIterator, intermediate
591614 return it .Error ()
592615}
593616
617+ // buildRemovedAccountStorageNodes builds the "removed" diffs for all the storage nodes for a destroyed account
618+ func (sdb * builder ) buildRemovedAccountStorageNodes (sr common.Hash , intermediateNodes bool , output types2.StorageNodeSink ) error {
619+ if bytes .Equal (sr .Bytes (), emptyContractRoot .Bytes ()) {
620+ return nil
621+ }
622+ log .Debug ("Storage Root For Removed Diffs" , "root" , sr .Hex ())
623+ sTrie , err := sdb .stateCache .OpenTrie (sr )
624+ if err != nil {
625+ log .Info ("error in build removed account storage diffs" , "error" , err )
626+ return err
627+ }
628+ it := sTrie .NodeIterator (make ([]byte , 0 ))
629+ err = sdb .buildRemovedStorageNodesFromTrie (it , intermediateNodes , output )
630+ if err != nil {
631+ return err
632+ }
633+ return nil
634+ }
635+
636+ // buildRemovedStorageNodesFromTrie returns diffs for all the storage nodes in the provided node interator
637+ // including intermediate nodes can be turned on or off
638+ func (sdb * builder ) buildRemovedStorageNodesFromTrie (it trie.NodeIterator , intermediateNodes bool , output types2.StorageNodeSink ) error {
639+ for it .Next (true ) {
640+ // skip value nodes
641+ if it .Leaf () || bytes .Equal (nullHashBytes , it .Hash ().Bytes ()) {
642+ continue
643+ }
644+ node , nodeElements , err := trie_helpers .ResolveNode (it , sdb .stateCache .TrieDB ())
645+ if err != nil {
646+ return err
647+ }
648+ switch node .NodeType {
649+ case types2 .Leaf :
650+ partialPath := trie .CompactToHex (nodeElements [0 ].([]byte ))
651+ valueNodePath := append (node .Path , partialPath ... )
652+ encodedPath := trie .HexToCompact (valueNodePath )
653+ leafKey := encodedPath [1 :]
654+ if err := output (types2.StorageNode {
655+ NodeType : types2 .Removed ,
656+ Path : node .Path ,
657+ NodeValue : []byte {},
658+ LeafKey : leafKey ,
659+ }); err != nil {
660+ return err
661+ }
662+ case types2 .Extension , types2 .Branch :
663+ if intermediateNodes {
664+ if err := output (types2.StorageNode {
665+ NodeType : types2 .Removed ,
666+ Path : node .Path ,
667+ NodeValue : []byte {},
668+ }); err != nil {
669+ return err
670+ }
671+ }
672+ default :
673+ return fmt .Errorf ("unexpected node type %s" , node .NodeType )
674+ }
675+ }
676+ return it .Error ()
677+ }
678+
594679// buildStorageNodesIncremental builds the storage diff node objects for all nodes that exist in a different state at B than A
595680func (sdb * builder ) buildStorageNodesIncremental (oldSR common.Hash , newSR common.Hash , intermediateNodes bool , output types2.StorageNodeSink ) error {
596681 if bytes .Equal (newSR .Bytes (), oldSR .Bytes ()) {
@@ -606,22 +691,23 @@ func (sdb *builder) buildStorageNodesIncremental(oldSR common.Hash, newSR common
606691 return err
607692 }
608693
609- diffPathsAtB , err := sdb .createdAndUpdatedStorage (
694+ diffSlotsAtB , diffPathsAtB , err := sdb .createdAndUpdatedStorage (
610695 oldTrie .NodeIterator ([]byte {}), newTrie .NodeIterator ([]byte {}),
611696 intermediateNodes , output )
612697 if err != nil {
613698 return err
614699 }
615700 err = sdb .deletedOrUpdatedStorage (oldTrie .NodeIterator ([]byte {}), newTrie .NodeIterator ([]byte {}),
616- diffPathsAtB , intermediateNodes , output )
701+ diffSlotsAtB , diffPathsAtB , intermediateNodes , output )
617702 if err != nil {
618703 return err
619704 }
620705 return nil
621706}
622707
623- func (sdb * builder ) createdAndUpdatedStorage (a , b trie.NodeIterator , intermediateNodes bool , output types2.StorageNodeSink ) (map [string ]bool , error ) {
708+ func (sdb * builder ) createdAndUpdatedStorage (a , b trie.NodeIterator , intermediateNodes bool , output types2.StorageNodeSink ) (map [string ]bool , map [ string ] bool , error ) {
624709 diffPathsAtB := make (map [string ]bool )
710+ diffSlotsAtB := make (map [string ]bool )
625711 it , _ := trie .NewDifferenceIterator (a , b )
626712 for it .Next (true ) {
627713 // skip value nodes
@@ -630,21 +716,22 @@ func (sdb *builder) createdAndUpdatedStorage(a, b trie.NodeIterator, intermediat
630716 }
631717 node , nodeElements , err := trie_helpers .ResolveNode (it , sdb .stateCache .TrieDB ())
632718 if err != nil {
633- return nil , err
719+ return nil , nil , err
634720 }
635721 switch node .NodeType {
636722 case types2 .Leaf :
637723 partialPath := trie .CompactToHex (nodeElements [0 ].([]byte ))
638724 valueNodePath := append (node .Path , partialPath ... )
639725 encodedPath := trie .HexToCompact (valueNodePath )
640726 leafKey := encodedPath [1 :]
727+ diffSlotsAtB [common .Bytes2Hex (leafKey )] = true
641728 if err := output (types2.StorageNode {
642729 NodeType : node .NodeType ,
643730 Path : node .Path ,
644731 NodeValue : node .NodeValue ,
645732 LeafKey : leafKey ,
646733 }); err != nil {
647- return nil , err
734+ return nil , nil , err
648735 }
649736 case types2 .Extension , types2 .Branch :
650737 if intermediateNodes {
@@ -653,18 +740,18 @@ func (sdb *builder) createdAndUpdatedStorage(a, b trie.NodeIterator, intermediat
653740 Path : node .Path ,
654741 NodeValue : node .NodeValue ,
655742 }); err != nil {
656- return nil , err
743+ return nil , nil , err
657744 }
658745 }
659746 default :
660- return nil , fmt .Errorf ("unexpected node type %s" , node .NodeType )
747+ return nil , nil , fmt .Errorf ("unexpected node type %s" , node .NodeType )
661748 }
662749 diffPathsAtB [common .Bytes2Hex (node .Path )] = true
663750 }
664- return diffPathsAtB , it .Error ()
751+ return diffSlotsAtB , diffPathsAtB , it .Error ()
665752}
666753
667- func (sdb * builder ) deletedOrUpdatedStorage (a , b trie.NodeIterator , diffPathsAtB map [string ]bool , intermediateNodes bool , output types2.StorageNodeSink ) error {
754+ func (sdb * builder ) deletedOrUpdatedStorage (a , b trie.NodeIterator , diffSlotsAtB , diffPathsAtB map [string ]bool , intermediateNodes bool , output types2.StorageNodeSink ) error {
668755 it , _ := trie .NewDifferenceIterator (b , a )
669756 for it .Next (true ) {
670757 // skip value nodes
@@ -675,34 +762,53 @@ func (sdb *builder) deletedOrUpdatedStorage(a, b trie.NodeIterator, diffPathsAtB
675762 if err != nil {
676763 return err
677764 }
678- // if this node path showed up in diffPathsAtB
679- // that means this node was updated at B and we already have the updated diff for it
680- // otherwise that means this node was deleted in B and we need to add a "removed" diff to represent that event
681- if _ , ok := diffPathsAtB [common .Bytes2Hex (node .Path )]; ok {
682- continue
683- }
765+
684766 switch node .NodeType {
685767 case types2 .Leaf :
686768 partialPath := trie .CompactToHex (nodeElements [0 ].([]byte ))
687769 valueNodePath := append (node .Path , partialPath ... )
688770 encodedPath := trie .HexToCompact (valueNodePath )
689771 leafKey := encodedPath [1 :]
690- if err := output (types2.StorageNode {
691- NodeType : types2 .Removed ,
692- Path : node .Path ,
693- NodeValue : []byte {},
694- LeafKey : leafKey ,
695- }); err != nil {
696- return err
772+
773+ // if this node's path did not show up in diffPathsAtB
774+ // that means the node at this path was deleted (or moved) in B
775+ if _ , ok := diffPathsAtB [common .Bytes2Hex (node .Path )]; ! ok {
776+ // if this node's leaf key also did not show up in diffSlotsAtB
777+ // that means the node was deleted
778+ // in that case, emit an empty "removed" diff storage node
779+ if _ , ok := diffSlotsAtB [common .Bytes2Hex (leafKey )]; ! ok {
780+ if err := output (types2.StorageNode {
781+ NodeType : types2 .Removed ,
782+ Path : node .Path ,
783+ NodeValue : []byte {},
784+ LeafKey : leafKey ,
785+ }); err != nil {
786+ return err
787+ }
788+ } else {
789+ // emit an empty "removed" diff with empty leaf key if the account was moved
790+ if err := output (types2.StorageNode {
791+ NodeType : types2 .Removed ,
792+ Path : node .Path ,
793+ NodeValue : []byte {},
794+ }); err != nil {
795+ return err
796+ }
797+ }
697798 }
698799 case types2 .Extension , types2 .Branch :
699- if intermediateNodes {
700- if err := output (types2.StorageNode {
701- NodeType : types2 .Removed ,
702- Path : node .Path ,
703- NodeValue : []byte {},
704- }); err != nil {
705- return err
800+ // if this node's path did not show up in diffPathsAtB
801+ // that means the node at this path was deleted in B
802+ // in that case, emit an empty "removed" diff storage node
803+ if _ , ok := diffPathsAtB [common .Bytes2Hex (node .Path )]; ! ok {
804+ if intermediateNodes {
805+ if err := output (types2.StorageNode {
806+ NodeType : types2 .Removed ,
807+ Path : node .Path ,
808+ NodeValue : []byte {},
809+ }); err != nil {
810+ return err
811+ }
706812 }
707813 }
708814 default :
0 commit comments