-
Notifications
You must be signed in to change notification settings - Fork 201
/
Copy pathdisperser.proto
252 lines (222 loc) · 9.94 KB
/
disperser.proto
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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
syntax = "proto3";
package disperser;
import "common/common.proto";
option go_package = "github.com/Layr-Labs/eigenda/api/grpc/disperser";
// Disperser defines the public APIs for dispersing blobs.
service Disperser {
// This API accepts blob to disperse from clients.
// This executes the dispersal async, i.e. it returns once the request
// is accepted. The client could use GetBlobStatus() API to poll the the
// processing status of the blob.
rpc DisperseBlob(DisperseBlobRequest) returns (DisperseBlobReply) {}
// DisperseBlobAuthenticated is similar to DisperseBlob, except that it requires the
// client to authenticate itself via the AuthenticationData message. The protoco is as follows:
// 1. The client sends a DisperseBlobAuthenticated request with the DisperseBlobRequest message
// 2. The Disperser sends back a BlobAuthHeader message containing information for the client to
// verify and sign.
// 3. The client verifies the BlobAuthHeader and sends back the signed BlobAuthHeader in an
// AuthenticationData message.
// 4. The Disperser verifies the signature and returns a DisperseBlobReply message.
rpc DisperseBlobAuthenticated(stream AuthenticatedRequest) returns (stream AuthenticatedReply);
// This API is meant to be polled for the blob status.
rpc GetBlobStatus(BlobStatusRequest) returns (BlobStatusReply) {}
// This retrieves the requested blob from the Disperser's backend.
// This is a more efficient way to retrieve blobs than directly retrieving
// from the DA Nodes (see detail about this approach in
// api/proto/retriever/retriever.proto).
// The blob should have been initially dispersed via this Disperser service
// for this API to work.
rpc RetrieveBlob(RetrieveBlobRequest) returns (RetrieveBlobReply) {}
}
// Requests and Responses
// Authenicated Message Types
message AuthenticatedRequest {
oneof payload {
DisperseBlobRequest disperse_request = 1;
AuthenticationData authentication_data = 2;
}
}
message AuthenticatedReply {
oneof payload {
BlobAuthHeader blob_auth_header = 1;
DisperseBlobReply disperse_reply = 2;
}
}
// BlobAuthHeader contains information about the blob for the client to verify and sign.
// - Once payments are enabled, the BlobAuthHeader will contain the KZG commitment to the blob, which the client
// will verify and sign. Having the client verify the KZG commitment instead of calculating it avoids
// the need for the client to have the KZG structured reference string (SRS), which can be large.
// The signed KZG commitment prevents the disperser from sending a different blob to the DA Nodes
// than the one the client sent.
// - In the meantime, the BlobAuthHeader contains a simple challenge parameter is used to prevent
// replay attacks in the event that a signature is leaked.
message BlobAuthHeader {
uint32 challenge_parameter = 1;
}
// AuthenticationData contains the signature of the BlobAuthHeader.
message AuthenticationData {
bytes authentication_data = 1;
}
message DisperseBlobRequest {
// The data to be dispersed.
// The size of data must be <= 2MiB. Every 32 bytes of data chunk is interpreted as an integer in big endian format
// where the lower address has more significant bits. The integer must stay in the valid range to be interpreted
// as a field element on the bn254 curve. The valid range is
// 0 <= x < 21888242871839275222246405745257275088548364400416034343698204186575808495617
// containing slightly less than 254 bits and more than 253 bits. If any one of the 32 bytes chunk is outside the range,
// the whole request is deemed as invalid, and rejected.
bytes data = 1;
// The quorums to which the blob will be sent, in addition to the required quorums which are configured
// on the EigenDA smart contract. If required quorums are included here, an error will be returned.
// The disperser will ensure that the encoded blobs for each quorum are all processed
// within the same batch.
repeated uint32 custom_quorum_numbers = 2;
// The account ID of the client. This should be a hex-encoded string of the ECSDA public key
// corresponding to the key used by the client to sign the BlobAuthHeader.
string account_id = 3;
}
message DisperseBlobReply {
// The status of the blob associated with the request_id.
BlobStatus result = 1;
// The request ID generated by the disperser.
// Once a request is accepted (although not processed), a unique request ID will be
// generated.
// Two different DisperseBlobRequests (determined by the hash of the DisperseBlobRequest)
// will have different IDs, and the same DisperseBlobRequest sent repeatedly at different
// times will also have different IDs.
// The client should use this ID to query the processing status of the request (via
// the GetBlobStatus API).
bytes request_id = 2;
}
// BlobStatusRequest is used to query the status of a blob.
message BlobStatusRequest {
bytes request_id = 1;
}
message BlobStatusReply {
// The status of the blob.
BlobStatus status = 1;
// The blob info needed for clients to confirm the blob against the EigenDA contracts.
BlobInfo info = 2;
}
// RetrieveBlobRequest contains parameters to retrieve the blob.
message RetrieveBlobRequest {
bytes batch_header_hash = 1;
uint32 blob_index = 2;
}
// RetrieveBlobReply contains the retrieved blob data
message RetrieveBlobReply {
bytes data = 1;
}
// Data Types
// BlobStatus represents the status of a blob.
// The status of a blob is updated as the blob is processed by the disperser.
// The status of a blob can be queried by the client using the GetBlobStatus API.
// Intermediate states are states that the blob can be in while being processed, and it can be updated to a differet state:
// - PROCESSING
// - DISPERSING
// - CONFIRMED
// Terminal states are states that will not be updated to a different state:
// - FAILED
// - FINALIZED
// - INSUFFICIENT_SIGNATURES
enum BlobStatus {
UNKNOWN = 0;
// PROCESSING means that the blob is currently being processed by the disperser
PROCESSING = 1;
// CONFIRMED means that the blob has been dispersed to DA Nodes and the dispersed
// batch containing the blob has been confirmed onchain
CONFIRMED = 2;
// FAILED means that the blob has failed permanently (for reasons other than insufficient
// signatures, which is a separate state)
FAILED = 3;
// FINALIZED means that the block containing the blob's confirmation transaction has been finalized on Ethereum
FINALIZED = 4;
// INSUFFICIENT_SIGNATURES means that the confirmation threshold for the blob was not met
// for at least one quorum.
INSUFFICIENT_SIGNATURES = 5;
// DISPERSING means that the blob is currently being dispersed to DA Nodes and being confirmed onchain
DISPERSING = 6;
}
// Types below correspond to the types necessary to verify a blob
// https://github.com/Layr-Labs/eigenda/blob/master/contracts/src/libraries/EigenDABlobUtils.sol#L29
// BlobInfo contains information needed to confirm the blob against the EigenDA contracts
message BlobInfo {
BlobHeader blob_header = 1;
BlobVerificationProof blob_verification_proof = 2;
}
message BlobHeader {
// KZG commitment of the blob.
common.G1Commitment commitment = 1;
// The length of the blob in symbols (each symbol is 32 bytes).
uint32 data_length = 2;
// The params of the quorums that this blob participates in.
repeated BlobQuorumParam blob_quorum_params = 3;
}
message BlobQuorumParam {
// The ID of the quorum.
uint32 quorum_number = 1;
// The max percentage of stake within the quorum that can be held by or delegated
// to adversarial operators. Currently, this and the next parameter are standardized
// across the quorum using values read from the EigenDA contracts.
uint32 adversary_threshold_percentage = 2;
// The min percentage of stake that must attest in order to consider
// the dispersal is successful.
uint32 confirmation_threshold_percentage = 3;
// The length of each chunk.
uint32 chunk_length = 4;
}
message BlobVerificationProof {
// batch_id is an incremental ID assigned to a batch by EigenDAServiceManager
uint32 batch_id = 1;
// The index of the blob in the batch (which is logically an ordered list of blobs).
uint32 blob_index = 2;
BatchMetadata batch_metadata = 3;
// inclusion_proof is a merkle proof for a blob header's inclusion in a batch
bytes inclusion_proof = 4;
// indexes of quorums in BatchHeader.quorum_numbers that match the quorums in BlobHeader.blob_quorum_params
// Ex. BlobHeader.blob_quorum_params = [
// {
// quorum_number = 0,
// ...
// },
// {
// quorum_number = 3,
// ...
// },
// {
// quorum_number = 5,
// ...
// },
// ]
// BatchHeader.quorum_numbers = [0, 5, 3] => 0x000503
// Then, quorum_indexes = [0, 2, 1] => 0x000201
bytes quorum_indexes = 5;
}
message BatchMetadata {
BatchHeader batch_header = 1;
// The hash of all public keys of the operators that did not sign the batch.
bytes signatory_record_hash = 2;
// The fee payment paid by users for dispersing this batch. It's the bytes
// representation of a big.Int value.
bytes fee = 3;
// The Ethereum block number at which the batch is confirmed onchain.
uint32 confirmation_block_number = 4;
// This is the hash of the ReducedBatchHeader defined onchain, see:
// https://github.com/Layr-Labs/eigenda/blob/master/contracts/src/interfaces/IEigenDAServiceManager.sol#L43
// The is the message that the operators will sign their signatures on.
bytes batch_header_hash = 5;
}
message BatchHeader {
// The root of the merkle tree with the hashes of blob headers as leaves.
bytes batch_root = 1;
// All quorums associated with blobs in this batch. Sorted in ascending order.
// Ex. [0, 2, 1] => 0x000102
bytes quorum_numbers = 2;
// The percentage of stake that has signed for this batch.
// The quorum_signed_percentages[i] is percentage for the quorum_numbers[i].
bytes quorum_signed_percentages = 3;
// The Ethereum block number at which the batch was created.
// The Disperser will encode and disperse the blobs based on the onchain info
// (e.g. operator stakes) at this block number.
uint32 reference_block_number = 4;
}