forked from celestiaorg/celestia-app
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshare_sequence.go
142 lines (124 loc) · 3.81 KB
/
share_sequence.go
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package shares
import (
"fmt"
"github.com/celestiaorg/celestia-app/pkg/appconsts"
appns "github.com/celestiaorg/celestia-app/pkg/namespace"
)
// ShareSequence represents a contiguous sequence of shares that are part of the
// same namespace and blob. For compact shares, one share sequence exists per
// reserved namespace. For sparse shares, one share sequence exists per blob.
type ShareSequence struct {
Namespace appns.Namespace
Shares []Share
}
// RawData returns the raw share data of this share sequence. The raw data does
// not contain the namespace ID, info byte, sequence length, or reserved bytes.
func (s ShareSequence) RawData() (data []byte, err error) {
for _, share := range s.Shares {
raw, err := share.RawData()
if err != nil {
return []byte{}, err
}
data = append(data, raw...)
}
sequenceLen, err := s.SequenceLen()
if err != nil {
return []byte{}, err
}
// trim any padding that may have been added to the last share
return data[:sequenceLen], nil
}
func (s ShareSequence) SequenceLen() (uint32, error) {
if len(s.Shares) == 0 {
return 0, fmt.Errorf("invalid sequence length because share sequence %v has no shares", s)
}
firstShare := s.Shares[0]
return firstShare.SequenceLen()
}
// validSequenceLen extracts the sequenceLen written to the first share
// and returns an error if the number of shares needed to store a sequence of
// length sequenceLen doesn't match the number of shares in this share
// sequence. Returns nil if there is no error.
func (s ShareSequence) validSequenceLen() error {
if len(s.Shares) == 0 {
return fmt.Errorf("invalid sequence length because share sequence %v has no shares", s)
}
isPadding, err := s.isPadding()
if err != nil {
return err
}
if isPadding {
return nil
}
firstShare := s.Shares[0]
sharesNeeded, err := numberOfSharesNeeded(firstShare)
if err != nil {
return err
}
if len(s.Shares) != sharesNeeded {
return fmt.Errorf("share sequence has %d shares but needed %d shares", len(s.Shares), sharesNeeded)
}
return nil
}
func (s ShareSequence) isPadding() (bool, error) {
if len(s.Shares) != 1 {
return false, nil
}
isPadding, err := s.Shares[0].IsPadding()
if err != nil {
return false, err
}
return isPadding, nil
}
// numberOfSharesNeeded extracts the sequenceLen written to the share
// firstShare and returns the number of shares needed to store a sequence of
// that length.
func numberOfSharesNeeded(firstShare Share) (sharesUsed int, err error) {
sequenceLen, err := firstShare.SequenceLen()
if err != nil {
return 0, err
}
isCompact, err := firstShare.IsCompactShare()
if err != nil {
return 0, err
}
if isCompact {
return CompactSharesNeeded(int(sequenceLen)), nil
}
return SparseSharesNeeded(sequenceLen), nil
}
// CompactSharesNeeded returns the number of compact shares needed to store a
// sequence of length sequenceLen. The parameter sequenceLen is the number
// of bytes of transactions or intermediate state roots in a sequence.
func CompactSharesNeeded(sequenceLen int) (sharesNeeded int) {
if sequenceLen == 0 {
return 0
}
if sequenceLen < appconsts.FirstCompactShareContentSize {
return 1
}
bytesAvailable := appconsts.FirstCompactShareContentSize
sharesNeeded++
for bytesAvailable < sequenceLen {
bytesAvailable += appconsts.ContinuationCompactShareContentSize
sharesNeeded++
}
return sharesNeeded
}
// SparseSharesNeeded returns the number of shares needed to store a sequence of
// length sequenceLen.
func SparseSharesNeeded(sequenceLen uint32) (sharesNeeded int) {
if sequenceLen == 0 {
return 0
}
if sequenceLen < appconsts.FirstSparseShareContentSize {
return 1
}
bytesAvailable := appconsts.FirstSparseShareContentSize
sharesNeeded++
for uint32(bytesAvailable) < sequenceLen {
bytesAvailable += appconsts.ContinuationSparseShareContentSize
sharesNeeded++
}
return sharesNeeded
}