Skip to content

Commit

Permalink
Add db backend hook for merkletree package
Browse files Browse the repository at this point in the history
- Export fields of nodes struct for gob encoding

- Add gob encoding/decoding for PAD, STR, MerkleTree, Policies (use internally)
  • Loading branch information
vqhuy committed Dec 25, 2016
1 parent 8d42521 commit 21709e9
Show file tree
Hide file tree
Showing 14 changed files with 582 additions and 83 deletions.
100 changes: 79 additions & 21 deletions merkletree/merkletree.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package merkletree

import (
"bytes"
"encoding/gob"
"errors"
"io"

"github.com/coniks-sys/coniks-go/crypto"
"github.com/coniks-sys/coniks-go/utils"
Expand Down Expand Up @@ -74,10 +76,10 @@ func (m *MerkleTree) Get(lookupIndex []byte) *AuthenticationPath {
direction := lookupIndexBits[depth]
var hashArr [crypto.HashSizeByte]byte
if direction {
copy(hashArr[:], nodePointer.(*interiorNode).leftHash)
copy(hashArr[:], nodePointer.(*interiorNode).LeftHash)
nodePointer = nodePointer.(*interiorNode).rightChild
} else {
copy(hashArr[:], nodePointer.(*interiorNode).rightHash)
copy(hashArr[:], nodePointer.(*interiorNode).RightHash)
nodePointer = nodePointer.(*interiorNode).leftChild
}
authPath.PrunedTree = append(authPath.PrunedTree, hashArr)
Expand All @@ -91,13 +93,13 @@ func (m *MerkleTree) Get(lookupIndex []byte) *AuthenticationPath {
case *userLeafNode:
pNode := nodePointer.(*userLeafNode)
authPath.Leaf = &ProofNode{
Level: pNode.level,
Index: pNode.index,
Value: pNode.value,
Level: pNode.Level,
Index: pNode.Index,
Value: pNode.Value,
IsEmpty: false,
Commitment: &crypto.Commit{pNode.commitment.Salt, pNode.commitment.Value},
Commitment: &crypto.Commit{pNode.Commitment.Salt, pNode.Commitment.Value},
}
if bytes.Equal(nodePointer.(*userLeafNode).index, lookupIndex) {
if bytes.Equal(nodePointer.(*userLeafNode).Index, lookupIndex) {
return authPath
}
// reached a different leaf with a matching prefix
Expand All @@ -108,8 +110,8 @@ func (m *MerkleTree) Get(lookupIndex []byte) *AuthenticationPath {
case *emptyNode:
pNode := nodePointer.(*emptyNode)
authPath.Leaf = &ProofNode{
Level: pNode.level,
Index: pNode.index,
Level: pNode.Level,
Index: pNode.Index,
Value: nil,
IsEmpty: true,
Commitment: nil,
Expand All @@ -130,10 +132,10 @@ func (m *MerkleTree) Set(index []byte, key string, value []byte) error {
return err
}
toAdd := userLeafNode{
key: key,
value: append([]byte{}, value...), // make a copy of value
index: index,
commitment: commitment,
Key: key,
Value: append([]byte{}, value...), // make a copy of value
Index: index,
Commitment: commitment,
}
m.insertNode(index, &toAdd)
return nil
Expand All @@ -157,23 +159,23 @@ insertLoop:
panic(ErrInvalidTree)
}

if bytes.Equal(currentNodeUL.index, toAdd.index) {
if bytes.Equal(currentNodeUL.Index, toAdd.Index) {
// replace the value
toAdd.parent = currentNodeUL.parent
toAdd.level = currentNodeUL.level
toAdd.Level = currentNodeUL.Level
*currentNodeUL = *toAdd
return
}

newInteriorNode := newInteriorNode(currentNodeUL.parent, depth, indexBits[:depth])

direction := utils.GetNthBit(currentNodeUL.index, depth)
direction := utils.GetNthBit(currentNodeUL.Index, depth)
if direction {
newInteriorNode.rightChild = currentNodeUL
} else {
newInteriorNode.leftChild = currentNodeUL
}
currentNodeUL.level = depth + 1
currentNodeUL.Level = depth + 1
currentNodeUL.parent = newInteriorNode
if newInteriorNode.parent.(*interiorNode).leftChild == nodePointer {
newInteriorNode.parent.(*interiorNode).leftChild = newInteriorNode
Expand All @@ -185,20 +187,20 @@ insertLoop:
currentNodeI := nodePointer.(*interiorNode)
direction := indexBits[depth]
if direction { // go right
currentNodeI.rightHash = nil
currentNodeI.RightHash = nil
if currentNodeI.rightChild.isEmpty() {
currentNodeI.rightChild = toAdd
toAdd.level = depth + 1
toAdd.Level = depth + 1
toAdd.parent = currentNodeI
break insertLoop
} else {
nodePointer = currentNodeI.rightChild
}
} else { // go left
currentNodeI.leftHash = nil
currentNodeI.LeftHash = nil
if currentNodeI.leftChild.isEmpty() {
currentNodeI.leftChild = toAdd
toAdd.level = depth + 1
toAdd.Level = depth + 1
toAdd.parent = currentNodeI
break insertLoop
} else {
Expand Down Expand Up @@ -250,3 +252,59 @@ func (m *MerkleTree) Clone() *MerkleTree {
hash: append([]byte{}, m.hash...),
}
}

// encodeTree writes the tree's nonce into buff first,
// following by all the nodes data.
func encodeTree(buff io.Writer, m *MerkleTree) error {
enc := gob.NewEncoder(buff)
if err := enc.Encode(m.nonce); err != nil {
return err
}
if err := encodeNode(enc, m.root); err != nil {
return err
}
return nil
}

// decodeTree reconstructs the tree from the buffer
// that was written using encodeTree.
func decodeTree(buff io.Reader) (*MerkleTree, error) {
m := new(MerkleTree)
dec := gob.NewDecoder(buff)
if err := dec.Decode(&m.nonce); err != nil {
return nil, err
}
root, err := reconstructTree(dec, nil)
if err != nil {
return nil, err
}
m.root = root.(*interiorNode)
m.hash = m.root.hash(m)
return m, nil
}

func reconstructTree(dec *gob.Decoder, parent merkleNode) (merkleNode, error) {
n, err := decodeNode(dec)
if err != nil {
return nil, err
}

if _, ok := n.(*emptyNode); ok {
n.(*emptyNode).parent = parent
return n, nil
}
if _, ok := n.(*userLeafNode); ok {
n.(*userLeafNode).parent = parent
return n, nil
}
n.(*interiorNode).parent = parent
n.(*interiorNode).leftChild, err = reconstructTree(dec, n)
if err != nil {
return nil, err
}
n.(*interiorNode).rightChild, err = reconstructTree(dec, n)
if err != nil {
return nil, err
}
return n, nil
}
8 changes: 4 additions & 4 deletions merkletree/merkletree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ func TestOneEntry(t *testing.T) {
h.Write(utils.ToBytes([]bool{true}))
h.Write(utils.UInt32ToBytes(1))
h.Read(expect[:])
if !bytes.Equal(m.root.rightHash, expect[:]) {
if !bytes.Equal(m.root.RightHash, expect[:]) {
t.Error("Wrong righ hash!",
"expected", expect,
"get", m.root.rightHash)
"get", m.root.RightHash)
}

r := m.Get(index)
Expand Down Expand Up @@ -70,10 +70,10 @@ func TestOneEntry(t *testing.T) {
h.Write(commit[:])
h.Read(expect[:])

if !bytes.Equal(m.root.leftHash, expect[:]) {
if !bytes.Equal(m.root.LeftHash, expect[:]) {
t.Error("Wrong left hash!",
"expected", expect,
"get", m.root.leftHash)
"get", m.root.LeftHash)
}

r = m.Get([]byte("abc"))
Expand Down
15 changes: 15 additions & 0 deletions merkletree/mock_ad.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package merkletree

import "encoding/gob"

func init() {
gob.Register(&MockAd{})
}

type MockAd struct {
Data string
}

func (t *MockAd) Serialize() []byte {
return []byte(t.Data)
}
Loading

0 comments on commit 21709e9

Please sign in to comment.