@@ -29,10 +29,15 @@ func (s *DispersalServerV2) DisperseBlob(ctx context.Context, req *pb.DisperseBl
29
29
if onchainState == nil {
30
30
return nil , api .NewErrorInternal ("onchain state is nil" )
31
31
}
32
- if err := s .validateDispersalRequest (ctx , req , onchainState ); err != nil {
32
+ blobHeader , err := s .validateDispersalRequest (req , onchainState )
33
+ if err != nil {
33
34
return nil , api .NewErrorInvalidArg (fmt .Sprintf ("failed to validate the request: %v" , err ))
34
35
}
35
36
37
+ if err := s .checkBlobExistence (ctx , blobHeader ); err != nil {
38
+ return nil , err
39
+ }
40
+
36
41
// Check against payment meter to make sure there is quota remaining
37
42
if err := s .checkPaymentMeter (ctx , req , start ); err != nil {
38
43
return nil , err
@@ -43,10 +48,6 @@ func (s *DispersalServerV2) DisperseBlob(ctx context.Context, req *pb.DisperseBl
43
48
44
49
blob := req .GetBlob ()
45
50
s .metrics .reportDisperseBlobSize (len (blob ))
46
- blobHeader , err := corev2 .BlobHeaderFromProtobuf (req .GetBlobHeader ())
47
- if err != nil {
48
- return nil , api .NewErrorInvalidArg (fmt .Sprintf ("failed to parse the blob header proto: %v" , err ))
49
- }
50
51
s .logger .Debug ("received a new blob dispersal request" , "blobSizeBytes" , len (blob ), "quorums" , req .GetBlobHeader ().GetQuorumNumbers ())
51
52
52
53
blobKey , err := s .StoreBlob (ctx , blob , blobHeader , req .GetSignature (), time .Now (), onchainState .TTL )
@@ -133,100 +134,110 @@ func (s *DispersalServerV2) checkPaymentMeter(ctx context.Context, req *pb.Dispe
133
134
}
134
135
135
136
func (s * DispersalServerV2 ) validateDispersalRequest (
136
- ctx context.Context ,
137
137
req * pb.DisperseBlobRequest ,
138
- onchainState * OnchainState ) error {
138
+ onchainState * OnchainState ) ( * corev2. BlobHeader , error ) {
139
139
140
140
signature := req .GetSignature ()
141
141
if len (signature ) != 65 {
142
- return fmt .Errorf ("signature is expected to be 65 bytes, but got %d bytes" , len (signature ))
142
+ return nil , fmt .Errorf ("signature is expected to be 65 bytes, but got %d bytes" , len (signature ))
143
143
}
144
144
blob := req .GetBlob ()
145
145
blobSize := len (blob )
146
146
if blobSize == 0 {
147
- return errors .New ("blob size must be greater than 0" )
147
+ return nil , errors .New ("blob size must be greater than 0" )
148
148
}
149
149
blobLength := encoding .GetBlobLengthPowerOf2 (uint (blobSize ))
150
150
if blobLength > uint (s .maxNumSymbolsPerBlob ) {
151
- return errors .New ("blob size too big" )
151
+ return nil , errors .New ("blob size too big" )
152
152
}
153
153
154
154
blobHeaderProto := req .GetBlobHeader ()
155
155
if blobHeaderProto .GetCommitment () == nil {
156
- return errors .New ("blob header must contain commitments" )
156
+ return nil , errors .New ("blob header must contain commitments" )
157
157
}
158
158
159
159
if blobHeaderProto .GetCommitment () == nil {
160
- return errors .New ("blob header must contain a commitment" )
160
+ return nil , errors .New ("blob header must contain a commitment" )
161
161
}
162
162
commitedBlobLength := blobHeaderProto .GetCommitment ().GetLength ()
163
163
if commitedBlobLength == 0 || commitedBlobLength != encoding .NextPowerOf2 (commitedBlobLength ) {
164
- return errors .New ("invalid commitment length, must be a power of 2" )
164
+ return nil , errors .New ("invalid commitment length, must be a power of 2" )
165
165
}
166
166
lengthPowerOf2 := encoding .GetBlobLengthPowerOf2 (uint (blobSize ))
167
167
if lengthPowerOf2 > uint (commitedBlobLength ) {
168
- return fmt .Errorf ("commitment length %d is less than blob length %d" , commitedBlobLength , lengthPowerOf2 )
168
+ return nil , fmt .Errorf ("commitment length %d is less than blob length %d" , commitedBlobLength , lengthPowerOf2 )
169
169
}
170
170
171
171
blobHeader , err := corev2 .BlobHeaderFromProtobuf (blobHeaderProto )
172
172
if err != nil {
173
- return fmt .Errorf ("invalid blob header: %w" , err )
173
+ return nil , fmt .Errorf ("invalid blob header: %w" , err )
174
174
}
175
175
176
176
if blobHeader .PaymentMetadata == (core.PaymentMetadata {}) {
177
- return errors .New ("payment metadata is required" )
177
+ return nil , errors .New ("payment metadata is required" )
178
178
}
179
179
180
180
timestampIsNegative := blobHeader .PaymentMetadata .Timestamp < 0
181
181
paymentIsNegative := blobHeader .PaymentMetadata .CumulativePayment .Cmp (big .NewInt (0 )) == - 1
182
182
timestampIsZeroAndPaymentIsZero := blobHeader .PaymentMetadata .Timestamp == 0 && blobHeader .PaymentMetadata .CumulativePayment .Cmp (big .NewInt (0 )) == 0
183
183
if timestampIsNegative || paymentIsNegative || timestampIsZeroAndPaymentIsZero {
184
- return errors .New ("invalid payment metadata" )
184
+ return nil , errors .New ("invalid payment metadata" )
185
185
}
186
186
187
187
if len (blobHeaderProto .GetQuorumNumbers ()) == 0 {
188
- return errors .New ("blob header must contain at least one quorum number" )
188
+ return nil , errors .New ("blob header must contain at least one quorum number" )
189
189
}
190
190
191
191
if len (blobHeaderProto .GetQuorumNumbers ()) > int (onchainState .QuorumCount ) {
192
- return fmt .Errorf ("too many quorum numbers specified: maximum is %d" , onchainState .QuorumCount )
192
+ return nil , fmt .Errorf ("too many quorum numbers specified: maximum is %d" , onchainState .QuorumCount )
193
193
}
194
194
195
195
for _ , quorum := range blobHeaderProto .GetQuorumNumbers () {
196
196
if quorum > corev2 .MaxQuorumID || uint8 (quorum ) >= onchainState .QuorumCount {
197
- return fmt .Errorf ("invalid quorum number %d; maximum is %d" , quorum , onchainState .QuorumCount )
197
+ return nil , fmt .Errorf ("invalid quorum number %d; maximum is %d" , quorum , onchainState .QuorumCount )
198
198
}
199
199
}
200
200
201
201
// validate every 32 bytes is a valid field element
202
202
_ , err = rs .ToFrArray (blob )
203
203
if err != nil {
204
204
s .logger .Error ("failed to convert a 32bytes as a field element" , "err" , err )
205
- return errors .New ("encountered an error to convert a 32-bytes into a valid field element, please use the correct format where every 32bytes(big-endian) is less than 21888242871839275222246405745257275088548364400416034343698204186575808495617" )
205
+ return nil , errors .New ("encountered an error to convert a 32-bytes into a valid field element, please use the correct format where every 32bytes(big-endian) is less than 21888242871839275222246405745257275088548364400416034343698204186575808495617" )
206
206
}
207
207
208
208
if _ , ok := onchainState .BlobVersionParameters .Get (corev2 .BlobVersion (blobHeaderProto .GetVersion ())); ! ok {
209
- return fmt .Errorf ("invalid blob version %d; valid blob versions are: %v" , blobHeaderProto .GetVersion (), onchainState .BlobVersionParameters .Keys ())
209
+ return nil , fmt .Errorf ("invalid blob version %d; valid blob versions are: %v" , blobHeaderProto .GetVersion (), onchainState .BlobVersionParameters .Keys ())
210
210
}
211
211
212
212
if err = s .authenticator .AuthenticateBlobRequest (blobHeader , signature ); err != nil {
213
- return fmt .Errorf ("authentication failed: %w" , err )
213
+ return nil , fmt .Errorf ("authentication failed: %w" , err )
214
214
}
215
215
216
216
commitments , err := s .prover .GetCommitmentsForPaddedLength (blob )
217
217
if err != nil {
218
- return fmt .Errorf ("failed to get commitments: %w" , err )
218
+ return nil , fmt .Errorf ("failed to get commitments: %w" , err )
219
219
}
220
220
if ! commitments .Equal (& blobHeader .BlobCommitments ) {
221
- return errors .New ("invalid blob commitment" )
221
+ return nil , errors .New ("invalid blob commitment" )
222
222
}
223
223
224
+ return blobHeader , nil
225
+ }
226
+
227
+ func (s * DispersalServerV2 ) checkBlobExistence (ctx context.Context , blobHeader * corev2.BlobHeader ) error {
224
228
blobKey , err := blobHeader .BlobKey ()
225
229
if err != nil {
226
- return fmt .Errorf ("failed to get blob key: %w" , err )
230
+ return api .NewErrorInvalidArg (fmt .Sprintf ("failed to parse the blob header: %v" , err ))
231
+ }
232
+
233
+ // check if blob already exists
234
+ exists , err := s .blobMetadataStore .CheckBlobExists (ctx , blobKey )
235
+ if err != nil {
236
+ return api .NewErrorInternal (fmt .Sprintf ("failed to check blob existence: %v" , err ))
227
237
}
228
- if s .blobStore .CheckBlobExists (ctx , blobKey ) {
229
- return fmt .Errorf ("blob already exists: %s" , blobKey .Hex ())
238
+
239
+ if exists {
240
+ return api .NewErrorAlreadyExists (fmt .Sprintf ("blob already exists: %s" , blobKey .Hex ()))
230
241
}
231
242
232
243
return nil
0 commit comments