forked from dymensionxyz/dymint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathda.go
210 lines (182 loc) · 6.78 KB
/
da.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
package da
import (
"encoding/hex"
"fmt"
"strconv"
"strings"
"github.com/cometbft/cometbft/crypto/merkle"
"github.com/dymensionxyz/dymint/store"
"github.com/dymensionxyz/dymint/types"
"github.com/rollkit/celestia-openrpc/types/blob"
"github.com/tendermint/tendermint/libs/pubsub"
)
// StatusCode is a type for DA layer return status.
// TODO: define an enum of different non-happy-path cases
// that might need to be handled by Dymint independent of
// the underlying DA chain.
type StatusCode uint64
// Commitment should contain serialized cryptographic commitment to Blob value.
type Commitment = []byte
// Blob is the data submitted/received from DA interface.
type Blob = []byte
// Data Availability return codes.
const (
StatusUnknown StatusCode = iota
StatusSuccess
StatusError
)
// Client defines all the possible da clients
type Client string
// Data availability clients
const (
Mock Client = "mock"
Celestia Client = "celestia"
Avail Client = "avail"
)
// Option is a function that sets a parameter on the da layer.
type Option func(DataAvailabilityLayerClient)
// BaseResult contains basic information returned by DA layer.
type BaseResult struct {
// Code is to determine if the action succeeded.
Code StatusCode
// Message may contain DA layer specific information (like DA block height/hash, detailed error message, etc)
Message string
// Error is the error returned by the DA layer
Error error
}
// DAMetaData contains meta data about a batch on the Data Availability Layer.
type DASubmitMetaData struct {
// Height is the height of the block in the da layer
Height uint64
// Namespace ID
Namespace []byte
// Client is the client to use to fetch data from the da layer
Client Client
// Share commitment, for each blob, used to obtain blobs and proofs
Commitment Commitment
// Initial position for each blob in the NMT
Index int
// Number of shares of each blob
Length int
// any NMT root for the specific height, necessary for non-inclusion proof
Root []byte
}
// ToPath converts a DAMetaData to a path.
func (d *DASubmitMetaData) ToPath() string {
// convert uint64 to string
if d.Commitment != nil {
commitment := hex.EncodeToString(d.Commitment)
dataroot := hex.EncodeToString(d.Root)
path := []string{string(d.Client), ".", strconv.FormatUint(d.Height, 10), ".", strconv.Itoa(d.Index), ".", strconv.Itoa(d.Length), ".", commitment, ".", string(d.Namespace), ".", dataroot}
return strings.Join(path, "")
} else {
path := []string{string(d.Client), ".", strconv.FormatUint(d.Height, 10)}
return strings.Join(path, "")
}
}
// FromPath parses a path to a DAMetaData.
func (d *DASubmitMetaData) FromPath(path string) (*DASubmitMetaData, error) {
pathParts := strings.FieldsFunc(path, func(r rune) bool { return r == '.' })
if len(pathParts) < 2 {
return nil, fmt.Errorf("invalid DA path")
}
height, err := strconv.ParseUint(pathParts[1], 10, 64)
if err != nil {
return nil, err
}
submitData := &DASubmitMetaData{
Height: height,
Client: Client(pathParts[0]),
}
if len(pathParts) == 7 {
submitData.Index, err = strconv.Atoi(pathParts[2])
if err != nil {
return nil, err
}
submitData.Length, err = strconv.Atoi(pathParts[3])
if err != nil {
return nil, err
}
submitData.Commitment, err = hex.DecodeString(pathParts[4])
if err != nil {
return nil, err
}
submitData.Namespace = []byte(pathParts[5])
submitData.Root, err = hex.DecodeString(pathParts[6])
if err != nil {
return nil, err
}
}
return submitData, nil
}
// DAMetaData contains meta data about a batch on the Data Availability Layer.
type DACheckMetaData struct {
// Height is the height of the block in the da layer
Height uint64
// Client is the client to use to fetch data from the da layer
Client Client
// Submission index in the Hub
SLIndex uint64
// Namespace ID
Namespace []byte
// Share commitment, for each blob, used to obtain blobs and proofs
Commitment Commitment
// Initial position for each blob in the NMT
Index int
// Number of shares of each blob
Length int
// Proofs necessary to validate blob inclusion in the specific height
Proofs []*blob.Proof
// NMT roots for each NMT Proof
NMTRoots []byte
// Proofs necessary to validate blob inclusion in the specific height
RowProofs []*merkle.Proof
// any NMT root for the specific height, necessary for non-inclusion proof
Root []byte
}
// ResultSubmitBatch contains information returned from DA layer after block submission.
type ResultSubmitBatch struct {
BaseResult
// DAHeight informs about a height on Data Availability Layer for given result.
SubmitMetaData *DASubmitMetaData
}
// ResultCheckBatch contains information about block availability, returned from DA layer client.
type ResultCheckBatch struct {
BaseResult
// DAHeight informs about a height on Data Availability Layer for given result.
CheckMetaData *DACheckMetaData
}
// ResultRetrieveBatch contains batch of blocks returned from DA layer client.
type ResultRetrieveBatch struct {
BaseResult
// Block is the full block retrieved from Data Availability Layer.
// If Code is not equal to StatusSuccess, it has to be nil.
Batches []*types.Batch
// DAHeight informs about a height on Data Availability Layer for given result.
CheckMetaData *DACheckMetaData
}
// DataAvailabilityLayerClient defines generic interface for DA layer block submission.
// It also contains life-cycle methods.
type DataAvailabilityLayerClient interface {
// Init is called once to allow DA client to read configuration and initialize resources.
Init(config []byte, pubsubServer *pubsub.Server, kvStore store.KVStore, logger types.Logger, options ...Option) error
// Start is called once, after Init. It's implementation should start operation of DataAvailabilityLayerClient.
Start() error
// Stop is called once, when DataAvailabilityLayerClient is no longer needed.
Stop() error
// SubmitBatch submits the passed in block to the DA layer.
// This should create a transaction which (potentially)
// triggers a state transition in the DA layer.
SubmitBatch(batch *types.Batch) ResultSubmitBatch
GetClientType() Client
// CheckBatchAvailability checks the availability of the blob submitted getting proofs and validating them
CheckBatchAvailability(daMetaData *DASubmitMetaData) ResultCheckBatch
}
// BatchRetriever is additional interface that can be implemented by Data Availability Layer Client that is able to retrieve
// block data from DA layer. This gives the ability to use it for block synchronization.
type BatchRetriever interface {
// RetrieveBatches returns blocks at given data layer height from data availability layer.
RetrieveBatches(daMetaData *DASubmitMetaData) ResultRetrieveBatch
// CheckBatchAvailability checks the availability of the blob received getting proofs and validating them
CheckBatchAvailability(daMetaData *DASubmitMetaData) ResultCheckBatch
}