Skip to content

Commit 519807a

Browse files
committed
add new tests; create description;
1 parent 5c2a1cc commit 519807a

File tree

6 files changed

+186
-8
lines changed

6 files changed

+186
-8
lines changed

README.md

+107-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,108 @@
1-
# MPT - Merkle Patricia Tries
1+
# MPT - Modified Merkle Patricia Tries
22

3-
Simple implementation of Merkle Patricia Tries on GoLang.
3+
Simple implementation of Modified Merkle Patricia Tries on GoLang.
4+
5+
## Usage
6+
7+
1. Create the Trie:
8+
9+
- With empty root node:
10+
11+
```go
12+
trie := mpt.NewEmptyTrie()
13+
```
14+
15+
- With branch root node:
16+
17+
```go
18+
nd := node.NewBranchNode()
19+
trie := mpt.NewTrie(nd)
20+
```
21+
22+
- With extension root node:
23+
24+
```go
25+
nd := node.NewExtensionNode(nil, nil)
26+
trie := mpt.NewTrie(nd)
27+
```
28+
29+
2. Add key/value pair:
30+
31+
```go
32+
key := []byte("key")
33+
val := []byte("val")
34+
35+
// create new trie and try add key/value pair
36+
trie := mpt.NewEmptyTrie()
37+
if ok := trie.Put(key, val); !ok {
38+
// key/pair not added
39+
}
40+
41+
```
42+
43+
3. Get data by key:
44+
45+
```go
46+
key := []byte("key")
47+
val := []byte("val")
48+
49+
// create new trie and try add key/value pair
50+
trie := mpt.NewEmptyTrie()
51+
if ok := trie.Put(key, val); !ok {
52+
// key/pair not added
53+
}
54+
55+
// some logic...
56+
57+
// try to get data by key
58+
getVal, ok := trie.Get(key)
59+
if !ok {
60+
// key/pair not added
61+
}
62+
63+
```
64+
65+
4. Update data by key:
66+
67+
```go
68+
// initialize data
69+
key := []byte("key")
70+
val := []byte("val")
71+
72+
// create new trie and try add key/value pair
73+
trie := mpt.NewEmptyTrie()
74+
if ok := trie.Put(key, val); !ok {
75+
// key/pair not added
76+
}
77+
78+
// some logic...
79+
80+
// try to update value by key
81+
newVal := []byte("updated value")
82+
if ok := trie.Update(key, newVal); !ok {
83+
// data not updated
84+
}
85+
86+
```
87+
88+
5. Delete data by key:
89+
90+
```go
91+
// initialize data
92+
key := []byte("key")
93+
val := []byte("val")
94+
95+
// create new trie and try add key/value pair
96+
trie := mpt.NewEmptyTrie()
97+
if ok := trie.Put(key, val); !ok {
98+
// key/pair not added
99+
}
100+
101+
// some logic...
102+
103+
// try to delete data by key
104+
if ok := trie.Delete(key, newVal); !ok {
105+
// data not deleted
106+
}
107+
108+
```

database.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func NewDatabase() *Database {
1515
return &Database{}
1616
}
1717

