diff type for representing deleted accounts

This commit is contained in:
Ian Norden 2020-05-10 15:44:21 -05:00
parent 5c3e0d6437
commit b7c412d303
6 changed files with 414 additions and 395 deletions

View File

@ -89,21 +89,21 @@ func (sdb *builder) BuildStateDiff(oldStateRoot, newStateRoot common.Hash, block
if err != nil {
return StateDiff{}, fmt.Errorf("error building diff for updated accounts: %v", err)
}
createdAccounts, err := sdb.buildDiffEventual(creations)
createdAccounts, err := sdb.buildDiffCreations(creations)
if err != nil {
return StateDiff{}, fmt.Errorf("error building diff for created accounts: %v", err)
}
deletedAccounts, err := sdb.buildDiffEventual(deletions)
deletedAccounts, err := sdb.buildDiffDeletions(deletions)
if err != nil {
return StateDiff{}, fmt.Errorf("error building diff for deleted accounts: %v", err)
}
return StateDiff{
BlockNumber: blockNumber,
BlockHash: blockHash,
CreatedAccounts: createdAccounts,
DeletedAccounts: deletedAccounts,
UpdatedAccounts: updatedAccounts,
BlockNumber: blockNumber,
BlockHash: blockHash,
CreatedNodes: createdAccounts,
DeletedNodes: deletedAccounts,
UpdatedNodes: updatedAccounts,
}, nil
}
@ -184,52 +184,66 @@ func (sdb *builder) collectDiffNodes(a, b trie.NodeIterator) (AccountsMap, error
return diffAccounts, nil
}
func (sdb *builder) buildDiffEventual(accounts AccountsMap) ([]AccountDiff, error) {
accountDiffs := make([]AccountDiff, 0)
func (sdb *builder) buildDiffCreations(accounts AccountsMap) ([]StateNode, error) {
accountDiffs := make([]StateNode, 0, len(accounts))
var err error
for _, val := range accounts {
// If account is not nil, we need to process storage diffs
var storageDiffs []StorageDiff
var storageDiffs []StorageNode
if val.Account != nil {
storageDiffs, err = sdb.buildStorageDiffsEventual(val.Account.Root)
storageDiffs, err = sdb.buildStorageNodesEventual(val.Account.Root)
if err != nil {
return nil, fmt.Errorf("failed building eventual storage diffs for node %x\r\nerror: %v", val.Path, err)
}
}
accountDiffs = append(accountDiffs, AccountDiff{
NodeType: val.NodeType,
Path: val.Path,
LeafKey: val.LeafKey,
NodeValue: val.NodeValue,
Storage: storageDiffs,
accountDiffs = append(accountDiffs, StateNode{
NodeType: val.NodeType,
Path: val.Path,
LeafKey: val.LeafKey,
NodeValue: val.NodeValue,
StorageDiffs: storageDiffs,
})
}
return accountDiffs, nil
}
func (sdb *builder) buildDiffIncremental(creations AccountsMap, deletions AccountsMap, updatedKeys []string) ([]AccountDiff, error) {
updatedAccounts := make([]AccountDiff, 0)
func (sdb *builder) buildDiffDeletions(accounts AccountsMap) ([]StateNode, error) {
accountDiffs := make([]StateNode, 0, len(accounts))
for _, val := range accounts {
// deleted account can not have storage or it would not be deleted
accountDiffs = append(accountDiffs, StateNode{
NodeType: Removed,
Path: val.Path,
LeafKey: val.LeafKey,
NodeValue: []byte{},
})
}
return accountDiffs, nil
}
func (sdb *builder) buildDiffIncremental(creations AccountsMap, deletions AccountsMap, updatedKeys []string) ([]StateNode, error) {
updatedAccounts := make([]StateNode, 0, len(updatedKeys))
var err error
for _, val := range updatedKeys {
hashKey := common.HexToHash(val)
createdAcc := creations[hashKey]
deletedAcc := deletions[hashKey]
var storageDiffs []StorageDiff
var storageDiffs []StorageNode
if deletedAcc.Account != nil && createdAcc.Account != nil {
oldSR := deletedAcc.Account.Root
newSR := createdAcc.Account.Root
storageDiffs, err = sdb.buildStorageDiffsIncremental(oldSR, newSR)
storageDiffs, err = sdb.buildStorageNodesIncremental(oldSR, newSR)
if err != nil {
return nil, fmt.Errorf("failed building incremental storage diffs for %s\r\nerror: %v", hashKey.Hex(), err)
}
}
updatedAccounts = append(updatedAccounts, AccountDiff{
NodeType: createdAcc.NodeType,
Path: createdAcc.Path,
NodeValue: createdAcc.NodeValue,
LeafKey: createdAcc.LeafKey,
Storage: storageDiffs,
updatedAccounts = append(updatedAccounts, StateNode{
NodeType: createdAcc.NodeType,
Path: createdAcc.Path,
NodeValue: createdAcc.NodeValue,
LeafKey: createdAcc.LeafKey,
StorageDiffs: storageDiffs,
})
delete(creations, common.HexToHash(val))
delete(deletions, common.HexToHash(val))
@ -238,7 +252,10 @@ func (sdb *builder) buildDiffIncremental(creations AccountsMap, deletions Accoun
return updatedAccounts, nil
}
func (sdb *builder) buildStorageDiffsEventual(sr common.Hash) ([]StorageDiff, error) {
// if an account is moved to a new path that didn't previously have a node, it appears to have been "created"
// but it actually has a previous state associated with, a previous storage trie, so this would produce the
// wrong result... it would produce a node for the entire trie, not just the diffs since the last state
func (sdb *builder) buildStorageNodesEventual(sr common.Hash) ([]StorageNode, error) {
log.Debug("Storage Root For Eventual Diff", "root", sr.Hex())
stateCache := sdb.blockChain.StateCache()
sTrie, err := stateCache.OpenTrie(sr)
@ -247,10 +264,10 @@ func (sdb *builder) buildStorageDiffsEventual(sr common.Hash) ([]StorageDiff, er
return nil, err
}
it := sTrie.NodeIterator(make([]byte, 0))
return sdb.buildStorageDiffsFromTrie(it)
return sdb.buildStorageNodesFromTrie(it)
}
func (sdb *builder) buildStorageDiffsIncremental(oldSR common.Hash, newSR common.Hash) ([]StorageDiff, error) {
func (sdb *builder) buildStorageNodesIncremental(oldSR common.Hash, newSR common.Hash) ([]StorageNode, error) {
log.Debug("Storage Roots for Incremental Diff", "old", oldSR.Hex(), "new", newSR.Hex())
stateCache := sdb.blockChain.StateCache()
@ -266,11 +283,11 @@ func (sdb *builder) buildStorageDiffsIncremental(oldSR common.Hash, newSR common
oldIt := oldTrie.NodeIterator(make([]byte, 0))
newIt := newTrie.NodeIterator(make([]byte, 0))
it, _ := trie.NewDifferenceIterator(oldIt, newIt)
return sdb.buildStorageDiffsFromTrie(it)
return sdb.buildStorageNodesFromTrie(it)
}
func (sdb *builder) buildStorageDiffsFromTrie(it trie.NodeIterator) ([]StorageDiff, error) {
storageDiffs := make([]StorageDiff, 0)
func (sdb *builder) buildStorageNodesFromTrie(it trie.NodeIterator) ([]StorageNode, error) {
storageDiffs := make([]StorageNode, 0)
for it.Next(true) {
// skip value nodes
if it.Leaf() {
@ -299,7 +316,7 @@ func (sdb *builder) buildStorageDiffsFromTrie(it trie.NodeIterator) ([]StorageDi
valueNodePath := append(nodePath, partialPath...)
encodedPath := trie.HexToCompact(valueNodePath)
leafKey := encodedPath[1:]
sd := StorageDiff{
sd := StorageNode{
NodeType: ty,
Path: nodePath,
NodeValue: node,
@ -308,7 +325,7 @@ func (sdb *builder) buildStorageDiffsFromTrie(it trie.NodeIterator) ([]StorageDi
storageDiffs = append(storageDiffs, sd)
case Extension, Branch:
if sdb.config.IntermediateNodes {
storageDiffs = append(storageDiffs, StorageDiff{
storageDiffs = append(storageDiffs, StorageNode{
NodeType: ty,
Path: nodePath,
NodeValue: node,

View File

@ -34,8 +34,8 @@ import (
// TODO: add test that filters on address
var (
contractLeafKey []byte
emptyAccounts = make([]statediff.AccountDiff, 0)
emptyStorage = make([]statediff.StorageDiff, 0)
emptyAccounts = make([]statediff.StateNode, 0)
emptyStorage = make([]statediff.StorageNode, 0)
block0, block1, block2, block3 *types.Block
builder statediff.Builder
miningReward = int64(2000000000000000000)
@ -300,11 +300,11 @@ func TestBuilder(t *testing.T) {
blockHash: block0.Hash(),
},
&statediff.StateDiff{
BlockNumber: block0.Number(),
BlockHash: block0.Hash(),
CreatedAccounts: emptyAccounts,
DeletedAccounts: emptyAccounts,
UpdatedAccounts: emptyAccounts,
BlockNumber: block0.Number(),
BlockHash: block0.Hash(),
CreatedNodes: emptyAccounts,
DeletedNodes: emptyAccounts,
UpdatedNodes: emptyAccounts,
},
},
{
@ -319,17 +319,17 @@ func TestBuilder(t *testing.T) {
&statediff.StateDiff{
BlockNumber: block0.Number(),
BlockHash: block0.Hash(),
CreatedAccounts: []statediff.AccountDiff{
CreatedNodes: []statediff.StateNode{
{
Path: []byte{},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock0LeafNode,
Storage: emptyStorage,
Path: []byte{},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock0LeafNode,
StorageDiffs: emptyStorage,
},
},
DeletedAccounts: emptyAccounts,
UpdatedAccounts: emptyAccounts,
DeletedNodes: emptyAccounts,
UpdatedNodes: emptyAccounts,
},
},
{
@ -344,39 +344,39 @@ func TestBuilder(t *testing.T) {
&statediff.StateDiff{
BlockNumber: block1.Number(),
BlockHash: block1.Hash(),
CreatedAccounts: []statediff.AccountDiff{
CreatedNodes: []statediff.StateNode{
{
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock1LeafNode,
Storage: emptyStorage,
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock1LeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x05'},
NodeType: statediff.Leaf,
LeafKey: minerLeafKey,
NodeValue: minerAccountAtBlock1LeafNode,
Storage: emptyStorage,
Path: []byte{'\x05'},
NodeType: statediff.Leaf,
LeafKey: minerLeafKey,
NodeValue: minerAccountAtBlock1LeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1AtBlock1LeafNode,
Storage: emptyStorage,
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1AtBlock1LeafNode,
StorageDiffs: emptyStorage,
},
},
DeletedAccounts: []statediff.AccountDiff{ // This leaf appears to be deleted since it is turned into a branch node
DeletedNodes: []statediff.StateNode{ // This leaf appears to be deleted since it is turned into a branch node and the account is moved to \x00
{ // It would instead show up in the UpdateAccounts as new branch node IF intermediate node diffing was turned on (as it is in the test below)
Path: []byte{},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock0LeafNode,
Storage: emptyStorage,
Path: []byte{},
NodeType: statediff.Removed,
LeafKey: testhelpers.BankLeafKey,
NodeValue: []byte{},
StorageDiffs: emptyStorage,
},
},
UpdatedAccounts: emptyAccounts,
UpdatedNodes: emptyAccounts,
},
},
{
@ -393,13 +393,13 @@ func TestBuilder(t *testing.T) {
&statediff.StateDiff{
BlockNumber: block2.Number(),
BlockHash: block2.Hash(),
CreatedAccounts: []statediff.AccountDiff{
CreatedNodes: []statediff.StateNode{
{
Path: []byte{'\x06'},
NodeType: statediff.Leaf,
LeafKey: contractLeafKey,
NodeValue: contractAccountAtBlock2LeafNode,
Storage: []statediff.StorageDiff{
StorageDiffs: []statediff.StorageNode{
{
Path: []byte{},
NodeType: statediff.Leaf,
@ -409,35 +409,35 @@ func TestBuilder(t *testing.T) {
},
},
{
Path: []byte{'\x0c'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account2LeafKey,
NodeValue: account2AtBlock2LeafNode,
Storage: emptyStorage,
Path: []byte{'\x0c'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account2LeafKey,
NodeValue: account2AtBlock2LeafNode,
StorageDiffs: emptyStorage,
},
},
DeletedAccounts: emptyAccounts,
UpdatedAccounts: []statediff.AccountDiff{
DeletedNodes: emptyAccounts,
UpdatedNodes: []statediff.StateNode{
{
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock2LeafNode,
Storage: emptyStorage,
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock2LeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x05'},
NodeType: statediff.Leaf,
LeafKey: minerLeafKey,
NodeValue: minerAccountAtBlock2LeafNode,
Storage: emptyStorage,
Path: []byte{'\x05'},
NodeType: statediff.Leaf,
LeafKey: minerLeafKey,
NodeValue: minerAccountAtBlock2LeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1AtBlock2LeafNode,
Storage: emptyStorage,
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1AtBlock2LeafNode,
StorageDiffs: emptyStorage,
},
},
},
@ -453,24 +453,24 @@ func TestBuilder(t *testing.T) {
blockHash: block3.Hash(),
},
&statediff.StateDiff{
BlockNumber: block3.Number(),
BlockHash: block3.Hash(),
CreatedAccounts: []statediff.AccountDiff{},
DeletedAccounts: emptyAccounts,
UpdatedAccounts: []statediff.AccountDiff{
BlockNumber: block3.Number(),
BlockHash: block3.Hash(),
CreatedNodes: []statediff.StateNode{},
DeletedNodes: emptyAccounts,
UpdatedNodes: []statediff.StateNode{
{
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock3LeafNode,
Storage: emptyStorage,
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock3LeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x06'},
NodeType: statediff.Leaf,
LeafKey: contractLeafKey,
NodeValue: contractAccountAtBlock3LeafNode,
Storage: []statediff.StorageDiff{
StorageDiffs: []statediff.StorageNode{
{
Path: []byte{'\x02'},
NodeType: statediff.Leaf,
@ -486,11 +486,11 @@ func TestBuilder(t *testing.T) {
},
},
{
Path: []byte{'\x0c'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account2LeafKey,
NodeValue: account2AtBlock3LeafNode,
Storage: emptyStorage,
Path: []byte{'\x0c'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account2LeafKey,
NodeValue: account2AtBlock3LeafNode,
StorageDiffs: emptyStorage,
},
},
},
@ -547,11 +547,11 @@ func TestBuilderWithIntermediateNodes(t *testing.T) {
blockHash: block0.Hash(),
},
&statediff.StateDiff{
BlockNumber: block0.Number(),
BlockHash: block0.Hash(),
CreatedAccounts: emptyAccounts,
DeletedAccounts: emptyAccounts,
UpdatedAccounts: emptyAccounts,
BlockNumber: block0.Number(),
BlockHash: block0.Hash(),
CreatedNodes: emptyAccounts,
DeletedNodes: emptyAccounts,
UpdatedNodes: emptyAccounts,
},
},
{
@ -566,17 +566,17 @@ func TestBuilderWithIntermediateNodes(t *testing.T) {
&statediff.StateDiff{
BlockNumber: block0.Number(),
BlockHash: block0.Hash(),
CreatedAccounts: []statediff.AccountDiff{
CreatedNodes: []statediff.StateNode{
{
Path: []byte{},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock0LeafNode,
Storage: emptyStorage,
Path: []byte{},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock0LeafNode,
StorageDiffs: emptyStorage,
},
},
DeletedAccounts: emptyAccounts,
UpdatedAccounts: emptyAccounts,
DeletedNodes: emptyAccounts,
UpdatedNodes: emptyAccounts,
},
},
{
@ -591,36 +591,36 @@ func TestBuilderWithIntermediateNodes(t *testing.T) {
&statediff.StateDiff{
BlockNumber: block1.Number(),
BlockHash: block1.Hash(),
CreatedAccounts: []statediff.AccountDiff{
CreatedNodes: []statediff.StateNode{
{
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock1LeafNode,
Storage: emptyStorage,
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock1LeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x05'},
NodeType: statediff.Leaf,
LeafKey: minerLeafKey,
NodeValue: minerAccountAtBlock1LeafNode,
Storage: emptyStorage,
Path: []byte{'\x05'},
NodeType: statediff.Leaf,
LeafKey: minerLeafKey,
NodeValue: minerAccountAtBlock1LeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1AtBlock1LeafNode,
Storage: emptyStorage,
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1AtBlock1LeafNode,
StorageDiffs: emptyStorage,
},
},
DeletedAccounts: emptyAccounts,
UpdatedAccounts: []statediff.AccountDiff{
DeletedNodes: emptyAccounts,
UpdatedNodes: []statediff.StateNode{
{
Path: []byte{},
NodeType: statediff.Branch,
NodeValue: block1BranchNode,
Storage: emptyStorage,
Path: []byte{},
NodeType: statediff.Branch,
NodeValue: block1BranchNode,
StorageDiffs: emptyStorage,
},
},
},
@ -639,13 +639,13 @@ func TestBuilderWithIntermediateNodes(t *testing.T) {
&statediff.StateDiff{
BlockNumber: block2.Number(),
BlockHash: block2.Hash(),
CreatedAccounts: []statediff.AccountDiff{
CreatedNodes: []statediff.StateNode{
{
Path: []byte{'\x06'},
NodeType: statediff.Leaf,
LeafKey: contractLeafKey,
NodeValue: contractAccountAtBlock2LeafNode,
Storage: []statediff.StorageDiff{
StorageDiffs: []statediff.StorageNode{
{
Path: []byte{},
NodeType: statediff.Leaf,
@ -655,41 +655,41 @@ func TestBuilderWithIntermediateNodes(t *testing.T) {
},
},
{
Path: []byte{'\x0c'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account2LeafKey,
NodeValue: account2AtBlock2LeafNode,
Storage: emptyStorage,
Path: []byte{'\x0c'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account2LeafKey,
NodeValue: account2AtBlock2LeafNode,
StorageDiffs: emptyStorage,
},
},
DeletedAccounts: emptyAccounts,
UpdatedAccounts: []statediff.AccountDiff{
DeletedNodes: emptyAccounts,
UpdatedNodes: []statediff.StateNode{
{
Path: []byte{},
NodeType: statediff.Branch,
NodeValue: block2BranchNode,
Storage: emptyStorage,
Path: []byte{},
NodeType: statediff.Branch,
NodeValue: block2BranchNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock2LeafNode,
Storage: emptyStorage,
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock2LeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x05'},
NodeType: statediff.Leaf,
LeafKey: minerLeafKey,
NodeValue: minerAccountAtBlock2LeafNode,
Storage: emptyStorage,
Path: []byte{'\x05'},
NodeType: statediff.Leaf,
LeafKey: minerLeafKey,
NodeValue: minerAccountAtBlock2LeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1AtBlock2LeafNode,
Storage: emptyStorage,
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1AtBlock2LeafNode,
StorageDiffs: emptyStorage,
},
},
},
@ -705,30 +705,30 @@ func TestBuilderWithIntermediateNodes(t *testing.T) {
blockHash: block3.Hash(),
},
&statediff.StateDiff{
BlockNumber: block3.Number(),
BlockHash: block3.Hash(),
CreatedAccounts: []statediff.AccountDiff{},
DeletedAccounts: emptyAccounts,
UpdatedAccounts: []statediff.AccountDiff{
BlockNumber: block3.Number(),
BlockHash: block3.Hash(),
CreatedNodes: []statediff.StateNode{},
DeletedNodes: emptyAccounts,
UpdatedNodes: []statediff.StateNode{
{
Path: []byte{},
NodeType: statediff.Branch,
NodeValue: block3BranchNode,
Storage: emptyStorage,
Path: []byte{},
NodeType: statediff.Branch,
NodeValue: block3BranchNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock3LeafNode,
Storage: emptyStorage,
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock3LeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x06'},
NodeType: statediff.Leaf,
LeafKey: contractLeafKey,
NodeValue: contractAccountAtBlock3LeafNode,
Storage: []statediff.StorageDiff{
StorageDiffs: []statediff.StorageNode{
{
Path: []byte{},
NodeType: statediff.Branch,
@ -749,11 +749,11 @@ func TestBuilderWithIntermediateNodes(t *testing.T) {
},
},
{
Path: []byte{'\x0c'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account2LeafKey,
NodeValue: account2AtBlock3LeafNode,
Storage: emptyStorage,
Path: []byte{'\x0c'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account2LeafKey,
NodeValue: account2AtBlock3LeafNode,
StorageDiffs: emptyStorage,
},
},
},
@ -811,11 +811,11 @@ func TestBuilderWithWatchedAddressList(t *testing.T) {
blockHash: block0.Hash(),
},
&statediff.StateDiff{
BlockNumber: block0.Number(),
BlockHash: block0.Hash(),
CreatedAccounts: emptyAccounts,
DeletedAccounts: emptyAccounts,
UpdatedAccounts: emptyAccounts,
BlockNumber: block0.Number(),
BlockHash: block0.Hash(),
CreatedNodes: emptyAccounts,
DeletedNodes: emptyAccounts,
UpdatedNodes: emptyAccounts,
},
},
{
@ -828,11 +828,11 @@ func TestBuilderWithWatchedAddressList(t *testing.T) {
blockHash: block0.Hash(),
},
&statediff.StateDiff{
BlockNumber: block0.Number(),
BlockHash: block0.Hash(),
CreatedAccounts: emptyAccounts,
DeletedAccounts: emptyAccounts,
UpdatedAccounts: emptyAccounts,
BlockNumber: block0.Number(),
BlockHash: block0.Hash(),
CreatedNodes: emptyAccounts,
DeletedNodes: emptyAccounts,
UpdatedNodes: emptyAccounts,
},
},
{
@ -847,17 +847,17 @@ func TestBuilderWithWatchedAddressList(t *testing.T) {
&statediff.StateDiff{
BlockNumber: block1.Number(),
BlockHash: block1.Hash(),
CreatedAccounts: []statediff.AccountDiff{
CreatedNodes: []statediff.StateNode{
{
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1AtBlock1LeafNode,
Storage: emptyStorage,
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1AtBlock1LeafNode,
StorageDiffs: emptyStorage,
},
},
DeletedAccounts: emptyAccounts,
UpdatedAccounts: []statediff.AccountDiff{},
DeletedNodes: emptyAccounts,
UpdatedNodes: []statediff.StateNode{},
},
},
{
@ -873,13 +873,13 @@ func TestBuilderWithWatchedAddressList(t *testing.T) {
&statediff.StateDiff{
BlockNumber: block2.Number(),
BlockHash: block2.Hash(),
CreatedAccounts: []statediff.AccountDiff{
CreatedNodes: []statediff.StateNode{
{
Path: []byte{'\x06'},
NodeType: statediff.Leaf,
LeafKey: contractLeafKey,
NodeValue: contractAccountAtBlock2LeafNode,
Storage: []statediff.StorageDiff{
StorageDiffs: []statediff.StorageNode{
{
Path: []byte{},
NodeType: statediff.Leaf,
@ -889,14 +889,14 @@ func TestBuilderWithWatchedAddressList(t *testing.T) {
},
},
},
DeletedAccounts: emptyAccounts,
UpdatedAccounts: []statediff.AccountDiff{
DeletedNodes: emptyAccounts,
UpdatedNodes: []statediff.StateNode{
{
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1AtBlock2LeafNode,
Storage: emptyStorage,
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1AtBlock2LeafNode,
StorageDiffs: emptyStorage,
},
},
},
@ -912,17 +912,17 @@ func TestBuilderWithWatchedAddressList(t *testing.T) {
blockHash: block3.Hash(),
},
&statediff.StateDiff{
BlockNumber: block3.Number(),
BlockHash: block3.Hash(),
CreatedAccounts: []statediff.AccountDiff{},
DeletedAccounts: emptyAccounts,
UpdatedAccounts: []statediff.AccountDiff{
BlockNumber: block3.Number(),
BlockHash: block3.Hash(),
CreatedNodes: []statediff.StateNode{},
DeletedNodes: emptyAccounts,
UpdatedNodes: []statediff.StateNode{
{
Path: []byte{'\x06'},
NodeType: statediff.Leaf,
LeafKey: contractLeafKey,
NodeValue: contractAccountAtBlock3LeafNode,
Storage: []statediff.StorageDiff{
StorageDiffs: []statediff.StorageNode{
{
Path: []byte{'\x02'},
NodeType: statediff.Leaf,

View File

@ -26,7 +26,7 @@ import (
)
func sortKeys(data AccountsMap) []string {
var keys []string
keys := make([]string, 0, len(data))
for key := range data {
keys = append(keys, key.Hex())
}
@ -35,7 +35,8 @@ func sortKeys(data AccountsMap) []string {
return keys
}
// findIntersection finds the set of strings from both arrays that are equivalent (same key as same index)
// findIntersection finds the set of strings from both arrays that are equivalent
// a and b must first be sorted
// this is used to find which keys have been both "deleted" and "created" i.e. they were updated
func findIntersection(a, b []string) []string {
lenA := len(a)

View File

@ -47,8 +47,8 @@ var (
block1CoinbaseAddr, block2CoinbaseAddr, block3CoinbaseAddr common.Address
block1CoinbaseHash, block2CoinbaseHash, block3CoinbaseHash common.Hash
builder statediff.Builder
emptyAccounts = make([]statediff.AccountDiff, 0)
emptyStorage = make([]statediff.StorageDiff, 0)
emptyAccounts = make([]statediff.StateNode, 0)
emptyStorage = make([]statediff.StorageNode, 0)
// block 1 data
block1CoinbaseAccount, _ = rlp.EncodeToBytes(state.Account{
@ -498,34 +498,34 @@ func TestBuilderOnMainnetBlocks(t *testing.T) {
&statediff.StateDiff{
BlockNumber: block1.Number(),
BlockHash: block1.Hash(),
CreatedAccounts: []statediff.AccountDiff{
CreatedNodes: []statediff.StateNode{
{
Path: []byte{'\x04', '\x0b', '\x0e'},
NodeType: statediff.Leaf,
LeafKey: block1CoinbaseHash.Bytes(),
NodeValue: block1CoinbaseLeafNode,
Storage: emptyStorage,
Path: []byte{'\x04', '\x0b', '\x0e'},
NodeType: statediff.Leaf,
LeafKey: block1CoinbaseHash.Bytes(),
NodeValue: block1CoinbaseLeafNode,
StorageDiffs: emptyStorage,
},
},
DeletedAccounts: emptyAccounts,
UpdatedAccounts: []statediff.AccountDiff{
DeletedNodes: emptyAccounts,
UpdatedNodes: []statediff.StateNode{
{
Path: []byte{},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block1RootBranchNode,
Path: []byte{},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block1RootBranchNode,
},
{
Path: []byte{'\x04'},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block1x04BranchNode,
Path: []byte{'\x04'},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block1x04BranchNode,
},
{
Path: []byte{'\x04', '\x0b'},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block1x040bBranchNode,
Path: []byte{'\x04', '\x0b'},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block1x040bBranchNode,
},
},
},
@ -544,50 +544,50 @@ func TestBuilderOnMainnetBlocks(t *testing.T) {
&statediff.StateDiff{
BlockNumber: block2.Number(),
BlockHash: block2.Hash(),
CreatedAccounts: []statediff.AccountDiff{
// this new leaf at x00 x08 x0d x00 was created when a premine account (leaf) was moved from path x00 x08 x0d
CreatedNodes: []statediff.StateNode{
// this new leaf at x00 x08 x0d x00 was "created" when a premine account (leaf) was moved from path x00 x08 x0d
// this occurred because of the creation of the new coinbase receiving account (leaf) at x00 x08 x0d x04
// which necessitates we create a branch at x00 x08 x0d (as shown in the below UpdateAccounts)
{
Path: []byte{'\x00', '\x08', '\x0d', '\x00'},
NodeType: statediff.Leaf,
Storage: emptyStorage,
LeafKey: common.HexToHash("08d0f2e24db7943eab4415f99e109698863b0fecca1cf9ffc500f38cefbbe29e").Bytes(),
NodeValue: block2MovedPremineLeafNode,
Path: []byte{'\x00', '\x08', '\x0d', '\x00'},
NodeType: statediff.Leaf,
StorageDiffs: emptyStorage,
LeafKey: common.HexToHash("08d0f2e24db7943eab4415f99e109698863b0fecca1cf9ffc500f38cefbbe29e").Bytes(),
NodeValue: block2MovedPremineLeafNode,
},
{
Path: []byte{'\x00', '\x08', '\x0d', '\x04'},
NodeType: statediff.Leaf,
Storage: emptyStorage,
LeafKey: block2CoinbaseHash.Bytes(),
NodeValue: block2CoinbaseLeafNode,
Path: []byte{'\x00', '\x08', '\x0d', '\x04'},
NodeType: statediff.Leaf,
StorageDiffs: emptyStorage,
LeafKey: block2CoinbaseHash.Bytes(),
NodeValue: block2CoinbaseLeafNode,
},
},
DeletedAccounts: emptyAccounts,
UpdatedAccounts: []statediff.AccountDiff{
DeletedNodes: emptyAccounts,
UpdatedNodes: []statediff.StateNode{
{
Path: []byte{},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block2RootBranchNode,
Path: []byte{},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block2RootBranchNode,
},
{
Path: []byte{'\x00'},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block2x00BranchNode,
Path: []byte{'\x00'},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block2x00BranchNode,
},
{
Path: []byte{'\x00', '\x08'},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block2x0008BranchNode,
Path: []byte{'\x00', '\x08'},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block2x0008BranchNode,
},
{
Path: []byte{'\x00', '\x08', '\x0d'},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block2x00080dBranchNode,
Path: []byte{'\x00', '\x08', '\x0d'},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block2x00080dBranchNode,
},
},
},
@ -605,72 +605,72 @@ func TestBuilderOnMainnetBlocks(t *testing.T) {
&statediff.StateDiff{
BlockNumber: block3.Number(),
BlockHash: block3.Hash(),
CreatedAccounts: []statediff.AccountDiff{
CreatedNodes: []statediff.StateNode{
{ // How was this account created???
Path: []byte{'\x0c', '\x0e', '\x05', '\x07', '\x03'},
NodeType: statediff.Leaf,
Storage: emptyStorage,
LeafKey: common.HexToHash("ce573ced93917e658d10e2d9009470dad72b63c898d173721194a12f2ae5e190").Bytes(),
NodeValue: block3MovedPremineLeafNode1,
Path: []byte{'\x0c', '\x0e', '\x05', '\x07', '\x03'},
NodeType: statediff.Leaf,
StorageDiffs: emptyStorage,
LeafKey: common.HexToHash("ce573ced93917e658d10e2d9009470dad72b63c898d173721194a12f2ae5e190").Bytes(),
NodeValue: block3MovedPremineLeafNode1,
},
{ // This account (leaf) used to be at 0c 0e 05 07, not sure why it moves...
Path: []byte{'\x0c', '\x0e', '\x05', '\x07', '\x08'},
NodeType: statediff.Leaf,
Storage: emptyStorage,
LeafKey: common.HexToHash("ce5783bc1e69eedf90f402e11f6862da14ed8e50156635a04d6393bbae154012").Bytes(),
NodeValue: block3MovedPremineLeafNode2,
Path: []byte{'\x0c', '\x0e', '\x05', '\x07', '\x08'},
NodeType: statediff.Leaf,
StorageDiffs: emptyStorage,
LeafKey: common.HexToHash("ce5783bc1e69eedf90f402e11f6862da14ed8e50156635a04d6393bbae154012").Bytes(),
NodeValue: block3MovedPremineLeafNode2,
},
{ // this is the new account created due to the coinbase mining a block, it's creation shouldn't affect 0x 0e 05 07
Path: []byte{'\x06', '\x0e', '\x0f'},
NodeType: statediff.Leaf,
Storage: emptyStorage,
LeafKey: block3CoinbaseHash.Bytes(),
NodeValue: block3CoinbaseLeafNode,
Path: []byte{'\x06', '\x0e', '\x0f'},
NodeType: statediff.Leaf,
StorageDiffs: emptyStorage,
LeafKey: block3CoinbaseHash.Bytes(),
NodeValue: block3CoinbaseLeafNode,
},
},
DeletedAccounts: emptyAccounts,
UpdatedAccounts: []statediff.AccountDiff{
DeletedNodes: emptyAccounts,
UpdatedNodes: []statediff.StateNode{
{
Path: []byte{},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block3RootBranchNode,
Path: []byte{},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block3RootBranchNode,
},
{
Path: []byte{'\x06'},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block3x06BranchNode,
Path: []byte{'\x06'},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block3x06BranchNode,
},
{
Path: []byte{'\x06', '\x0e'},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block3x060eBranchNode,
Path: []byte{'\x06', '\x0e'},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block3x060eBranchNode,
},
{
Path: []byte{'\x0c'},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block3x0cBranchNode,
Path: []byte{'\x0c'},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block3x0cBranchNode,
},
{
Path: []byte{'\x0c', '\x0e'},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block3x0c0eBranchNode,
Path: []byte{'\x0c', '\x0e'},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block3x0c0eBranchNode,
},
{
Path: []byte{'\x0c', '\x0e', '\x05'},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block3x0c0e05BranchNode,
Path: []byte{'\x0c', '\x0e', '\x05'},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block3x0c0e05BranchNode,
},
{
Path: []byte{'\x0c', '\x0e', '\x05', '\x07'},
NodeType: statediff.Branch,
Storage: emptyStorage,
NodeValue: block3x0c0e0507BranchNode,
Path: []byte{'\x0c', '\x0e', '\x05', '\x07'},
NodeType: statediff.Branch,
StorageDiffs: emptyStorage,
NodeValue: block3x0c0e0507BranchNode,
},
},
},

View File

@ -33,12 +33,12 @@ import (
)
var (
emptyStorage = make([]statediff.StorageDiff, 0)
emptyAccounts = make([]statediff.AccountDiff, 0)
block0, block1 *types.Block
minerLeafKey = testhelpers.AddressToLeafKey(common.HexToAddress("0x0"))
emptyAccountDiffEventualMap = make([]statediff.AccountDiff, 0)
account1, _ = rlp.EncodeToBytes(state.Account{
emptyStorage = make([]statediff.StorageNode, 0)
emptyAccounts = make([]statediff.StateNode, 0)
block0, block1 *types.Block
minerLeafKey = testhelpers.AddressToLeafKey(common.HexToAddress("0x0"))
emptyStateNodeEventualMap = make([]statediff.StateNode, 0)
account1, _ = rlp.EncodeToBytes(state.Account{
Nonce: uint64(0),
Balance: big.NewInt(10000),
CodeHash: common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").Bytes(),
@ -102,39 +102,39 @@ func testSubscriptionAPI(t *testing.T) {
expectedStateDiff := statediff.StateDiff{
BlockNumber: block1.Number(),
BlockHash: block1.Hash(),
CreatedAccounts: []statediff.AccountDiff{
CreatedNodes: []statediff.StateNode{
{
Path: []byte{'\x05'},
NodeType: statediff.Leaf,
LeafKey: minerLeafKey,
NodeValue: minerAccountLeafNode,
Storage: emptyStorage,
Path: []byte{'\x05'},
NodeType: statediff.Leaf,
LeafKey: minerLeafKey,
NodeValue: minerAccountLeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1LeafNode,
Storage: emptyStorage,
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1LeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountLeafNode,
Storage: emptyStorage,
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountLeafNode,
StorageDiffs: emptyStorage,
},
},
DeletedAccounts: []statediff.AccountDiff{ // This leaf appears to be deleted since it is turned into a branch node
DeletedNodes: []statediff.StateNode{ // This leaf appears to be deleted since it is turned into a branch node
{ // It would instead show up in the UpdateAccounts as new branch node IF intermediate node diffing was turned on (as it is in the test below)
Path: []byte{},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock0LeafNode,
Storage: emptyStorage,
Path: []byte{},
NodeType: statediff.Removed,
LeafKey: testhelpers.BankLeafKey,
NodeValue: []byte{},
StorageDiffs: emptyStorage,
},
},
UpdatedAccounts: emptyAccounts,
UpdatedNodes: emptyAccounts,
}
expectedStateDiffBytes, _ := rlp.EncodeToBytes(expectedStateDiff)
blockChan := make(chan *types.Block)
@ -201,39 +201,39 @@ func testHTTPAPI(t *testing.T) {
expectedStateDiff := statediff.StateDiff{
BlockNumber: block1.Number(),
BlockHash: block1.Hash(),
CreatedAccounts: []statediff.AccountDiff{
CreatedNodes: []statediff.StateNode{
{
Path: []byte{'\x05'},
NodeType: statediff.Leaf,
LeafKey: minerLeafKey,
NodeValue: minerAccountLeafNode,
Storage: emptyStorage,
Path: []byte{'\x05'},
NodeType: statediff.Leaf,
LeafKey: minerLeafKey,
NodeValue: minerAccountLeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1LeafNode,
Storage: emptyStorage,
Path: []byte{'\x0e'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.Account1LeafKey,
NodeValue: account1LeafNode,
StorageDiffs: emptyStorage,
},
{
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountLeafNode,
Storage: emptyStorage,
Path: []byte{'\x00'},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountLeafNode,
StorageDiffs: emptyStorage,
},
},
DeletedAccounts: []statediff.AccountDiff{ // This leaf appears to be deleted since it is turned into a branch node
DeletedNodes: []statediff.StateNode{ // This leaf appears to be deleted since it is turned into a branch node
{ // It would instead show up in the UpdateAccounts as new branch node IF intermediate node diffing was turned on (as it is in the test below)
Path: []byte{},
NodeType: statediff.Leaf,
LeafKey: testhelpers.BankLeafKey,
NodeValue: bankAccountAtBlock0LeafNode,
Storage: emptyStorage,
Path: []byte{},
NodeType: statediff.Removed,
LeafKey: testhelpers.BankLeafKey,
NodeValue: []byte{},
StorageDiffs: emptyStorage,
},
},
UpdatedAccounts: emptyAccounts,
UpdatedNodes: emptyAccounts,
}
expectedStateDiffBytes, _ := rlp.EncodeToBytes(expectedStateDiff)
config := statediff.Config{

View File

@ -65,27 +65,27 @@ func (sd *Payload) Encode() ([]byte, error) {
// StateDiff is the final output structure from the builder
type StateDiff struct {
BlockNumber *big.Int `json:"blockNumber" gencodec:"required"`
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
CreatedAccounts []AccountDiff `json:"createdAccounts" gencodec:"required"`
DeletedAccounts []AccountDiff `json:"deletedAccounts" gencodec:"required"`
UpdatedAccounts []AccountDiff `json:"updatedAccounts" gencodec:"required"`
BlockNumber *big.Int `json:"blockNumber" gencodec:"required"`
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
CreatedNodes []StateNode `json:"createdAccounts" gencodec:"required"`
DeletedNodes []StateNode `json:"deletedAccounts" gencodec:"required"`
UpdatedNodes []StateNode `json:"updatedAccounts" gencodec:"required"`
encoded []byte
err error
}
// AccountDiff holds the data for a single state diff node
type AccountDiff struct {
NodeType NodeType `json:"nodeType" gencodec:"required"`
Path []byte `json:"path" gencodec:"required"`
NodeValue []byte `json:"value" gencodec:"required"`
Storage []StorageDiff `json:"storage"`
LeafKey []byte `json:"leafKey"`
// StateNode holds the data for a single state diff node
type StateNode struct {
NodeType NodeType `json:"nodeType" gencodec:"required"`
Path []byte `json:"path" gencodec:"required"`
NodeValue []byte `json:"value" gencodec:"required"`
StorageDiffs []StorageNode `json:"storage"`
LeafKey []byte `json:"leafKey"`
}
// StorageDiff holds the data for a single storage diff node
type StorageDiff struct {
// StorageNode holds the data for a single storage diff node
type StorageNode struct {
NodeType NodeType `json:"nodeType" gencodec:"required"`
Path []byte `json:"path" gencodec:"required"`
NodeValue []byte `json:"value" gencodec:"required"`
@ -112,4 +112,5 @@ const (
Leaf NodeType = "Leaf"
Extension NodeType = "Extension"
Branch NodeType = "Branch"
Removed NodeType = "Removed" // used to represent nodes which have been deleted (e.g. accounts due to EIp-158)
)