swarm/storage add hash.Hash interface for BMT .

Integrate with chunker.go
This commit is contained in:
Oren 2017-03-24 07:49:35 +03:00
parent eab1384b08
commit 44a9a39c84
4 changed files with 106 additions and 4 deletions

View file

@ -6,13 +6,21 @@ import (
"bytes"
_ "crypto/sha256"
"encoding/binary"
"errors"
"fmt"
"hash"
"io"
"github.com/ethereum/go-ethereum/crypto/sha3"
)
var hashFunc Hasher = sha3.NewKeccak256 //default hasher
type state struct {
btree BTree
root Root
}
// A merkle tree for a user that stores the entire tree
// Specifically this tree is left a leaning balanced binary tree
// Where each node holds the hash of its leaves
@ -313,3 +321,64 @@ func checkNode(height int, proof [][]byte, index, count uint64) ([]byte, bool) {
hash := h.Sum(make([]byte, 0))
return hash, ok
}
// ShakeHash defines the interface to hash functions that
// support arbitrary-length output.
type BMTHash interface {
// Write absorbs more data into the hash's state. It panics if input is
// written to it after output has been read from it.
io.Writer
// Read reads more output from the hash; reading affects the hash's
// state. (ShakeHash.Read is thus very different from Hash.Sum)
// It never returns an error.
io.Reader
// Clone returns a copy of the ShakeHash in its current state.
Clone() BMTHash
// Reset resets the ShakeHash to its initial state.
Reset()
}
// Reset clears the internal state by zeroing the sponge state and
func (d *state) Reset() {
d.root = Root{Count: 0, Base: nil}
d.btree = BTree{count: 0, root: nil, rootHash: nil}
}
// Write absorbs more data into the hash's state. It produces an error
// if more data is written to the ShakeHash after writing
func (d *state) Write(p []byte) (written int, err error) {
tree, r, count, err1 := BuildBMT(hashFunc, p, 32)
d.btree = *tree
d.root = *r
if err1 != 0 {
err = errors.New("bmt write error")
}
return count, err
}
func (d *state) Get(p []byte) (written int) {
return 3
}
// Sum return the root hash of the BMT
func (d *state) Sum(in []byte) []byte {
return d.root.Base
}
// BlockSize returns the rate of sponge underlying this hash function.
func (d *state) BlockSize() int { return 0 }
// Size returns the output size of the hash function in bytes.
func (d *state) Size() int { return 32 }
// NewBMTSHA3 creates a new BMT hash
func NewBMTSHA3() hash.Hash {
tmpbtree := BTree{count: 0, root: nil, rootHash: nil}
troot := Root{Count: 0, Base: nil}
return &state{btree: tmpbtree, root: troot}
}

View file

@ -41,6 +41,35 @@ func TestGetHeight2(t *testing.T) {
}
}
func TestBuildBMT3(t *testing.T) {
// Grab some data to make the tree out of, and partition
data, err := ioutil.ReadFile("binarymerkle_test.go") // assume testdata exists
if err != nil {
fmt.Println(err)
return
}
var thashFunc = MakeHashFunc("BMTSHA3")
var h = thashFunc()
h.Reset()
h.Write(data)
var key = h.Sum(nil)
fmt.Println(key)
// for i := 0; i < count; i++ {
// p := tree.InclusionProof(i)
//
// fmt.Println(p)
//
// ok := r.CheckProof(sha3.NewKeccak256, p, i)
// if !ok {
// t.Errorf("proof %d failed", i)
// }
// }
// fmt.Println("done")
}
func TestBuildBMT(t *testing.T) {
// Grab some data to make the tree out of, and partition
@ -50,7 +79,7 @@ func TestBuildBMT(t *testing.T) {
return
}
tree, r, count, err1 := BuildBMT(sha3.NewKeccak256, data, 32)
tree, r, count, err1 := BuildBMT(sha3.NewKeccak256, data, 1)
switch err1 {
case -1:
@ -61,7 +90,7 @@ func TestBuildBMT(t *testing.T) {
t.Errorf("BMT leaf count validation error")
return
case 0:
fmt.Println("Build BMT OK")
fmt.Println("Build BMT OK ", count)
}
fmt.Println(tree.Root())
@ -76,6 +105,7 @@ func TestBuildBMT(t *testing.T) {
t.Errorf("proof %d failed", i)
}
}
fmt.Println("done")
}
func TestBuildBMT2(t *testing.T) {
@ -88,7 +118,7 @@ func TestBuildBMT2(t *testing.T) {
}
fmt.Println(len(data))
blocks := splitData(data, 32)
blocks := splitData(data, 2)
count := len(blocks)

View file

@ -51,7 +51,8 @@ data_{i} := size(subtree_{i}) || key_{j} || key_{j+1} .... || key_{j+n-1}
*/
const (
defaultHash = "SHA3" // http://golang.org/pkg/hash/#Hash
//defaultHash = "SHA3"
defaultHash = "BMTSHA3" // http://golang.org/pkg/hash/#Hash
// defaultHash = "SHA256" // http://golang.org/pkg/hash/#Hash
defaultBranches int64 = 128
// hashSize int64 = hasherfunc.New().Size() // hasher knows about its own length in bytes

View file

@ -83,6 +83,8 @@ func MakeHashFunc(hash string) Hasher {
return crypto.SHA256.New
case "SHA3":
return sha3.NewKeccak256
case "BMTSHA3":
return NewBMTSHA3
}
return nil
}