18-
func (db *Database) GetNode(hash enc.Hash, cGen uint16) node.Node {
18+
func (db *Database) GetNode(hash enc.Hash) node.Node {
1919
return nil
2020
}
2121

node/branch_test.go

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package node
2+
3+
import (
4+
"bytes"
5+
"reflect"
6+
"testing"
7+
8+
"github.com/begmaroman/mpt/enc"
9+
)
10+
11+
func TestBranchNode_Find(t *testing.T) {
12+
key, value := enc.BytesToHex([]byte("key")), []byte("value")
13+
14+
nd := NewBranchNode()
15+
nd.Children[key[0]] = NewExtensionNode(key[1:], NewLeafNode(value))
16+
17+
rVal, rNd, ok := nd.Find(key)
18+
if !ok {
19+
t.Error("added data not found")
20+
return
21+
}
22+
23+
if !bytes.Equal(rVal, value) {
24+
t.Errorf("invalid value: expected %s got %s", value, rVal)
25+
}
26+
27+
if !reflect.DeepEqual(nd, rNd) {
28+
t.Errorf("invalid node: expected %#v got %#v", nd, rNd)
29+
}
30+
}
31+
32+
func TestBranchNode_PutAndCheck(t *testing.T) {
33+
key, value := enc.BytesToHex([]byte("key")), []byte("value")
34+
35+
nd := NewBranchNode()
36+
newNode, ok := nd.Put(key, NewLeafNode(value))
37+
if !ok {
38+
t.Error("put failed")
39+
return
40+
}
41+
42+
rVal, rNd, ok := newNode.Find(key)
43+
if !ok {
44+
t.Error("added data not found")
45+
return
46+
}
47+
48+
if !bytes.Equal(rVal, value) {
49+
t.Errorf("invalid value: expected %s got %s", value, rVal)
50+
}
51+
52+
if !reflect.DeepEqual(newNode, rNd) {
53+
t.Errorf("invalid node: expected %#v got %#v", newNode, rNd)
54+
}
55+
}

node/extension.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func (e *ExtensionNode) Find(key []byte) ([]byte, Node, bool) {
4444

4545
func (e *ExtensionNode) Put(key []byte, value Node) (Node, bool) {
4646
if e.Key == nil {
47-
47+
return NewExtensionNode(key, value), true
4848
}
4949

5050
matchKey := enc.PrefixLen(key, e.Key)

trie.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ var (
1414
type Trie struct {
1515
db *Database
1616
node node.Node
17-
18-
cGen, cLimit uint16
1917
}
2018

2119
func NewTrie(node node.Node) *Trie {
@@ -24,6 +22,10 @@ func NewTrie(node node.Node) *Trie {
2422
}
2523
}
2624

25+
func NewEmptyTrie() *Trie {
26+
return &Trie{}
27+
}
28+
2729
// Hash calculate and return hash of the tree
2830
func (t *Trie) Hash() (enc.Hash, error) {
2931
bHash, cached, err := t.hashRoot(nil)
@@ -144,7 +146,7 @@ func (t *Trie) resolve(n node.Node, prefix []byte) (node.Node, error) {
144146
func (t *Trie) resolveHash(n node.HashNode, prefix []byte) (node.Node, error) {
145147
hash := n.Hash() // get hash of HashNode
146148

147-
if nd := t.db.GetNode(hash, t.cGen); nd != nil { // lookup node.Node in database
149+
if nd := t.db.GetNode(hash); nd != nil { // lookup node.Node in database
148150
return nd, nil // return node.Node from database if exist
149151
}
150152

trie_test.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ func TestTrie_PutDeleteAndCheck(t *testing.T) {
246246
}
247247
}
248248

249-
func TestTrie_CustomStartNode(t *testing.T) {
249+
func TestTrie_CustomStartNode_BranchNode_Empty(t *testing.T) {
250250
key, val := []byte("test"), []byte("test value")
251251

252252
trie := mpt.NewTrie(node.NewBranchNode())
@@ -262,6 +262,22 @@ func TestTrie_CustomStartNode(t *testing.T) {
262262
}
263263
}
264264

265+
func TestTrie_CustomStartNode_ExtensionNode_Empty(t *testing.T) {
266+
key, val := []byte("test"), []byte("test value")
267+
268+
trie := mpt.NewTrie(node.NewExtensionNode(nil, nil))
269+
trie.Put(key, val)
270+
271+
rVal, ok := trie.Get([]byte("test"))
272+
if !ok {
273+
t.Errorf("lookup failed for key %s", key)
274+
}
275+
276+
if !bytes.Equal(rVal, val) {
277+
t.Errorf("check added: invalid value: expected %s got %s", val, rVal)
278+
}
279+
}
280+
265281
// Benchmarks
266282
func BenchmarkTrie_Get(b *testing.B) {
267283
key, val := []byte("tolongwseb;kjnwkjlevnoknbkomnrwobnwotrh34y6onyo"), []byte("lwebniopwjgnipwuhgpv wrhtpovm rhiopwerhgpowuihnopwrntgmopkrtmvport uiwthgipurthg puti")

0 commit comments

Comments
 (0)