]> Sergey Matveev's repositories - btrtrc.git/blob - merkle/hash.go
1a8f67a92288a243a772892bf88813620e3bb261
[btrtrc.git] / merkle / hash.go
1 package merkle
2
3 import (
4         "crypto/sha256"
5         "hash"
6 )
7
8 func NewHash() *Hash {
9         return &Hash{
10                 nextBlock: sha256.New(),
11         }
12 }
13
14 type Hash struct {
15         blocks    [][32]byte
16         nextBlock hash.Hash
17         written   int
18 }
19
20 func (h *Hash) remaining() int {
21         return BlockSize - h.written
22 }
23
24 func (h *Hash) Write(p []byte) (n int, err error) {
25         for len(p) > 0 {
26                 var n1 int
27                 n1, err = h.nextBlock.Write(p[:min(len(p), h.remaining())])
28                 n += n1
29                 h.written += n1
30                 p = p[n1:]
31                 if h.remaining() == 0 {
32                         h.blocks = append(h.blocks, h.nextBlockSum())
33                         h.nextBlock.Reset()
34                         h.written = 0
35                 }
36                 if err != nil {
37                         break
38                 }
39         }
40         return
41 }
42
43 func (h *Hash) nextBlockSum() (sum [32]byte) {
44         h.nextBlock.Sum(sum[:0])
45         return
46 }
47
48 func (h *Hash) Sum(b []byte) []byte {
49         blocks := h.blocks
50         if h.written != 0 {
51                 blocks = append(blocks, h.nextBlockSum())
52         }
53         sum := RootWithPadHash(blocks, [32]byte{})
54         return append(b, sum[:]...)
55 }
56
57 func (h *Hash) Reset() {
58         h.blocks = h.blocks[:0]
59         h.nextBlock.Reset()
60 }
61
62 func (h *Hash) Size() int {
63         return 32
64 }
65
66 func (h *Hash) BlockSize() int {
67         return h.nextBlock.BlockSize()
68 }
69
70 var _ hash.Hash = (*Hash)(nil)