-
Notifications
You must be signed in to change notification settings - Fork 973
/
Copy pathadd.go
101 lines (94 loc) · 2.99 KB
/
add.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
package share
import (
"context"
"fmt"
"math"
"github.com/ipfs/go-blockservice"
"github.com/celestiaorg/celestia-app/pkg/wrapper"
"github.com/celestiaorg/celestia-node/share/ipld"
"github.com/celestiaorg/nmt"
"github.com/celestiaorg/rsmt2d"
)
// AddShares erasures and extends shares to blockservice.BlockService using the provided
// ipld.NodeAdder.
func AddShares(
ctx context.Context,
shares []Share,
adder blockservice.BlockService,
) (*rsmt2d.ExtendedDataSquare, error) {
if len(shares) == 0 {
return nil, fmt.Errorf("empty data") // empty block is not an empty Data
}
squareSize := int(math.Sqrt(float64(len(shares))))
// create nmt adder wrapping batch adder with calculated size
batchAdder := ipld.NewNmtNodeAdder(ctx, adder, ipld.MaxSizeBatchOption(squareSize*2))
// create the nmt wrapper to generate row and col commitments
// recompute the eds
eds, err := rsmt2d.ComputeExtendedDataSquare(
shares,
DefaultRSMT2DCodec(),
wrapper.NewConstructor(uint64(squareSize),
nmt.NodeVisitor(batchAdder.Visit)),
)
if err != nil {
return nil, fmt.Errorf("failure to recompute the extended data square: %w", err)
}
// compute roots
eds.RowRoots()
// commit the batch to ipfs
return eds, batchAdder.Commit()
}
// ImportShares imports flattend chunks of data into Extended Data square and saves it in
// blockservice.BlockService
func ImportShares(
ctx context.Context,
shares [][]byte,
adder blockservice.BlockService) (*rsmt2d.ExtendedDataSquare, error) {
if len(shares) == 0 {
return nil, fmt.Errorf("ipld: importing empty data")
}
squareSize := int(math.Sqrt(float64(len(shares))))
// create nmt adder wrapping batch adder with calculated size
batchAdder := ipld.NewNmtNodeAdder(ctx, adder, ipld.MaxSizeBatchOption(squareSize*2))
// recompute the eds
eds, err := rsmt2d.ImportExtendedDataSquare(
shares,
DefaultRSMT2DCodec(),
wrapper.NewConstructor(uint64(squareSize/2),
nmt.NodeVisitor(batchAdder.Visit)),
)
if err != nil {
return nil, fmt.Errorf("failure to recompute the extended data square: %w", err)
}
// compute roots
eds.RowRoots()
// commit the batch to DAG
return eds, batchAdder.Commit()
}
// ExtractODS returns the original shares of the given ExtendedDataSquare. This
// is a helper function for circumstances where AddShares must be used after the EDS has already
// been generated.
func ExtractODS(eds *rsmt2d.ExtendedDataSquare) []Share {
origWidth := eds.Width() / 2
origShares := make([][]byte, origWidth*origWidth)
for i := uint(0); i < origWidth; i++ {
row := eds.Row(i)
for j := uint(0); j < origWidth; j++ {
origShares[(i*origWidth)+j] = row[j]
}
}
return origShares
}
// ExtractEDS takes an EDS and extracts all shares from it in a flattened slice(row by row).
func ExtractEDS(eds *rsmt2d.ExtendedDataSquare) []Share {
flattenedEDSSize := eds.Width() * eds.Width()
out := make([][]byte, flattenedEDSSize)
count := 0
for i := uint(0); i < eds.Width(); i++ {
for _, share := range eds.Row(i) {
out[count] = share
count++
}
}
return out
}