Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

En 6407 trie package unit tests #1737

Merged
merged 16 commits into from
May 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cmd/node/config/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
MaxOpenFiles = 10

[TrieStorageManagerConfig]
PruningBufferLen = 1000
PruningBufferLen = 100000
SnapshotsBufferLen = 1000000
MaxSnapshots = 2

Expand Down Expand Up @@ -397,6 +397,8 @@
CheckpointRoundsModulus = 100
AccountsStatePruningEnabled = true
PeerStatePruningEnabled = true
MaxStateTrieLevelInMemory = 5
MaxPeerTrieLevelInMemory = 5

[BlockSizeThrottleConfig]
MinSizeInBytes = 104857 # 104857 is 10% from 1MB
Expand Down
2 changes: 2 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ type StateTriesConfig struct {
CheckpointRoundsModulus uint
AccountsStatePruningEnabled bool
PeerStatePruningEnabled bool
MaxStateTrieLevelInMemory uint
MaxPeerTrieLevelInMemory uint
}

// TrieStorageManagerConfig will hold config information about trie storage manager
Expand Down
2 changes: 1 addition & 1 deletion data/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ type StorageManager interface {

// TrieFactory creates new tries
type TrieFactory interface {
Create(config.StorageConfig, string, bool) (StorageManager, Trie, error)
Create(config.StorageConfig, string, bool, uint) (StorageManager, Trie, error)
IsInterfaceNil() bool
}

Expand Down
3 changes: 2 additions & 1 deletion data/state/accountsDB_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,8 @@ func TestAccountsDB_RevertToSnapshotShouldWork(t *testing.T) {
hsh := mock.HasherMock{}
accFactory := factory.NewAccountCreator()
storageManager, _ := trie.NewTrieStorageManagerWithoutPruning(mock.NewMemDbMock())
tr, _ := trie.NewTrie(storageManager, marsh, hsh)
maxTrieLevelInMemory := uint(5)
tr, _ := trie.NewTrie(storageManager, marsh, hsh, maxTrieLevelInMemory)

adb, _ := state.NewAccountsDB(tr, hsh, marsh, accFactory)

Expand Down
38 changes: 20 additions & 18 deletions data/syncer/baseAccountsSyncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,31 @@ import (
)

type baseAccountsSyncer struct {
hasher hashing.Hasher
marshalizer marshal.Marshalizer
trieSyncers map[string]data.TrieSyncer
dataTries map[string]data.Trie
mutex sync.Mutex
trieStorageManager data.StorageManager
requestHandler trie.RequestHandler
waitTime time.Duration
shardId uint32
cacher storage.Cacher
rootHash []byte
hasher hashing.Hasher
marshalizer marshal.Marshalizer
trieSyncers map[string]data.TrieSyncer
dataTries map[string]data.Trie
mutex sync.Mutex
trieStorageManager data.StorageManager
requestHandler trie.RequestHandler
waitTime time.Duration
shardId uint32
miiu96 marked this conversation as resolved.
Show resolved Hide resolved
cacher storage.Cacher
rootHash []byte
maxTrieLevelInMemory uint
}

const minWaitTime = time.Second

// ArgsNewBaseAccountsSyncer defines the arguments needed for the new account syncer
type ArgsNewBaseAccountsSyncer struct {
Hasher hashing.Hasher
Marshalizer marshal.Marshalizer
TrieStorageManager data.StorageManager
RequestHandler trie.RequestHandler
WaitTime time.Duration
Cacher storage.Cacher
Hasher hashing.Hasher
Marshalizer marshal.Marshalizer
TrieStorageManager data.StorageManager
RequestHandler trie.RequestHandler
WaitTime time.Duration
Cacher storage.Cacher
MaxTrieLevelInMemory uint
}

func checkArgs(args ArgsNewBaseAccountsSyncer) error {
Expand Down Expand Up @@ -67,7 +69,7 @@ func checkArgs(args ArgsNewBaseAccountsSyncer) error {
func (b *baseAccountsSyncer) syncMainTrie(rootHash []byte, trieTopic string, ctx context.Context) error {
b.rootHash = rootHash

dataTrie, err := trie.NewTrie(b.trieStorageManager, b.marshalizer, b.hasher)
dataTrie, err := trie.NewTrie(b.trieStorageManager, b.marshalizer, b.hasher, b.maxTrieLevelInMemory)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion data/syncer/userAccountsSyncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (u *userAccountsSyncer) SyncAccounts(rootHash []byte) error {

func (u *userAccountsSyncer) syncAccountDataTries(rootHashes [][]byte, ctx context.Context) error {
for _, rootHash := range rootHashes {
dataTrie, err := trie.NewTrie(u.trieStorageManager, u.marshalizer, u.hasher)
dataTrie, err := trie.NewTrie(u.trieStorageManager, u.marshalizer, u.hasher, u.maxTrieLevelInMemory)
if err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions data/trie/branchNode.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ func (bn *branchNode) hashNode() ([]byte, error) {
return encodeNodeAndGetHash(bn)
}

func (bn *branchNode) commit(force bool, level byte, originDb data.DBWriteCacher, targetDb data.DBWriteCacher) error {
func (bn *branchNode) commit(force bool, level byte, maxTrieLevelInMemory uint, originDb data.DBWriteCacher, targetDb data.DBWriteCacher) error {
level++
err := bn.isEmptyOrNil()
if err != nil {
Expand All @@ -264,7 +264,7 @@ func (bn *branchNode) commit(force bool, level byte, originDb data.DBWriteCacher
continue
}

err = bn.children[i].commit(force, level, originDb, targetDb)
err = bn.children[i].commit(force, level, maxTrieLevelInMemory, originDb, targetDb)
if err != nil {
return err
}
Expand All @@ -274,7 +274,7 @@ func (bn *branchNode) commit(force bool, level byte, originDb data.DBWriteCacher
if err != nil {
return err
}
if level == maxTrieLevelAfterCommit {
if uint(level) == maxTrieLevelInMemory {
var collapsed node
collapsed, err = bn.getCollapsed()
if err != nil {
Expand Down
153 changes: 140 additions & 13 deletions data/trie/branchNode_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package trie

import (
"bytes"
"encoding/hex"
"errors"
"fmt"
Expand Down Expand Up @@ -187,9 +188,10 @@ func TestBranchNode_setRootHash(t *testing.T) {
marsh, hsh := getTestMarshAndHasher()
trieStorage1, _ := NewTrieStorageManager(db, marsh, hsh, cfg, &mock.EvictionWaitingList{}, config.TrieStorageManagerConfig{})
trieStorage2, _ := NewTrieStorageManager(db, marsh, hsh, cfg, &mock.EvictionWaitingList{}, config.TrieStorageManagerConfig{})
maxTrieLevelInMemory := uint(5)

tr1, _ := NewTrie(trieStorage1, marsh, hsh)
tr2, _ := NewTrie(trieStorage2, marsh, hsh)
tr1, _ := NewTrie(trieStorage1, marsh, hsh, maxTrieLevelInMemory)
tr2, _ := NewTrie(trieStorage2, marsh, hsh, maxTrieLevelInMemory)

maxIterations := 10000
for i := 0; i < maxIterations; i++ {
Expand Down Expand Up @@ -348,7 +350,7 @@ func TestBranchNode_commit(t *testing.T) {
hash, _ := encodeNodeAndGetHash(collapsedBn)
_ = bn.setHash()

err := bn.commit(false, 0, db, db)
err := bn.commit(false, 0, 5, db, db)
assert.Nil(t, err)

encNode, _ := db.Get(hash)
Expand All @@ -363,7 +365,7 @@ func TestBranchNode_commitEmptyNode(t *testing.T) {

bn := emptyDirtyBranchNode()

err := bn.commit(false, 0, nil, nil)
err := bn.commit(false, 0, 5, nil, nil)
assert.True(t, errors.Is(err, ErrEmptyBranchNode))
}

Expand All @@ -372,7 +374,7 @@ func TestBranchNode_commitNilNode(t *testing.T) {

var bn *branchNode

err := bn.commit(false, 0, nil, nil)
err := bn.commit(false, 0, 5, nil, nil)
assert.True(t, errors.Is(err, ErrNilBranchNode))
}

Expand Down Expand Up @@ -417,7 +419,7 @@ func TestBranchNode_resolveCollapsed(t *testing.T) {
childPos := byte(2)

_ = bn.setHash()
_ = bn.commit(false, 0, db, db)
_ = bn.commit(false, 0, 5, db, db)
resolved, _ := newLeafNode([]byte("dog"), []byte("dog"), bn.marsh, bn.hasher)
resolved.dirty = false
resolved.hash = bn.EncodedChildren[childPos]
Expand Down Expand Up @@ -518,7 +520,7 @@ func TestBranchNode_tryGetCollapsedNode(t *testing.T) {
bn, collapsedBn := getBnAndCollapsedBn(getTestMarshAndHasher())

_ = bn.setHash()
_ = bn.commit(false, 0, db, db)
_ = bn.commit(false, 0, 5, db, db)

childPos := byte(2)
key := append([]byte{childPos}, []byte("dog")...)
Expand Down Expand Up @@ -644,7 +646,7 @@ func TestBranchNode_insertCollapsedNode(t *testing.T) {
node, _ := newLeafNode(key, []byte("dogs"), bn.marsh, bn.hasher)

_ = bn.setHash()
_ = bn.commit(false, 0, db, db)
_ = bn.commit(false, 0, 5, db, db)

dirty, newBn, _, err := collapsedBn.insert(node, db)
assert.True(t, dirty)
Expand All @@ -663,7 +665,7 @@ func TestBranchNode_insertInStoredBnOnExistingPos(t *testing.T) {
key := append([]byte{childPos}, []byte("dog")...)
node, _ := newLeafNode(key, []byte("dogs"), bn.marsh, bn.hasher)

_ = bn.commit(false, 0, db, db)
_ = bn.commit(false, 0, 5, db, db)
bnHash := bn.getHash()
ln, _, _ := bn.getNext(key, db)
lnHash := ln.getHash()
Expand All @@ -684,7 +686,7 @@ func TestBranchNode_insertInStoredBnOnNilPos(t *testing.T) {
key := append([]byte{nilChildPos}, []byte("dog")...)
node, _ := newLeafNode(key, []byte("dogs"), bn.marsh, bn.hasher)

_ = bn.commit(false, 0, db, db)
_ = bn.commit(false, 0, 5, db, db)
bnHash := bn.getHash()
expectedHashes := [][]byte{bnHash}

Expand Down Expand Up @@ -763,7 +765,7 @@ func TestBranchNode_deleteFromStoredBn(t *testing.T) {
childPos := byte(2)
lnKey := append([]byte{childPos}, []byte("dog")...)

_ = bn.commit(false, 0, db, db)
_ = bn.commit(false, 0, 5, db, db)
bnHash := bn.getHash()
ln, _, _ := bn.getNext(lnKey, db)
lnHash := ln.getHash()
Expand Down Expand Up @@ -845,7 +847,7 @@ func TestBranchNode_deleteCollapsedNode(t *testing.T) {
db := mock.NewMemDbMock()
bn, collapsedBn := getBnAndCollapsedBn(getTestMarshAndHasher())
_ = bn.setHash()
_ = bn.commit(false, 0, db, db)
_ = bn.commit(false, 0, 5, db, db)

childPos := byte(2)
key := append([]byte{childPos}, []byte("dog")...)
Expand Down Expand Up @@ -1017,7 +1019,7 @@ func TestBranchNode_getChildrenCollapsedBn(t *testing.T) {

db := mock.NewMemDbMock()
bn, collapsedBn := getBnAndCollapsedBn(getTestMarshAndHasher())
_ = bn.commit(true, 0, db, db)
_ = bn.commit(true, 0, 5, db, db)

children, err := collapsedBn.getChildren(db)
assert.Nil(t, err)
Expand Down Expand Up @@ -1208,3 +1210,128 @@ func BenchmarkMarshallNodeJson(b *testing.B) {
_, _ = marsh.Marshal(bn)
}
}

func TestBranchNode_newBranchNodeNilMarshalizerShouldErr(t *testing.T) {
t.Parallel()

bn, err := newBranchNode(nil, mock.HasherMock{})
assert.Nil(t, bn)
assert.Equal(t, ErrNilMarshalizer, err)
}

func TestBranchNode_newBranchNodeNilHasherShouldErr(t *testing.T) {
t.Parallel()

bn, err := newBranchNode(&mock.MarshalizerMock{}, nil)
assert.Nil(t, bn)
assert.Equal(t, ErrNilHasher, err)
}

func TestBranchNode_newBranchNodeOkVals(t *testing.T) {
t.Parallel()

var children [nrOfChildren]node
marsh, hasher := getTestMarshAndHasher()
bn, err := newBranchNode(marsh, hasher)

assert.Nil(t, err)
assert.Equal(t, make([][]byte, nrOfChildren), bn.EncodedChildren)
assert.Equal(t, children, bn.children)
assert.Equal(t, marsh, bn.marsh)
assert.Equal(t, hasher, bn.hasher)
assert.True(t, bn.dirty)
}

func TestBranchNode_getMarshalizer(t *testing.T) {
t.Parallel()

expectedMarsh := &mock.MarshalizerMock{}
bn := &branchNode{
baseNode: &baseNode{
marsh: expectedMarsh,
},
}

marsh := bn.getMarshalizer()
assert.Equal(t, expectedMarsh, marsh)
}

func TestBranchNode_setRootHashCollapsedChildren(t *testing.T) {
t.Parallel()

marsh, hasher := getTestMarshAndHasher()
bn := &branchNode{
baseNode: &baseNode{
marsh: marsh,
hasher: hasher,
},
}

_, collapsedBn := getBnAndCollapsedBn(marsh, hasher)
_, collapsedEn := getEnAndCollapsedEn()
collapsedLn := getLn(marsh, hasher)

bn.children[0] = collapsedBn
bn.children[1] = collapsedEn
bn.children[2] = collapsedLn

err := bn.setRootHash()
assert.Nil(t, err)
}

func TestBranchNode_commitCollapsesTrieIfMaxTrieLevelInMemoryIsReached(t *testing.T) {
t.Parallel()

bn, collapsedBn := getBnAndCollapsedBn(getTestMarshAndHasher())
_ = collapsedBn.setRootHash()

err := bn.commit(true, 0, 1, mock.NewMemDbMock(), mock.NewMemDbMock())
assert.Nil(t, err)

assert.Equal(t, collapsedBn.EncodedChildren, bn.EncodedChildren)
assert.Equal(t, collapsedBn.children, bn.children)
assert.Equal(t, collapsedBn.hash, bn.hash)
}

func TestBranchNode_reduceNodeBnChild(t *testing.T) {
t.Parallel()

marsh, hasher := getTestMarshAndHasher()
en, _ := getEnAndCollapsedEn()
pos := 5
expectedNode, _ := newExtensionNode([]byte{byte(pos)}, en.child, marsh, hasher)

newNode, err := en.child.reduceNode(pos)
assert.Nil(t, err)
assert.Equal(t, expectedNode, newNode)
}

func TestBranchNode_printShouldNotPanicEvenIfNodeIsCollapsed(t *testing.T) {
t.Parallel()

bnWriter := bytes.NewBuffer(make([]byte, 0))
collapsedBnWriter := bytes.NewBuffer(make([]byte, 0))

db := mock.NewMemDbMock()
bn, collapsedBn := getBnAndCollapsedBn(getTestMarshAndHasher())
_ = bn.commit(true, 0, 5, db, db)
_ = collapsedBn.commit(true, 0, 5, db, db)

bn.print(bnWriter, 0, db)
collapsedBn.print(collapsedBnWriter, 0, db)

assert.Equal(t, bnWriter.Bytes(), collapsedBnWriter.Bytes())
}

func TestBranchNode_getDirtyHashesFromCleanNode(t *testing.T) {
t.Parallel()

db := mock.NewMemDbMock()
bn, _ := getBnAndCollapsedBn(getTestMarshAndHasher())
_ = bn.commit(true, 0, 5, db, db)
dirtyHashes := make(data.ModifiedHashes)

err := bn.getDirtyHashes(dirtyHashes)
assert.Nil(t, err)
assert.Equal(t, 0, len(dirtyHashes))
}
Loading