1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package contains convenience methods and validator for content-addressed chunks
package content
import (
"encoding/binary"
"errors"
"fmt"
"github.com/ethersphere/bee/pkg/swarm"
bmtlegacy "github.com/ethersphere/bmt/legacy"
)
// NewChunk creates a new content-addressed single-span chunk.
// The length of the chunk data is set as the span.
func NewChunk(data []byte) (swarm.Chunk, error) {
return NewChunkWithSpan(data, int64(len(data)))
}
// NewChunkWithSpan creates a new content-addressed chunk from given data and span.
func NewChunkWithSpan(data []byte, span int64) (swarm.Chunk, error) {
if len(data) > swarm.ChunkSize {
return nil, errors.New("max chunk size exceeded")
}
if span < swarm.ChunkSize && span != int64(len(data)) {
return nil, fmt.Errorf("single-span chunk size mismatch; span is %d, chunk data length %d", span, len(data))
}
bmtPool := bmtlegacy.NewTreePool(swarm.NewHasher, swarm.Branches, bmtlegacy.PoolSize)
hasher := bmtlegacy.New(bmtPool)
// execute hash, compare and return result
spanBytes := make([]byte, 8)
binary.LittleEndian.PutUint64(spanBytes, uint64(span))
err := hasher.SetSpanBytes(spanBytes)
if err != nil {
return nil, err
}
_, err = hasher.Write(data)
if err != nil {
return nil, err
}
s := hasher.Sum(nil)
payload := append(spanBytes, data...)
address := swarm.NewAddress(s)
return swarm.NewChunk(address, payload), nil
}
// NewChunkWithSpanBytes deserializes a content-addressed chunk from separate
// data and span byte slices.
func NewChunkWithSpanBytes(data, spanBytes []byte) (swarm.Chunk, error) {
bmtPool := bmtlegacy.NewTreePool(swarm.NewHasher, swarm.Branches, bmtlegacy.PoolSize)
hasher := bmtlegacy.New(bmtPool)
// execute hash, compare and return result
err := hasher.SetSpanBytes(spanBytes)
if err != nil {
return nil, err
}
_, err = hasher.Write(data)
if err != nil {
return nil, err
}
s := hasher.Sum(nil)
payload := append(spanBytes, data...)
address := swarm.NewAddress(s)
return swarm.NewChunk(address, payload), nil
}
// contentChunkFromBytes deserializes a content-addressed chunk.
func contentChunkFromBytes(chunkData []byte) (swarm.Chunk, error) {
if len(chunkData) < swarm.SpanSize {
return nil, errors.New("shorter than minimum length")
}
return NewChunkWithSpanBytes(chunkData[8:], chunkData[:8])
}