Index Removed diffs without leaf keys if an account or storage node is moved
This commit is contained in:
parent
9917e6c293
commit
c21aa96962
@ -202,7 +202,7 @@ func (sdb *builder) buildStateDiffWithIntermediateStateNodes(args types2.StateRo
|
|||||||
// a map of their leafkey to all the accounts that were touched and exist at A
|
// a map of their leafkey to all the accounts that were touched and exist at A
|
||||||
diffAccountsAtA, err := sdb.deletedOrUpdatedState(
|
diffAccountsAtA, err := sdb.deletedOrUpdatedState(
|
||||||
oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}),
|
oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}),
|
||||||
diffPathsAtB, params.watchedAddressesLeafKeys,
|
diffAccountsAtB, diffPathsAtB, params.watchedAddressesLeafKeys,
|
||||||
params.IntermediateStorageNodes, output)
|
params.IntermediateStorageNodes, output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error collecting deletedOrUpdatedNodes: %v", err)
|
return fmt.Errorf("error collecting deletedOrUpdatedNodes: %v", err)
|
||||||
@ -257,7 +257,7 @@ func (sdb *builder) buildStateDiffWithoutIntermediateStateNodes(args types2.Stat
|
|||||||
// a map of their leafkey to all the accounts that were touched and exist at A
|
// a map of their leafkey to all the accounts that were touched and exist at A
|
||||||
diffAccountsAtA, err := sdb.deletedOrUpdatedState(
|
diffAccountsAtA, err := sdb.deletedOrUpdatedState(
|
||||||
oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}),
|
oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}),
|
||||||
diffPathsAtB, params.watchedAddressesLeafKeys,
|
diffAccountsAtB, diffPathsAtB, params.watchedAddressesLeafKeys,
|
||||||
params.IntermediateStorageNodes, output)
|
params.IntermediateStorageNodes, output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error collecting deletedOrUpdatedNodes: %v", err)
|
return fmt.Errorf("error collecting deletedOrUpdatedNodes: %v", err)
|
||||||
@ -388,7 +388,7 @@ func (sdb *builder) createdAndUpdatedStateWithIntermediateNodes(a, b trie.NodeIt
|
|||||||
|
|
||||||
// deletedOrUpdatedState returns a slice of all the pathes that are emptied at B
|
// deletedOrUpdatedState returns a slice of all the pathes that are emptied at B
|
||||||
// and a mapping of their leafkeys to all the accounts that exist in a different state at A than B
|
// and a mapping of their leafkeys to all the accounts that exist in a different state at A than B
|
||||||
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) {
|
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) {
|
||||||
diffAccountAtA := make(types2.AccountMap)
|
diffAccountAtA := make(types2.AccountMap)
|
||||||
it, _ := trie.NewDifferenceIterator(b, a)
|
it, _ := trie.NewDifferenceIterator(b, a)
|
||||||
for it.Next(true) {
|
for it.Next(true) {
|
||||||
@ -421,10 +421,14 @@ func (sdb *builder) deletedOrUpdatedState(a, b trie.NodeIterator, diffPathsAtB m
|
|||||||
}
|
}
|
||||||
// if this node's path did not show up in diffPathsAtB
|
// if this node's path did not show up in diffPathsAtB
|
||||||
// that means the node at this path was deleted (or moved) in B
|
// that means the node at this path was deleted (or moved) in B
|
||||||
// emit an empty "removed" diff to signify as such
|
|
||||||
// emit empty "removed" diff for all storage nodes
|
|
||||||
if _, ok := diffPathsAtB[common.Bytes2Hex(node.Path)]; !ok {
|
if _, ok := diffPathsAtB[common.Bytes2Hex(node.Path)]; !ok {
|
||||||
diff := types2.StateNode{
|
var diff types2.StateNode
|
||||||
|
// if this node's leaf key also did not show up in diffAccountsAtB
|
||||||
|
// that means the node was deleted
|
||||||
|
// in that case, emit an empty "removed" diff state node
|
||||||
|
// include empty "removed" diff storage nodes for all the storage slots
|
||||||
|
if _, ok := diffAccountsAtB[common.Bytes2Hex(leafKey)]; !ok {
|
||||||
|
diff = types2.StateNode{
|
||||||
NodeType: types2.Removed,
|
NodeType: types2.Removed,
|
||||||
Path: node.Path,
|
Path: node.Path,
|
||||||
LeafKey: leafKey,
|
LeafKey: leafKey,
|
||||||
@ -437,6 +441,14 @@ func (sdb *builder) deletedOrUpdatedState(a, b trie.NodeIterator, diffPathsAtB m
|
|||||||
return nil, fmt.Errorf("failed building storage diffs for removed node %x\r\nerror: %v", node.Path, err)
|
return nil, fmt.Errorf("failed building storage diffs for removed node %x\r\nerror: %v", node.Path, err)
|
||||||
}
|
}
|
||||||
diff.StorageNodes = storageDiffs
|
diff.StorageNodes = storageDiffs
|
||||||
|
} else {
|
||||||
|
// emit an empty "removed" diff with empty leaf key if the account was moved
|
||||||
|
diff = types2.StateNode{
|
||||||
|
NodeType: types2.Removed,
|
||||||
|
Path: node.Path,
|
||||||
|
NodeValue: []byte{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := output(diff); err != nil {
|
if err := output(diff); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -679,22 +691,23 @@ func (sdb *builder) buildStorageNodesIncremental(oldSR common.Hash, newSR common
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
diffPathsAtB, err := sdb.createdAndUpdatedStorage(
|
diffSlotsAtB, diffPathsAtB, err := sdb.createdAndUpdatedStorage(
|
||||||
oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}),
|
oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}),
|
||||||
intermediateNodes, output)
|
intermediateNodes, output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = sdb.deletedOrUpdatedStorage(oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}),
|
err = sdb.deletedOrUpdatedStorage(oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}),
|
||||||
diffPathsAtB, intermediateNodes, output)
|
diffSlotsAtB, diffPathsAtB, intermediateNodes, output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sdb *builder) createdAndUpdatedStorage(a, b trie.NodeIterator, intermediateNodes bool, output types2.StorageNodeSink) (map[string]bool, error) {
|
func (sdb *builder) createdAndUpdatedStorage(a, b trie.NodeIterator, intermediateNodes bool, output types2.StorageNodeSink) (map[string]bool, map[string]bool, error) {
|
||||||
diffPathsAtB := make(map[string]bool)
|
diffPathsAtB := make(map[string]bool)
|
||||||
|
diffSlotsAtB := make(map[string]bool)
|
||||||
it, _ := trie.NewDifferenceIterator(a, b)
|
it, _ := trie.NewDifferenceIterator(a, b)
|
||||||
for it.Next(true) {
|
for it.Next(true) {
|
||||||
// skip value nodes
|
// skip value nodes
|
||||||
@ -703,7 +716,7 @@ func (sdb *builder) createdAndUpdatedStorage(a, b trie.NodeIterator, intermediat
|
|||||||
}
|
}
|
||||||
node, nodeElements, err := trie_helpers.ResolveNode(it, sdb.stateCache.TrieDB())
|
node, nodeElements, err := trie_helpers.ResolveNode(it, sdb.stateCache.TrieDB())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
switch node.NodeType {
|
switch node.NodeType {
|
||||||
case types2.Leaf:
|
case types2.Leaf:
|
||||||
@ -711,13 +724,14 @@ func (sdb *builder) createdAndUpdatedStorage(a, b trie.NodeIterator, intermediat
|
|||||||
valueNodePath := append(node.Path, partialPath...)
|
valueNodePath := append(node.Path, partialPath...)
|
||||||
encodedPath := trie.HexToCompact(valueNodePath)
|
encodedPath := trie.HexToCompact(valueNodePath)
|
||||||
leafKey := encodedPath[1:]
|
leafKey := encodedPath[1:]
|
||||||
|
diffSlotsAtB[common.Bytes2Hex(leafKey)] = true
|
||||||
if err := output(types2.StorageNode{
|
if err := output(types2.StorageNode{
|
||||||
NodeType: node.NodeType,
|
NodeType: node.NodeType,
|
||||||
Path: node.Path,
|
Path: node.Path,
|
||||||
NodeValue: node.NodeValue,
|
NodeValue: node.NodeValue,
|
||||||
LeafKey: leafKey,
|
LeafKey: leafKey,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
case types2.Extension, types2.Branch:
|
case types2.Extension, types2.Branch:
|
||||||
if intermediateNodes {
|
if intermediateNodes {
|
||||||
@ -726,18 +740,18 @@ func (sdb *builder) createdAndUpdatedStorage(a, b trie.NodeIterator, intermediat
|
|||||||
Path: node.Path,
|
Path: node.Path,
|
||||||
NodeValue: node.NodeValue,
|
NodeValue: node.NodeValue,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unexpected node type %s", node.NodeType)
|
return nil, nil, fmt.Errorf("unexpected node type %s", node.NodeType)
|
||||||
}
|
}
|
||||||
diffPathsAtB[common.Bytes2Hex(node.Path)] = true
|
diffPathsAtB[common.Bytes2Hex(node.Path)] = true
|
||||||
}
|
}
|
||||||
return diffPathsAtB, it.Error()
|
return diffSlotsAtB, diffPathsAtB, it.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sdb *builder) deletedOrUpdatedStorage(a, b trie.NodeIterator, diffPathsAtB map[string]bool, intermediateNodes bool, output types2.StorageNodeSink) error {
|
func (sdb *builder) deletedOrUpdatedStorage(a, b trie.NodeIterator, diffSlotsAtB, diffPathsAtB map[string]bool, intermediateNodes bool, output types2.StorageNodeSink) error {
|
||||||
it, _ := trie.NewDifferenceIterator(b, a)
|
it, _ := trie.NewDifferenceIterator(b, a)
|
||||||
for it.Next(true) {
|
for it.Next(true) {
|
||||||
// skip value nodes
|
// skip value nodes
|
||||||
@ -748,18 +762,21 @@ func (sdb *builder) deletedOrUpdatedStorage(a, b trie.NodeIterator, diffPathsAtB
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// if this node path showed up in diffPathsAtB
|
|
||||||
// that means this node was updated at B and we already have the updated diff for it
|
|
||||||
// otherwise that means this node was deleted in B and we need to add a "removed" diff to represent that event
|
|
||||||
if _, ok := diffPathsAtB[common.Bytes2Hex(node.Path)]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch node.NodeType {
|
switch node.NodeType {
|
||||||
case types2.Leaf:
|
case types2.Leaf:
|
||||||
partialPath := trie.CompactToHex(nodeElements[0].([]byte))
|
partialPath := trie.CompactToHex(nodeElements[0].([]byte))
|
||||||
valueNodePath := append(node.Path, partialPath...)
|
valueNodePath := append(node.Path, partialPath...)
|
||||||
encodedPath := trie.HexToCompact(valueNodePath)
|
encodedPath := trie.HexToCompact(valueNodePath)
|
||||||
leafKey := encodedPath[1:]
|
leafKey := encodedPath[1:]
|
||||||
|
|
||||||
|
// if this node's path did not show up in diffPathsAtB
|
||||||
|
// that means the node at this path was deleted (or moved) in B
|
||||||
|
if _, ok := diffPathsAtB[common.Bytes2Hex(node.Path)]; !ok {
|
||||||
|
// if this node's leaf key also did not show up in diffSlotsAtB
|
||||||
|
// that means the node was deleted
|
||||||
|
// in that case, emit an empty "removed" diff storage node
|
||||||
|
if _, ok := diffSlotsAtB[common.Bytes2Hex(leafKey)]; !ok {
|
||||||
if err := output(types2.StorageNode{
|
if err := output(types2.StorageNode{
|
||||||
NodeType: types2.Removed,
|
NodeType: types2.Removed,
|
||||||
Path: node.Path,
|
Path: node.Path,
|
||||||
@ -768,7 +785,22 @@ func (sdb *builder) deletedOrUpdatedStorage(a, b trie.NodeIterator, diffPathsAtB
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// emit an empty "removed" diff with empty leaf key if the account was moved
|
||||||
|
if err := output(types2.StorageNode{
|
||||||
|
NodeType: types2.Removed,
|
||||||
|
Path: node.Path,
|
||||||
|
NodeValue: []byte{},
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
case types2.Extension, types2.Branch:
|
case types2.Extension, types2.Branch:
|
||||||
|
// if this node's path did not show up in diffPathsAtB
|
||||||
|
// that means the node at this path was deleted in B
|
||||||
|
// in that case, emit an empty "removed" diff storage node
|
||||||
|
if _, ok := diffPathsAtB[common.Bytes2Hex(node.Path)]; !ok {
|
||||||
if intermediateNodes {
|
if intermediateNodes {
|
||||||
if err := output(types2.StorageNode{
|
if err := output(types2.StorageNode{
|
||||||
NodeType: types2.Removed,
|
NodeType: types2.Removed,
|
||||||
@ -778,6 +810,7 @@ func (sdb *builder) deletedOrUpdatedStorage(a, b trie.NodeIterator, diffPathsAtB
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unexpected node type %s", node.NodeType)
|
return fmt.Errorf("unexpected node type %s", node.NodeType)
|
||||||
}
|
}
|
||||||
|
@ -2087,7 +2087,6 @@ func TestBuilderWithMovedAccount(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Path: []byte{'\x00'},
|
Path: []byte{'\x00'},
|
||||||
NodeType: types2.Removed,
|
NodeType: types2.Removed,
|
||||||
LeafKey: test_helpers.BankLeafKey,
|
|
||||||
NodeValue: []byte{},
|
NodeValue: []byte{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -2224,7 +2223,6 @@ func TestBuilderWithMovedAccountOnlyLeafs(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Path: []byte{'\x00'},
|
Path: []byte{'\x00'},
|
||||||
NodeType: types2.Removed,
|
NodeType: types2.Removed,
|
||||||
LeafKey: test_helpers.BankLeafKey,
|
|
||||||
NodeValue: []byte{},
|
NodeValue: []byte{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user