mirror of
https://github.com/vbatts/merkle.git
synced 2024-11-30 18:15:40 +00:00
stream: Write() is mostly finished
This commit is contained in:
parent
68f4bcde5d
commit
257ed6dfad
2 changed files with 72 additions and 15 deletions
49
stream.go
49
stream.go
|
@ -21,14 +21,13 @@ func NewHash(hm HashMaker, merkleBlockLength int) hash.Hash {
|
||||||
// that will validate nodes as the new bytes are written. If a new written
|
// that will validate nodes as the new bytes are written. If a new written
|
||||||
// block fails checksum, then return an error on the io.Writer
|
// block fails checksum, then return an error on the io.Writer
|
||||||
|
|
||||||
// TODO satisfy the hash.Hash interface
|
|
||||||
type merkleHash struct {
|
type merkleHash struct {
|
||||||
blockSize int
|
blockSize int
|
||||||
tree *Tree
|
tree *Tree
|
||||||
hm HashMaker
|
hm HashMaker
|
||||||
lastBlock []byte // as needed, for Sum()
|
lastBlock []byte // as needed, for Sum()
|
||||||
lastBlockLen int
|
lastBlockLen int
|
||||||
//partialLastBlock bool
|
partialLastNode bool // true when Sum() has appended a Node for a partial block
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX this will be tricky, as the last block can be less than the BlockSize.
|
// XXX this will be tricky, as the last block can be less than the BlockSize.
|
||||||
|
@ -40,10 +39,23 @@ type merkleHash struct {
|
||||||
//
|
//
|
||||||
// if that last block was complete, then no worries. start the next node.
|
// if that last block was complete, then no worries. start the next node.
|
||||||
func (mh *merkleHash) Sum(b []byte) []byte {
|
func (mh *merkleHash) Sum(b []byte) []byte {
|
||||||
|
if b != nil && (len(b)+mh.lastBlockLen) > mh.blockSize {
|
||||||
|
// write a full node
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := NewNodeHashBlock(mh.hm, curBlock)
|
||||||
|
if err != nil {
|
||||||
|
// XXX might need to stash again the prior lastBlock and first little chunk
|
||||||
|
return numWritten, err
|
||||||
|
}
|
||||||
|
mh.tree.Nodes = append(mh.tree.Nodes, n)
|
||||||
|
numWritten += offset
|
||||||
|
|
||||||
// TODO check if len(mh.lastBlock) < blockSize
|
// TODO check if len(mh.lastBlock) < blockSize
|
||||||
sum, err := mh.tree.Root().Checksum()
|
sum, err := mh.tree.Root().Checksum()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
// XXX i hate to swallow an error here, but the `Sum() []byte` signature :-\
|
||||||
|
log.Printf("[ERROR]: %s", err)
|
||||||
}
|
}
|
||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
@ -63,7 +75,8 @@ func (mh *merkleHash) Write(b []byte) (int, error) {
|
||||||
offset int = 0
|
offset int = 0
|
||||||
)
|
)
|
||||||
if mh.lastBlock != nil && mh.lastBlockLen > 0 {
|
if mh.lastBlock != nil && mh.lastBlockLen > 0 {
|
||||||
numBytes = copy(curBlock[:], mh.lastBlock[:])
|
// XXX off by one?
|
||||||
|
numBytes = copy(curBlock[:], mh.lastBlock[:mh.lastBlockLen])
|
||||||
// not adding to numWritten, since these blocks were accounted for in a
|
// not adding to numWritten, since these blocks were accounted for in a
|
||||||
// prior Write()
|
// prior Write()
|
||||||
|
|
||||||
|
@ -71,8 +84,7 @@ func (mh *merkleHash) Write(b []byte) (int, error) {
|
||||||
offset = copy(curBlock[numBytes:], b[:(mh.blockSize-numBytes)])
|
offset = copy(curBlock[numBytes:], b[:(mh.blockSize-numBytes)])
|
||||||
n, err := NewNodeHashBlock(mh.hm, curBlock)
|
n, err := NewNodeHashBlock(mh.hm, curBlock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// XXX might need to stash again the prior lastBlock and first little
|
// XXX might need to stash again the prior lastBlock and first little chunk
|
||||||
// chunk
|
|
||||||
return numWritten, err
|
return numWritten, err
|
||||||
}
|
}
|
||||||
mh.tree.Nodes = append(mh.tree.Nodes, n)
|
mh.tree.Nodes = append(mh.tree.Nodes, n)
|
||||||
|
@ -81,12 +93,21 @@ func (mh *merkleHash) Write(b []byte) (int, error) {
|
||||||
|
|
||||||
numBytes = (len(b) - offset)
|
numBytes = (len(b) - offset)
|
||||||
for i := 0; i < numBytes/mh.blockSize; i++ {
|
for i := 0; i < numBytes/mh.blockSize; i++ {
|
||||||
// TODO Node for curBlock
|
//fmt.Printf("%s", b[offset:offset+mh.blockSize])
|
||||||
|
numWritten += copy(curBlock, b[offset:offset+mh.blockSize])
|
||||||
|
n, err := NewNodeHashBlock(mh.hm, curBlock)
|
||||||
|
if err != nil {
|
||||||
|
// XXX might need to stash again the prior lastBlock and first little chunk
|
||||||
|
return numWritten, err
|
||||||
|
}
|
||||||
|
mh.tree.Nodes = append(mh.tree.Nodes, n)
|
||||||
|
offset = offset + mh.blockSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO stash (numBytes % mh.blockSize) in mh.lastBlock
|
mh.lastBlockLen = numBytes % mh.blockSize
|
||||||
|
// XXX off by one?
|
||||||
|
numWritten += copy(mh.lastBlock[:], b[(len(b)-mh.lastBlockLen):])
|
||||||
|
|
||||||
// TODO if len(mh.lastBlock) < blockSize, then set that before returning
|
|
||||||
return numWritten, nil
|
return numWritten, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,42 @@
|
||||||
package merkle
|
package merkle
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
func TestMerkleHashWriter(t *testing.T) {
|
func TestMerkleHashWriter(t *testing.T) {
|
||||||
|
msg := "the quick brown fox jumps over the lazy dog"
|
||||||
|
h := NewHash(DefaultHashMaker, 10)
|
||||||
|
i, err := io.Copy(h, bytes.NewBufferString(msg))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if i != int64(len(msg)) {
|
||||||
|
t.Fatalf("expected to write %d, only wrote %d", len(msg), i)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
mh *merkleHash
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
if mh, ok = h.(*merkleHash); !ok {
|
||||||
|
t.Fatalf("expected to get merkleHash, but got %#t", h)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're left with a partial lastBlock
|
||||||
|
expectedNum := 4
|
||||||
|
if len(mh.tree.Nodes) != expectedNum {
|
||||||
|
t.Errorf("expected %d nodes, got %d", expectedNum, len(mh.tree.Nodes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next test Sum()
|
||||||
|
|
||||||
|
// count blocks again, we should get 5 nodes now
|
||||||
|
|
||||||
|
// Test Sum() again, ensure same sum
|
||||||
|
|
||||||
|
// Write more. This should pop the last node, and use the lastBlock.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue