2 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
3 Copyright (C) 2016-2023 Sergey Matveev <stargrave@stargrave.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 3 of the License.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 "lukechampine.com/blake3"
32 MTHBlockSize = 128 * 1024
37 MTHLeafKey = blake3.Sum256([]byte("NNCP MTH LEAF"))
38 MTHNodeKey = blake3.Sum256([]byte("NNCP MTH NODE"))
41 type MTHSeqEnt struct {
47 func (ent *MTHSeqEnt) String() string {
48 return fmt.Sprintf("%03d\t%06d\t%s", ent.l, ent.c, hex.EncodeToString(ent.h[:]))
51 type MTHEventType string
54 MTHEventAdd MTHEventType = "Add"
55 MTHEventPreadd MTHEventType = "Pre"
56 MTHEventFold MTHEventType = "Fold"
59 type MTHEvent struct {
64 func (e MTHEvent) String() string {
65 return fmt.Sprintf("%s\t%s", e.Type, e.Ent.String())
70 PreaddFrom(r io.Reader, pktName string, showPrgrs bool) (int64, error)
72 Events() chan MTHEvent
76 hasherLeaf *blake3.Hasher
77 hasherNode *blake3.Hasher
88 func MTHSeqNew(size, offset int64) *MTHSeq {
90 hasherLeaf: blake3.New(MTHSize, MTHLeafKey[:]),
91 hasherNode: blake3.New(MTHSize, MTHNodeKey[:]),
92 buf: bytes.NewBuffer(make([]byte, 0, 2*MTHBlockSize)),
97 prepends := offset / MTHBlockSize
98 toSkip := MTHBlockSize - (offset - prepends*MTHBlockSize)
99 if toSkip == MTHBlockSize {
101 } else if toSkip > 0 {
104 prependSize := prepends * MTHBlockSize
106 if prependSize > size {
109 if offset+toSkip > size {
110 toSkip = size - offset
113 mth.prependSize = prependSize
118 func (mth *MTHSeq) Reset() { panic("not implemented") }
120 func (mth *MTHSeq) Size() int { return MTHSize }
122 func (mth *MTHSeq) BlockSize() int { return MTHBlockSize }
124 func (mth *MTHSeq) PreaddFrom(r io.Reader, pktName string, showPrgrs bool) (int64, error) {
126 return 0, errors.New("already Sum()ed")
128 if mth.buf.Len() > 0 {
129 if _, err := mth.hasherLeaf.Write(mth.buf.Next(MTHBlockSize)); err != nil {
135 prevHashes := mth.hashes
139 lr := io.LimitedReader{R: r, N: mth.prependSize}
140 les := LEs{{"Pkt", pktName}, {"FullSize", mth.prependSize}}
141 n, err := CopyProgressed(mth, &lr, "prehash", les, showPrgrs)
142 for _, ent := range prevHashes {
143 mth.hashes = append(mth.hashes, ent)
146 if mth.buf.Len() > 0 {
147 mth.ctr = prevCtr - 1
154 func (mth *MTHSeq) Events() chan MTHEvent {
155 mth.events = make(chan MTHEvent)
159 func (mth *MTHSeq) PreaddSize() int64 { return mth.prependSize }
161 func (mth *MTHSeq) leafAdd() {
162 ent := MTHSeqEnt{c: mth.ctr}
163 mth.hasherLeaf.Sum(ent.h[:0])
164 mth.hasherLeaf.Reset()
165 mth.hashes = append(mth.hashes, ent)
167 if mth.events != nil {
168 mth.events <- MTHEvent{MTHEventAdd, &ent}
172 func (mth *MTHSeq) fold() {
173 for len(mth.hashes) >= 2 {
174 hlen := len(mth.hashes)
175 end1 := &mth.hashes[hlen-2]
176 end0 := &mth.hashes[hlen-1]
180 if end1.l != end0.l {
183 if _, err := mth.hasherNode.Write(end1.h[:]); err != nil {
186 if _, err := mth.hasherNode.Write(end0.h[:]); err != nil {
189 mth.hashes = mth.hashes[:hlen-1]
192 mth.hasherNode.Sum(end1.h[:0])
193 mth.hasherNode.Reset()
194 if mth.events != nil {
195 mth.events <- MTHEvent{MTHEventFold, end1}
200 func (mth *MTHSeq) Write(data []byte) (int, error) {
202 return 0, errors.New("already Sum()ed")
204 n, err := mth.buf.Write(data)
209 if int64(mth.buf.Len()) < mth.toSkip {
212 mth.buf.Next(int(mth.toSkip))
215 for mth.buf.Len() >= MTHBlockSize {
216 if _, err = mth.hasherLeaf.Write(mth.buf.Next(MTHBlockSize)); err != nil {
225 func (mth *MTHSeq) Sum(b []byte) []byte {
227 return append(b, mth.hashes[0].h[:]...)
229 if mth.buf.Len() > 0 {
230 if _, err := mth.hasherLeaf.Write(mth.buf.Next(MTHBlockSize)); err != nil {
238 if _, err := mth.hasherLeaf.Write(nil); err != nil {
244 ent := MTHSeqEnt{c: 1}
245 copy(ent.h[:], mth.hashes[0].h[:])
247 mth.hashes = append(mth.hashes, ent)
248 if mth.events != nil {
249 mth.events <- MTHEvent{MTHEventAdd, &ent}
253 for len(mth.hashes) >= 2 {
254 hlen := len(mth.hashes)
255 end1 := &mth.hashes[hlen-2]
256 end0 := &mth.hashes[hlen-1]
259 if mth.events != nil {
260 mth.events <- MTHEvent{MTHEventAdd, end0}
265 if mth.events != nil {
268 return append(b, mth.hashes[0].h[:]...)
271 func MTHNew(size, offset int64) MTH {
272 return MTHSeqNew(size, offset)
275 // Some kind of reference implementation (fat, because eats memory)
278 hasher *blake3.Hasher
279 hashes [][MTHSize]byte
284 func MTHFatNew() *MTHFat {
286 hasher: blake3.New(MTHSize, MTHLeafKey[:]),
287 buf: bytes.NewBuffer(make([]byte, 0, 2*MTHBlockSize)),
291 func (mth *MTHFat) Events() chan MTHEvent {
292 mth.events = make(chan MTHEvent)
296 func (mth *MTHFat) Write(data []byte) (int, error) {
297 n, err := mth.buf.Write(data)
301 for mth.buf.Len() >= MTHBlockSize {
302 if _, err = mth.hasher.Write(mth.buf.Next(MTHBlockSize)); err != nil {
305 h := new([MTHSize]byte)
306 mth.hasher.Sum(h[:0])
308 mth.hashes = append(mth.hashes, *h)
309 if mth.events != nil {
310 mth.events <- MTHEvent{
313 0, int64(len(mth.hashes) - 1),
314 mth.hashes[len(mth.hashes)-1],
322 func (mth *MTHFat) Sum(b []byte) []byte {
323 if mth.buf.Len() > 0 {
324 b := mth.buf.Next(MTHBlockSize)
325 if _, err := mth.hasher.Write(b); err != nil {
328 h := new([MTHSize]byte)
329 mth.hasher.Sum(h[:0])
331 mth.hashes = append(mth.hashes, *h)
332 if mth.events != nil {
333 mth.events <- MTHEvent{
336 0, int64(len(mth.hashes) - 1),
337 mth.hashes[len(mth.hashes)-1],
342 switch len(mth.hashes) {
344 h := new([MTHSize]byte)
345 if _, err := mth.hasher.Write(nil); err != nil {
348 mth.hasher.Sum(h[:0])
350 mth.hashes = append(mth.hashes, *h)
351 if mth.events != nil {
352 mth.events <- MTHEvent{MTHEventAdd, &MTHSeqEnt{0, 0, mth.hashes[0]}}
356 mth.hashes = append(mth.hashes, mth.hashes[0])
357 if mth.events != nil {
358 mth.events <- MTHEvent{MTHEventAdd, &MTHSeqEnt{0, 1, mth.hashes[1]}}
361 mth.hasher = blake3.New(MTHSize, MTHNodeKey[:])
363 for len(mth.hashes) != 1 {
364 hashesUp := make([][MTHSize]byte, 0, 1+len(mth.hashes)/2)
365 pairs := (len(mth.hashes) / 2) * 2
366 for i := 0; i < pairs; i += 2 {
367 if _, err := mth.hasher.Write(mth.hashes[i][:]); err != nil {
370 if _, err := mth.hasher.Write(mth.hashes[i+1][:]); err != nil {
373 h := new([MTHSize]byte)
374 mth.hasher.Sum(h[:0])
376 hashesUp = append(hashesUp, *h)
377 if mth.events != nil {
378 mth.events <- MTHEvent{
381 level, int64(len(hashesUp) - 1),
382 hashesUp[len(hashesUp)-1],
387 if len(mth.hashes)%2 == 1 {
388 hashesUp = append(hashesUp, mth.hashes[len(mth.hashes)-1])
389 if mth.events != nil {
390 mth.events <- MTHEvent{
393 level, int64(len(hashesUp) - 1),
394 hashesUp[len(hashesUp)-1],
399 mth.hashes = hashesUp
402 if mth.events != nil {
405 return append(b, mth.hashes[0][:]...)