-
-type MTHSeqEnt struct {
- l int64
- h [MTHSize]byte
-}
-
-type MTHSeq struct {
- hasherLeaf *blake3.Hasher
- hasherNode *blake3.Hasher
- hashes []MTHSeqEnt
- buf *bytes.Buffer
- events chan MTHEvent
- ctrs []int64
- finished bool
-}
-
-func MTHSeqNew() *MTHSeq {
- mth := MTHSeq{
- hasherLeaf: blake3.New(MTHSize, MTHLeafKey[:]),
- hasherNode: blake3.New(MTHSize, MTHNodeKey[:]),
- buf: bytes.NewBuffer(make([]byte, 0, 2*MTHBlockSize)),
- ctrs: make([]int64, 1, 2),
- }
- return &mth
-}
-
-func (mth *MTHSeq) Reset() { panic("not implemented") }
-
-func (mth *MTHSeq) Size() int { return MTHSize }
-
-func (mth *MTHSeq) BlockSize() int { return MTHBlockSize }
-
-func (mth *MTHSeq) PrependFrom(r io.Reader) (int64, error) {
- panic("must not reach that code")
-}
-
-func (mth *MTHSeq) Events() chan MTHEvent {
- mth.events = make(chan MTHEvent)
- return mth.events
-}
-
-func (mth *MTHSeq) SetPktName(pktName string) {}
-
-func (mth *MTHSeq) PrependSize() int64 { return 0 }
-
-func (mth *MTHSeq) leafAdd() {
- ent := MTHSeqEnt{l: 0}
- mth.hasherLeaf.Sum(ent.h[:0])
- mth.hasherLeaf.Reset()
- mth.hashes = append(mth.hashes, ent)
- if mth.events != nil {
- mth.events <- MTHEvent{
- MTHEventAppend, 0, mth.ctrs[0],
- mth.hashes[len(mth.hashes)-1].h[:],
- }
- }
- mth.ctrs[0]++
-}
-
-func (mth *MTHSeq) incr(l int64) {
- if int64(len(mth.ctrs)) <= l {
- mth.ctrs = append(mth.ctrs, 0)
- } else {
- mth.ctrs[l]++
- }
-}
-
-func (mth *MTHSeq) fold() {
- for len(mth.hashes) >= 2 {
- if mth.hashes[len(mth.hashes)-2].l != mth.hashes[len(mth.hashes)-1].l {
- break
- }
- if _, err := mth.hasherNode.Write(mth.hashes[len(mth.hashes)-2].h[:]); err != nil {
- panic(err)
- }
- if _, err := mth.hasherNode.Write(mth.hashes[len(mth.hashes)-1].h[:]); err != nil {
- panic(err)
- }
- mth.hashes = mth.hashes[:len(mth.hashes)-1]
- end := &mth.hashes[len(mth.hashes)-1]
- end.l++
- mth.incr(end.l)
- mth.hasherNode.Sum(end.h[:0])
- mth.hasherNode.Reset()
- if mth.events != nil {
- mth.events <- MTHEvent{MTHEventFold, end.l, mth.ctrs[end.l], end.h[:]}
- }
- }
-}
-
-func (mth *MTHSeq) Write(data []byte) (int, error) {
- if mth.finished {
- return 0, errors.New("already Sum()ed")
- }
- n, err := mth.buf.Write(data)
- if err != nil {
- return n, err
- }
- for mth.buf.Len() >= MTHBlockSize {
- if _, err = mth.hasherLeaf.Write(mth.buf.Next(MTHBlockSize)); err != nil {
- return n, err
- }
- mth.leafAdd()
- mth.fold()
- }
- return n, err
-}
-
-func (mth *MTHSeq) Sum(b []byte) []byte {
- if mth.finished {
- return append(b, mth.hashes[0].h[:]...)
- }
- if mth.buf.Len() > 0 {
- if _, err := mth.hasherLeaf.Write(mth.buf.Next(MTHBlockSize)); err != nil {
- panic(err)
- }
- mth.leafAdd()
- mth.fold()
- }
- switch mth.ctrs[0] {
- case 0:
- if _, err := mth.hasherLeaf.Write(nil); err != nil {
- panic(err)
- }
- mth.leafAdd()
- fallthrough
- case 1:
- mth.hashes = append(mth.hashes, mth.hashes[0])
- mth.ctrs[0]++
- if mth.events != nil {
- mth.events <- MTHEvent{
- MTHEventAppend, 0, mth.ctrs[0],
- mth.hashes[len(mth.hashes)-1].h[:],
- }
- }
- mth.fold()
- }
- for len(mth.hashes) >= 2 {
- l := mth.hashes[len(mth.hashes)-2].l
- mth.incr(l)
- mth.hashes[len(mth.hashes)-1].l = l
- if mth.events != nil {
- mth.events <- MTHEvent{
- MTHEventAppend, l, mth.ctrs[l],
- mth.hashes[len(mth.hashes)-1].h[:],
- }
- }
- mth.fold()
- }
- mth.finished = true
- if mth.events != nil {
- close(mth.events)
- }
- return append(b, mth.hashes[0].h[:]...)
-}
-
-func MTHNew(size, offset int64) MTH {
- if offset == 0 {
- return MTHSeqNew()
- }
- return MTHFatNew(size, offset)
-}