-
Notifications
You must be signed in to change notification settings - Fork 267
/
share_merging.go
134 lines (110 loc) · 3.31 KB
/
share_merging.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
package shares
import (
"bytes"
"github.com/celestiaorg/celestia-app/pkg/appconsts"
"github.com/celestiaorg/rsmt2d"
"github.com/gogo/protobuf/proto"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
coretypes "github.com/tendermint/tendermint/types"
)
// Merge extracts block data from an extended data square.
func Merge(eds *rsmt2d.ExtendedDataSquare) (coretypes.Data, error) {
squareSize := eds.Width() / 2
// sort block data shares by namespace
var (
sortedTxShares [][]byte
sortedEvdShares [][]byte
sortedMsgShares [][]byte
)
// iterate over each row index
for x := uint(0); x < squareSize; x++ {
// iterate over each share in the original data square
row := eds.Row(x)
for _, share := range row[:squareSize] {
// sort the data of that share types via namespace
nid := share[:appconsts.NamespaceSize]
switch {
case bytes.Equal(appconsts.TxNamespaceID, nid):
sortedTxShares = append(sortedTxShares, share)
case bytes.Equal(appconsts.EvidenceNamespaceID, nid):
sortedEvdShares = append(sortedEvdShares, share)
case bytes.Equal(appconsts.TailPaddingNamespaceID, nid):
continue
// ignore unused but reserved namespaces
case bytes.Compare(nid, appconsts.MaxReservedNamespace) < 1:
continue
// every other namespaceID should be a message
default:
sortedMsgShares = append(sortedMsgShares, share)
}
}
}
// pass the raw share data to their respective parsers
txs, err := ParseTxs(sortedTxShares)
if err != nil {
return coretypes.Data{}, err
}
evd, err := ParseEvd(sortedEvdShares)
if err != nil {
return coretypes.Data{}, err
}
msgs, err := ParseMsgs(sortedMsgShares)
if err != nil {
return coretypes.Data{}, err
}
return coretypes.Data{
Txs: txs,
Evidence: evd,
Messages: msgs,
OriginalSquareSize: uint64(squareSize),
}, nil
}
// ParseTxs collects all of the transactions from the shares provided
func ParseTxs(shares [][]byte) (coretypes.Txs, error) {
// parse the sharse
rawTxs, err := parseCompactShares(shares)
if err != nil {
return nil, err
}
// convert to the Tx type
txs := make(coretypes.Txs, len(rawTxs))
for i := 0; i < len(txs); i++ {
txs[i] = coretypes.Tx(rawTxs[i])
}
return txs, nil
}
// ParseEvd collects all evidence from the shares provided.
func ParseEvd(shares [][]byte) (coretypes.EvidenceData, error) {
// the raw data returned does not have length delimiters or namespaces and
// is ready to be unmarshaled
rawEvd, err := parseCompactShares(shares)
if err != nil {
return coretypes.EvidenceData{}, err
}
evdList := make(coretypes.EvidenceList, len(rawEvd))
// parse into protobuf bytes
for i := 0; i < len(rawEvd); i++ {
// unmarshal the evidence
var protoEvd tmproto.Evidence
err := proto.Unmarshal(rawEvd[i], &protoEvd)
if err != nil {
return coretypes.EvidenceData{}, err
}
evd, err := coretypes.EvidenceFromProto(&protoEvd)
if err != nil {
return coretypes.EvidenceData{}, err
}
evdList[i] = evd
}
return coretypes.EvidenceData{Evidence: evdList}, nil
}
// ParseMsgs collects all messages from the shares provided
func ParseMsgs(shares [][]byte) (coretypes.Messages, error) {
msgList, err := parseSparseShares(shares)
if err != nil {
return coretypes.Messages{}, err
}
return coretypes.Messages{
MessagesList: msgList,
}, nil
}