Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
47b6d27
Cover more store/load child trie related test cases
kishansagathiya Feb 16, 2022
29ace8a
test error `failed to insert child trie with root` in trie.Load
kishansagathiya Feb 21, 2022
772b6c2
temp
kishansagathiya Feb 22, 2022
061b9bf
test TestGetStorageChildAndGetStorageFromChild with non-empty trie
kishansagathiya Mar 3, 2022
bf0f5ee
tackle the case when encoding and hash is same
kishansagathiya Mar 3, 2022
46af47a
Merge branch 'development' into kishan/task/trie-test
kishansagathiya Mar 3, 2022
8a5f18c
so far things work, no error finding any nodes, child tries get
kishansagathiya Mar 7, 2022
e4f434a
child tries don't have empty bits in their encoding
kishansagathiya Mar 7, 2022
13f3e59
cleaning up
kishansagathiya Mar 7, 2022
d6d5a87
more clean up
kishansagathiya Mar 7, 2022
4eed767
accept []byte key in trie.Load instead of common.Hash
kishansagathiya Mar 7, 2022
c24a76d
uncomment the test TestLoadWithChildTriesFails
kishansagathiya Mar 7, 2022
d6f63bd
more clean up
kishansagathiya Mar 7, 2022
46d590c
more cleanup
kishansagathiya Mar 8, 2022
68e4469
remove mockleaf
kishansagathiya Mar 8, 2022
82db221
Merge branch 'development' into kishan/task/trie-test
kishansagathiya Mar 10, 2022
42d1532
fix the commit
kishansagathiya Mar 10, 2022
2dd3a2c
fix(lib/trie): Make sure writing and reading to disk gives the same t…
kishansagathiya Mar 14, 2022
f174ab9
Merge branch 'development' into kishan/task/trie-test
kishansagathiya Mar 14, 2022
fe91011
Merge branch 'kishan/task/trie-test' of github.com:ChainSafe/gossamer…
kishansagathiya Mar 14, 2022
019953b
remove todos
kishansagathiya Mar 15, 2022
ccca175
Update lib/trie/child_storage.go
kishansagathiya Mar 17, 2022
03af4b0
Update dot/state/storage_test.go
kishansagathiya Mar 17, 2022
9d4f195
Update dot/state/storage.go
kishansagathiya Mar 18, 2022
d6cfcc2
addressed reviews
kishansagathiya Mar 18, 2022
31d2b8e
Merge branch 'kishan/task/trie-test' of github.com:ChainSafe/gossamer…
kishansagathiya Mar 18, 2022
5c7ec38
renaming Test to keyValue
kishansagathiya Mar 18, 2022
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
2 changes: 1 addition & 1 deletion dot/state/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestTrie_StoreAndLoadFromDB(t *testing.T) {
expected := tt.MustHash()

tt = trie.NewEmptyTrie()
err = tt.Load(db, encroot)
err = tt.Load(db, encroot.ToBytes())
require.NoError(t, err)
require.Equal(t, expected, tt.MustHash())
}
Expand Down
2 changes: 1 addition & 1 deletion dot/state/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func (s *StorageState) TrieState(root *common.Hash) (*rtstorage.TrieState, error
// LoadFromDB loads an encoded trie from the DB where the key is `root`
func (s *StorageState) LoadFromDB(root common.Hash) (*trie.Trie, error) {
t := trie.NewEmptyTrie()
err := t.Load(s.db, root)
err := t.Load(s.db, root.ToBytes())
if err != nil {
return nil, err
}
Expand Down
11 changes: 9 additions & 2 deletions dot/state/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/ChainSafe/gossamer/dot/state/pruner"
"github.com/ChainSafe/gossamer/dot/telemetry"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/internal/trie/node"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/genesis"
runtime "github.com/ChainSafe/gossamer/lib/runtime/storage"
Expand Down Expand Up @@ -227,7 +228,12 @@ func TestGetStorageChildAndGetStorageFromChild(t *testing.T) {
"0",
))

testChildTrie := trie.NewEmptyTrie()
key := []byte{1, 2}
value := []byte{3, 4}
const dirty = true
const generation = 0
testChildTrie := trie.NewTrie(node.NewLeaf(key, value, dirty, generation))
Comment thread
kishansagathiya marked this conversation as resolved.
Outdated

testChildTrie.Put([]byte("keyInsidechild"), []byte("voila"))

err = genTrie.PutChild([]byte("keyToChild"), testChildTrie)
Expand All @@ -236,6 +242,7 @@ func TestGetStorageChildAndGetStorageFromChild(t *testing.T) {
triesGauge := NewMockGauge(ctrl)
triesGauge.EXPECT().Inc().Times(2)
triesGauge.EXPECT().Set(0.00)

tries := &Tries{
rootToTrie: make(map[common.Hash]*trie.Trie),
triesGauge: triesGauge,
Expand Down Expand Up @@ -269,7 +276,7 @@ func TestGetStorageChildAndGetStorageFromChild(t *testing.T) {
_, err = storage.GetStorageChild(&rootHash, []byte("keyToChild"))
require.NoError(t, err)

value, err := storage.GetStorageFromChild(&rootHash, []byte("keyToChild"), []byte("keyInsidechild"))
value, err = storage.GetStorageFromChild(&rootHash, []byte("keyToChild"), []byte("keyInsidechild"))
require.NoError(t, err)

require.Equal(t, []byte("voila"), value)
Expand Down
11 changes: 7 additions & 4 deletions lib/trie/child_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,20 @@ var ChildStorageKeyPrefix = []byte(":child_storage:default:")
var ErrChildTrieDoesNotExist = errors.New("child trie does not exist")

// PutChild inserts a child trie into the main trie at key :child_storage:[keyToChild]
// A child trie is added as a node (K, V) in main trie. K is the child storage key
Comment thread
kishansagathiya marked this conversation as resolved.
Outdated
// associated to the child trie, and V is the Merkle value of its corresponding child trie.
// To get merkle value of a node, we get value of the node. If the value is shorter than
// 32 bits, we use it as merkle value. Otherwise, we use it's blake2b hash as merkle value.
Comment thread
kishansagathiya marked this conversation as resolved.
Outdated
func (t *Trie) PutChild(keyToChild []byte, child *Trie) error {
childHash, err := child.Hash()
_, hash, err := child.root.EncodeAndHash()
if err != nil {
return err
}

key := append(ChildStorageKeyPrefix, keyToChild...)
value := [32]byte(childHash)

t.Put(key, value[:])
t.childTries[childHash] = child
t.Put(key, hash)
t.childTries[common.BytesToHash(hash)] = child
return nil
}

Expand Down
18 changes: 10 additions & 8 deletions lib/trie/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,24 +145,23 @@ func (t *Trie) loadProof(proofHashToNode map[string]Node, n Node) {

// Load reconstructs the trie from the database from the given root hash.
// It is used when restarting the node to load the current state trie.
func (t *Trie) Load(db chaindb.Database, rootHash common.Hash) error {
if rootHash == EmptyHash {
func (t *Trie) Load(db chaindb.Database, rootHashBytes []byte) error {
Comment thread
kishansagathiya marked this conversation as resolved.
Outdated
if len(rootHashBytes) == 0 {
t.root = nil
return nil
}

rootHashBytes := rootHash[:]

encodedNode, err := db.Get(rootHashBytes)
if err != nil {
return fmt.Errorf("failed to find root key %s: %w", rootHash, err)
return fmt.Errorf("failed to find root key 0x%x: %w", rootHashBytes, err)
}

reader := bytes.NewReader(encodedNode)
root, err := node.Decode(reader)
if err != nil {
return fmt.Errorf("cannot decode root node: %w", err)
}

t.root = root
t.root.SetDirty(false)
t.root.SetEncodingAndHash(encodedNode, rootHashBytes)
Expand All @@ -185,6 +184,7 @@ func (t *Trie) load(db chaindb.Database, n Node) error {
}

hash := child.GetHash()

encodedNode, err := db.Get(hash)
if err != nil {
return fmt.Errorf("cannot find child node key 0x%x in database: %w", hash, err)
Expand All @@ -209,11 +209,13 @@ func (t *Trie) load(db chaindb.Database, n Node) error {
for _, key := range t.GetKeysWithPrefix(ChildStorageKeyPrefix) {
childTrie := NewEmptyTrie()
value := t.Get(key)
err := childTrie.Load(db, common.NewHash(value))
// TODO: Tests this error
err := childTrie.Load(db, value)
if err != nil {
return fmt.Errorf("failed to load child trie with root hash=0x%x: %w", value, err)
}

// TODO: Test this error
err = t.PutChild(value, childTrie)
if err != nil {
return fmt.Errorf("failed to insert child trie with root hash=0x%x into main trie: %w",
Expand Down Expand Up @@ -377,8 +379,8 @@ func (t *Trie) writeDirty(db chaindb.Batch, n Node) error {
n.GetHash(), err)
}

if n == t.root {
// hash root node even if its encoding is under 32 bytes
// hash root node even if its encoding is under 32 bytes
if n == t.root && len(encoding) < 32 {
Comment thread
kishansagathiya marked this conversation as resolved.
Outdated
encodingDigest, err := common.Blake2bHash(encoding)
if err != nil {
return fmt.Errorf("cannot hash root node encoding: %w", err)
Expand Down
67 changes: 62 additions & 5 deletions lib/trie/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"testing"

"github.com/ChainSafe/chaindb"
"github.com/ChainSafe/gossamer/internal/trie/node"
"github.com/ChainSafe/gossamer/lib/utils"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -63,9 +64,10 @@ func TestTrie_DatabaseStoreAndLoad(t *testing.T) {
require.NoError(t, err)

res := NewEmptyTrie()
err = res.Load(db, trie.MustHash())
err = res.Load(db, trie.MustHash().ToBytes())
require.NoError(t, err)
require.Equal(t, trie.MustHash(), res.MustHash())
require.Equal(t, trie.String(), res.String())
Comment thread
kishansagathiya marked this conversation as resolved.

for _, test := range testCase {
val, err := GetFromDB(db, trie.MustHash(), test.key)
Expand Down Expand Up @@ -134,7 +136,7 @@ func TestTrie_WriteDirty_Put(t *testing.T) {
require.NoError(t, err)

res := NewEmptyTrie()
err = res.Load(db, trie.MustHash())
err = res.Load(db, trie.MustHash().ToBytes())
require.NoError(t, err)
require.Equal(t, trie.MustHash(), res.MustHash())

Expand Down Expand Up @@ -204,7 +206,7 @@ func TestTrie_WriteDirty_PutReplace(t *testing.T) {
}

res := NewEmptyTrie()
err := res.Load(db, trie.MustHash())
err := res.Load(db, trie.MustHash().ToBytes())
require.NoError(t, err)
require.Equal(t, trie.MustHash(), res.MustHash())

Expand Down Expand Up @@ -264,7 +266,7 @@ func TestTrie_WriteDirty_Delete(t *testing.T) {
require.NoError(t, err)

res := NewEmptyTrie()
err = res.Load(db, trie.MustHash())
err = res.Load(db, trie.MustHash().ToBytes())
require.NoError(t, err)
require.Equal(t, trie.MustHash(), res.MustHash())

Expand Down Expand Up @@ -329,7 +331,7 @@ func TestTrie_WriteDirty_ClearPrefix(t *testing.T) {
require.NoError(t, err)

res := NewEmptyTrie()
err = res.Load(db, trie.MustHash())
err = res.Load(db, trie.MustHash().ToBytes())
require.NoError(t, err)

require.Equal(t, trie.MustHash(), res.MustHash())
Expand Down Expand Up @@ -387,3 +389,58 @@ func TestTrie_GetFromDB(t *testing.T) {
}
}
}

func TestStoreAndLoadWithChildTries(t *testing.T) {
testCase := []Test{
Comment thread
kishansagathiya marked this conversation as resolved.
Outdated
Comment thread
kishansagathiya marked this conversation as resolved.
Outdated
{key: []byte{0xf2, 0x3}, value: []byte("f")},
{key: []byte{0x09, 0xd3}, value: []byte("noot")},
{key: []byte{0x07}, value: []byte("ramen")},
{key: []byte{0}, value: nil},
{
key: []byte("The boxed moved. That was a problem."),
value: []byte("The question now was whether or not Peter was going to open it up and look inside to see why it had moved."), // nolint
},
}

key := []byte{1, 2}
value := []byte{3, 4}
const dirty = true
const generation = 0

t.Run("happy path, tries being loaded are same as trie being read", func(t *testing.T) {
// hash could be different for keys smaller than 32 and larger than 32 bits.
// thus, testing with keys of different sizes.
keysToTest := [][]byte{
[]byte("This handout will help you understand how paragraphs are formed, how to develop stronger paragraphs."),
[]byte("This handout"),
[]byte("test"),
}

for _, keyToChild := range keysToTest {
trie := NewEmptyTrie()

for _, test := range testCase {
trie.Put(test.key, test.value)
}

db := newTestDB(t)

sampleChildTrie := NewTrie(node.NewLeaf(key, value, dirty, generation))

err := trie.PutChild(keyToChild, sampleChildTrie)
require.NoError(t, err)

err = trie.Store(db)
require.NoError(t, err)

res := NewEmptyTrie()

err = res.Load(db, trie.root.GetHash())
require.NoError(t, err)

require.Equal(t, trie.childTries, res.childTries)
}

})

}
2 changes: 1 addition & 1 deletion lib/trie/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func GenerateProof(root []byte, keys [][]byte, db chaindb.Database) ([][]byte, e
trackedProofs := make(map[string][]byte)

proofTrie := NewEmptyTrie()
if err := proofTrie.Load(db, common.BytesToHash(root)); err != nil {
if err := proofTrie.Load(db, root); err != nil {
return nil, err
}

Expand Down
3 changes: 1 addition & 2 deletions lib/trie/trie_endtoend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (

"github.com/ChainSafe/gossamer/internal/trie/codec"
"github.com/ChainSafe/gossamer/internal/trie/node"
"github.com/ChainSafe/gossamer/lib/common"
)

const (
Expand Down Expand Up @@ -397,7 +396,7 @@ func TestTrieDiff(t *testing.T) {
}

dbTrie := NewEmptyTrie()
err = dbTrie.Load(storageDB, common.BytesToHash(newTrie.root.GetHash()))
err = dbTrie.Load(storageDB, newTrie.root.GetHash())
require.NoError(t, err)
}

Expand Down