@@ -198,8 +198,7 @@ func (sdb *StateDiffBuilder) WriteStateDiffObject(args types2.StateRoots, params
198198 },
199199 }
200200
201- if ! params .IntermediateStateNodes || len (params .WatchedAddresses ) > 0 {
202- // if we are watching only specific accounts then we are only diffing leaf nodes
201+ if ! params .IntermediateStateNodes {
203202 return sdb .BuildStateDiffWithoutIntermediateStateNodes (iterPairs , params , output , codeOutput )
204203 } else {
205204 return sdb .BuildStateDiffWithIntermediateStateNodes (iterPairs , params , output , codeOutput )
@@ -211,7 +210,7 @@ func (sdb *StateDiffBuilder) BuildStateDiffWithIntermediateStateNodes(iterPairs
211210 // a map of their leafkey to all the accounts that were touched and exist at B
212211 // and a slice of all the paths for the nodes in both of the above sets
213212 diffAccountsAtB , diffPathsAtB , err := sdb .createdAndUpdatedStateWithIntermediateNodes (
214- iterPairs [0 ].Older , iterPairs [0 ].Newer , output )
213+ iterPairs [0 ].Older , iterPairs [0 ].Newer , params . watchedAddressesLeafPaths , output )
215214 if err != nil {
216215 return fmt .Errorf ("error collecting createdAndUpdatedNodes: %v" , err )
217216 }
@@ -220,7 +219,7 @@ func (sdb *StateDiffBuilder) BuildStateDiffWithIntermediateStateNodes(iterPairs
220219 // a map of their leafkey to all the accounts that were touched and exist at A
221220 diffAccountsAtA , err := sdb .deletedOrUpdatedState (
222221 iterPairs [1 ].Older , iterPairs [1 ].Newer ,
223- diffAccountsAtB , diffPathsAtB , params .watchedAddressesLeafKeys ,
222+ diffAccountsAtB , diffPathsAtB , params .watchedAddressesLeafPaths ,
224223 params .IntermediateStateNodes , params .IntermediateStorageNodes , output )
225224 if err != nil {
226225 return fmt .Errorf ("error collecting deletedOrUpdatedNodes: %v" , err )
@@ -256,7 +255,7 @@ func (sdb *StateDiffBuilder) BuildStateDiffWithoutIntermediateStateNodes(iterPai
256255 // and a slice of all the paths for the nodes in both of the above sets
257256 diffAccountsAtB , diffPathsAtB , err := sdb .createdAndUpdatedState (
258257 iterPairs [0 ].Older , iterPairs [0 ].Newer ,
259- params .watchedAddressesLeafKeys )
258+ params .watchedAddressesLeafPaths )
260259 if err != nil {
261260 return fmt .Errorf ("error collecting createdAndUpdatedNodes: %v" , err )
262261 }
@@ -265,7 +264,7 @@ func (sdb *StateDiffBuilder) BuildStateDiffWithoutIntermediateStateNodes(iterPai
265264 // a map of their leafkey to all the accounts that were touched and exist at A
266265 diffAccountsAtA , err := sdb .deletedOrUpdatedState (
267266 iterPairs [1 ].Older , iterPairs [1 ].Newer ,
268- diffAccountsAtB , diffPathsAtB , params .watchedAddressesLeafKeys ,
267+ diffAccountsAtB , diffPathsAtB , params .watchedAddressesLeafPaths ,
269268 params .IntermediateStateNodes , params .IntermediateStorageNodes , output )
270269 if err != nil {
271270 return fmt .Errorf ("error collecting deletedOrUpdatedNodes: %v" , err )
@@ -299,11 +298,18 @@ func (sdb *StateDiffBuilder) BuildStateDiffWithoutIntermediateStateNodes(iterPai
299298// createdAndUpdatedState returns
300299// a mapping of their leafkeys to all the accounts that exist in a different state at B than A
301300// and a slice of the paths for all of the nodes included in both
302- func (sdb * StateDiffBuilder ) createdAndUpdatedState (a , b trie.NodeIterator , watchedAddressesLeafKeys map [common. Hash ] struct {} ) (types2.AccountMap , map [string ]bool , error ) {
301+ func (sdb * StateDiffBuilder ) createdAndUpdatedState (a , b trie.NodeIterator , watchedAddressesLeafPaths [][] byte ) (types2.AccountMap , map [string ]bool , error ) {
303302 diffPathsAtB := make (map [string ]bool )
304- diffAcountsAtB := make (types2.AccountMap )
303+ diffAccountsAtB := make (types2.AccountMap )
304+ watchingAddresses := len (watchedAddressesLeafPaths ) > 0
305+
305306 it , _ := trie .NewDifferenceIterator (a , b )
306307 for it .Next (true ) {
308+ // ignore node if it is not along paths of interest
309+ if watchingAddresses && ! isValidPrefixPath (watchedAddressesLeafPaths , it .Path ()) {
310+ continue
311+ }
312+
307313 // skip value nodes
308314 if it .Leaf () || bytes .Equal (nullHashBytes , it .Hash ().Bytes ()) {
309315 continue
@@ -322,33 +328,44 @@ func (sdb *StateDiffBuilder) createdAndUpdatedState(a, b trie.NodeIterator, watc
322328 }
323329 partialPath := trie .CompactToHex (nodeElements [0 ].([]byte ))
324330 valueNodePath := append (node .Path , partialPath ... )
331+
332+ // ignore leaf node if it is not a watched address
333+ if ! isWatchedAddress (watchedAddressesLeafPaths , valueNodePath ) {
334+ continue
335+ }
336+
325337 encodedPath := trie .HexToCompact (valueNodePath )
326338 leafKey := encodedPath [1 :]
327- if isWatchedAddress (watchedAddressesLeafKeys , leafKey ) {
328- diffAcountsAtB [common .Bytes2Hex (leafKey )] = types2.AccountWrapper {
329- NodeType : node .NodeType ,
330- Path : node .Path ,
331- NodeValue : node .NodeValue ,
332- LeafKey : leafKey ,
333- Account : & account ,
334- }
339+ diffAccountsAtB [common .Bytes2Hex (leafKey )] = types2.AccountWrapper {
340+ NodeType : node .NodeType ,
341+ Path : node .Path ,
342+ NodeValue : node .NodeValue ,
343+ LeafKey : leafKey ,
344+ Account : & account ,
335345 }
336346 }
337347 // add both intermediate and leaf node paths to the list of diffPathsAtB
338348 diffPathsAtB [common .Bytes2Hex (node .Path )] = true
339349 }
340- return diffAcountsAtB , diffPathsAtB , it .Error ()
350+ return diffAccountsAtB , diffPathsAtB , it .Error ()
341351}
342352
343353// createdAndUpdatedStateWithIntermediateNodes returns
344354// a slice of all the intermediate nodes that exist in a different state at B than A
345355// a mapping of their leafkeys to all the accounts that exist in a different state at B than A
346356// and a slice of the paths for all of the nodes included in both
347- func (sdb * StateDiffBuilder ) createdAndUpdatedStateWithIntermediateNodes (a , b trie.NodeIterator , output types2.StateNodeSink ) (types2.AccountMap , map [string ]bool , error ) {
357+ func (sdb * StateDiffBuilder ) createdAndUpdatedStateWithIntermediateNodes (a , b trie.NodeIterator , watchedAddressesLeafPaths [][] byte , output types2.StateNodeSink ) (types2.AccountMap , map [string ]bool , error ) {
348358 diffPathsAtB := make (map [string ]bool )
349- diffAcountsAtB := make (types2.AccountMap )
359+ diffAccountsAtB := make (types2.AccountMap )
360+ watchingAddresses := len (watchedAddressesLeafPaths ) > 0
361+
350362 it , _ := trie .NewDifferenceIterator (a , b )
351363 for it .Next (true ) {
364+ // ignore node if it is not along paths of interest
365+ if watchingAddresses && ! isValidPrefixPath (watchedAddressesLeafPaths , it .Path ()) {
366+ continue
367+ }
368+
352369 // skip value nodes
353370 if it .Leaf () || bytes .Equal (nullHashBytes , it .Hash ().Bytes ()) {
354371 continue
@@ -367,9 +384,15 @@ func (sdb *StateDiffBuilder) createdAndUpdatedStateWithIntermediateNodes(a, b tr
367384 }
368385 partialPath := trie .CompactToHex (nodeElements [0 ].([]byte ))
369386 valueNodePath := append (node .Path , partialPath ... )
387+
388+ // ignore leaf node if it is not a watched address
389+ if ! isWatchedAddress (watchedAddressesLeafPaths , valueNodePath ) {
390+ continue
391+ }
392+
370393 encodedPath := trie .HexToCompact (valueNodePath )
371394 leafKey := encodedPath [1 :]
372- diffAcountsAtB [common .Bytes2Hex (leafKey )] = types2.AccountWrapper {
395+ diffAccountsAtB [common .Bytes2Hex (leafKey )] = types2.AccountWrapper {
373396 NodeType : node .NodeType ,
374397 Path : node .Path ,
375398 NodeValue : node .NodeValue ,
@@ -392,15 +415,22 @@ func (sdb *StateDiffBuilder) createdAndUpdatedStateWithIntermediateNodes(a, b tr
392415 // add both intermediate and leaf node paths to the list of diffPathsAtB
393416 diffPathsAtB [common .Bytes2Hex (node .Path )] = true
394417 }
395- return diffAcountsAtB , diffPathsAtB , it .Error ()
418+ return diffAccountsAtB , diffPathsAtB , it .Error ()
396419}
397420
398421// deletedOrUpdatedState returns a slice of all the pathes that are emptied at B
399422// and a mapping of their leafkeys to all the accounts that exist in a different state at A than B
400- func (sdb * StateDiffBuilder ) deletedOrUpdatedState (a , b trie.NodeIterator , diffAccountsAtB types2.AccountMap , diffPathsAtB map [string ]bool , watchedAddressesLeafKeys map [common. Hash ] struct {} , intermediateStateNodes , intermediateStorageNodes bool , output types2.StateNodeSink ) (types2.AccountMap , error ) {
423+ func (sdb * StateDiffBuilder ) deletedOrUpdatedState (a , b trie.NodeIterator , diffAccountsAtB types2.AccountMap , diffPathsAtB map [string ]bool , watchedAddressesLeafPaths [][] byte , intermediateStateNodes , intermediateStorageNodes bool , output types2.StateNodeSink ) (types2.AccountMap , error ) {
401424 diffAccountAtA := make (types2.AccountMap )
425+ watchingAddresses := len (watchedAddressesLeafPaths ) > 0
426+
402427 it , _ := trie .NewDifferenceIterator (b , a )
403428 for it .Next (true ) {
429+ // ignore node if it is not along paths of interest
430+ if watchingAddresses && ! isValidPrefixPath (watchedAddressesLeafPaths , it .Path ()) {
431+ continue
432+ }
433+
404434 // skip value nodes
405435 if it .Leaf () || bytes .Equal (nullHashBytes , it .Hash ().Bytes ()) {
406436 continue
@@ -419,50 +449,54 @@ func (sdb *StateDiffBuilder) deletedOrUpdatedState(a, b trie.NodeIterator, diffA
419449 }
420450 partialPath := trie .CompactToHex (nodeElements [0 ].([]byte ))
421451 valueNodePath := append (node .Path , partialPath ... )
452+
453+ // ignore leaf node if it is not a watched address
454+ if ! isWatchedAddress (watchedAddressesLeafPaths , valueNodePath ) {
455+ continue
456+ }
457+
422458 encodedPath := trie .HexToCompact (valueNodePath )
423459 leafKey := encodedPath [1 :]
424- if isWatchedAddress (watchedAddressesLeafKeys , leafKey ) {
425- diffAccountAtA [common .Bytes2Hex (leafKey )] = types2.AccountWrapper {
426- NodeType : node .NodeType ,
427- Path : node .Path ,
428- NodeValue : node .NodeValue ,
429- LeafKey : leafKey ,
430- Account : & account ,
431- }
432- // if this node's path did not show up in diffPathsAtB
433- // that means the node at this path was deleted (or moved) in B
434- if _ , ok := diffPathsAtB [common .Bytes2Hex (node .Path )]; ! ok {
435- var diff types2.StateNode
436- // if this node's leaf key also did not show up in diffAccountsAtB
437- // that means the node was deleted
438- // in that case, emit an empty "removed" diff state node
439- // include empty "removed" diff storage nodes for all the storage slots
440- if _ , ok := diffAccountsAtB [common .Bytes2Hex (leafKey )]; ! ok {
441- diff = types2.StateNode {
442- NodeType : types2 .Removed ,
443- Path : node .Path ,
444- LeafKey : leafKey ,
445- NodeValue : []byte {},
446- }
447-
448- var storageDiffs []types2.StorageNode
449- err := sdb .buildRemovedAccountStorageNodes (account .Root , intermediateStorageNodes , StorageNodeAppender (& storageDiffs ))
450- if err != nil {
451- return nil , fmt .Errorf ("failed building storage diffs for removed node %x\r \n error: %v" , node .Path , err )
452- }
453- diff .StorageNodes = storageDiffs
454- } else {
455- // emit an empty "removed" diff with empty leaf key if the account was moved
456- diff = types2.StateNode {
457- NodeType : types2 .Removed ,
458- Path : node .Path ,
459- NodeValue : []byte {},
460- }
460+ diffAccountAtA [common .Bytes2Hex (leafKey )] = types2.AccountWrapper {
461+ NodeType : node .NodeType ,
462+ Path : node .Path ,
463+ NodeValue : node .NodeValue ,
464+ LeafKey : leafKey ,
465+ Account : & account ,
466+ }
467+ // if this node's path did not show up in diffPathsAtB
468+ // that means the node at this path was deleted (or moved) in B
469+ if _ , ok := diffPathsAtB [common .Bytes2Hex (node .Path )]; ! ok {
470+ var diff types2.StateNode
471+ // if this node's leaf key also did not show up in diffAccountsAtB
472+ // that means the node was deleted
473+ // in that case, emit an empty "removed" diff state node
474+ // include empty "removed" diff storage nodes for all the storage slots
475+ if _ , ok := diffAccountsAtB [common .Bytes2Hex (leafKey )]; ! ok {
476+ diff = types2.StateNode {
477+ NodeType : types2 .Removed ,
478+ Path : node .Path ,
479+ LeafKey : leafKey ,
480+ NodeValue : []byte {},
461481 }
462482
463- if err := output (diff ); err != nil {
464- return nil , err
483+ var storageDiffs []types2.StorageNode
484+ err := sdb .buildRemovedAccountStorageNodes (account .Root , intermediateStorageNodes , StorageNodeAppender (& storageDiffs ))
485+ if err != nil {
486+ return nil , fmt .Errorf ("failed building storage diffs for removed node %x\r \n error: %v" , node .Path , err )
465487 }
488+ diff .StorageNodes = storageDiffs
489+ } else {
490+ // emit an empty "removed" diff with empty leaf key if the account was moved
491+ diff = types2.StateNode {
492+ NodeType : types2 .Removed ,
493+ Path : node .Path ,
494+ NodeValue : []byte {},
495+ }
496+ }
497+
498+ if err := output (diff ); err != nil {
499+ return nil , err
466500 }
467501 }
468502 case types2 .Extension , types2 .Branch :
@@ -830,13 +864,29 @@ func (sdb *StateDiffBuilder) deletedOrUpdatedStorage(a, b trie.NodeIterator, dif
830864 return it .Error ()
831865}
832866
867+ // isValidPrefixPath is used to check if a node at currentPath is a parent | ancestor to one of the addresses the builder is configured to watch
868+ func isValidPrefixPath (watchedAddressesLeafPaths [][]byte , currentPath []byte ) bool {
869+ for _ , watchedAddressPath := range watchedAddressesLeafPaths {
870+ if bytes .HasPrefix (watchedAddressPath , currentPath ) {
871+ return true
872+ }
873+ }
874+
875+ return false
876+ }
877+
833878// isWatchedAddress is used to check if a state account corresponds to one of the addresses the builder is configured to watch
834- func isWatchedAddress (watchedAddressesLeafKeys map [common. Hash ] struct {}, stateLeafKey []byte ) bool {
879+ func isWatchedAddress (watchedAddressesLeafPaths [][] byte , valueNodePath []byte ) bool {
835880 // If we aren't watching any specific addresses, we are watching everything
836- if len (watchedAddressesLeafKeys ) == 0 {
881+ if len (watchedAddressesLeafPaths ) == 0 {
837882 return true
838883 }
839884
840- _ , ok := watchedAddressesLeafKeys [common .BytesToHash (stateLeafKey )]
841- return ok
885+ for _ , watchedAddressPath := range watchedAddressesLeafPaths {
886+ if bytes .Equal (watchedAddressPath , valueNodePath ) {
887+ return true
888+ }
889+ }
890+
891+ return false
842892}
0 commit comments