@@ -182,20 +182,19 @@ func DataCommitment(ctx *rpctypes.Context, start, end uint64) (*ctypes.ResultDat
182
182
if err != nil {
183
183
return nil , err
184
184
}
185
- heights := generateHeightsList (start , end )
186
- blockResults := fetchBlocks (heights , len (heights ), 0 )
187
- if len (blockResults ) != len (heights ) {
188
- return nil , fmt .Errorf ("couldn't fetch all the blocks in the provided range" )
185
+ tuples , err := fetchDataRootTuples (start , end )
186
+ if err != nil {
187
+ return nil , err
189
188
}
190
- root , err := hashDataRootTuples (blockResults )
189
+ root , err := hashDataRootTuples (tuples )
191
190
if err != nil {
192
191
return nil , err
193
192
}
194
193
// Create data commitment
195
194
return & ctypes.ResultDataCommitment {DataCommitment : root }, nil
196
195
}
197
196
198
- // DataRootInclusionProof creates an inclusion proof of the data root of block
197
+ // DataRootInclusionProof creates an inclusion proof for the data root of block
199
198
// height `height` in the set of blocks defined by `start` and `end`. The range
200
199
// is end exclusive.
201
200
func DataRootInclusionProof (
@@ -208,12 +207,11 @@ func DataRootInclusionProof(
208
207
if err != nil {
209
208
return nil , err
210
209
}
211
- heights := generateHeightsList (start , end )
212
- blockResults := fetchBlocks (heights , len (heights ), 0 )
213
- if len (blockResults ) != len (heights ) {
214
- return nil , fmt .Errorf ("couldn't fetch all the blocks in the provided range" )
210
+ tuples , err := fetchDataRootTuples (start , end )
211
+ if err != nil {
212
+ return nil , err
215
213
}
216
- proof , err := proveDataRootTuples (blockResults , height )
214
+ proof , err := proveDataRootTuples (tuples , height )
217
215
if err != nil {
218
216
return nil , err
219
217
}
@@ -260,6 +258,15 @@ func To32PaddedHexBytes(number uint64) ([]byte, error) {
260
258
return paddedBytes , nil
261
259
}
262
260
261
+ // DataRootTuple contains the data that will be used to create the QGB commitments.
262
+ // The commitments will be signed by orchestrators and submitted to an EVM chain via a relayer.
263
+ // For more information: https://github.com/celestiaorg/quantum-gravity-bridge/blob/master/src/DataRootTuple.sol
264
+ type DataRootTuple struct {
265
+ height uint64
266
+ dataRoot [32 ]byte
267
+ squareSize uint64
268
+ }
269
+
263
270
// EncodeDataRootTuple takes a height, a data root and the square size, and returns the equivalent of
264
271
// `abi.encode(...)` in Ethereum.
265
272
// The encoded type is a DataRootTuple, which has the following ABI:
@@ -306,16 +313,6 @@ func EncodeDataRootTuple(height uint64, dataRoot [32]byte, squareSize uint64) ([
306
313
return append (paddedHeight , append (dataSlice , paddedSquareSize ... )... ), nil
307
314
}
308
315
309
- // generateHeightsList takes a begin and end block, then generates a list of heights
310
- // containing the elements of the range [beginBlock, endBlock].
311
- func generateHeightsList (beginBlock uint64 , endBlock uint64 ) []int64 {
312
- heights := make ([]int64 , endBlock - beginBlock )
313
- for i := beginBlock ; i < endBlock ; i ++ {
314
- heights [i - beginBlock ] = int64 (i )
315
- }
316
- return heights
317
- }
318
-
319
316
// validateDataCommitmentRange runs basic checks on the asc sorted list of
320
317
// heights that will be used subsequently in generating data commitments over
321
318
// the defined set of heights.
@@ -341,24 +338,19 @@ func validateDataCommitmentRange(start uint64, end uint64) error {
341
338
env .BlockStore .Height (),
342
339
)
343
340
}
344
- has , err := env .BlockIndexer .Has (int64 (end ))
345
- if err != nil {
346
- return err
347
- }
348
- if ! has {
349
- return fmt .Errorf (
350
- "last block %d is still not indexed" ,
351
- end ,
352
- )
353
- }
354
341
return nil
355
342
}
356
343
357
- // hashDataRootTuples hashes a list of blocks data root tuples, i.e. height and data root, and returns their merkle root.
358
- func hashDataRootTuples (blocks []* ctypes.ResultBlock ) ([]byte , error ) {
359
- dataRootEncodedTuples := make ([][]byte , 0 , len (blocks ))
360
- for _ , block := range blocks {
361
- encodedTuple , err := EncodeDataRootTuple (uint64 (block .Block .Height ), * (* [32 ]byte )(block .Block .DataHash ), block .Block .SquareSize )
344
+ // hashDataRootTuples hashes a list of blocks data root tuples, i.e. height, data root and square size,
345
+ // then returns their merkle root.
346
+ func hashDataRootTuples (tuples []DataRootTuple ) ([]byte , error ) {
347
+ dataRootEncodedTuples := make ([][]byte , 0 , len (tuples ))
348
+ for _ , tuple := range tuples {
349
+ encodedTuple , err := EncodeDataRootTuple (
350
+ tuple .height ,
351
+ tuple .dataRoot ,
352
+ tuple .squareSize ,
353
+ )
362
354
if err != nil {
363
355
return nil , err
364
356
}
@@ -377,7 +369,7 @@ func validateDataRootInclusionProofRequest(height uint64, start uint64, end uint
377
369
}
378
370
if height < start || height >= end {
379
371
return fmt .Errorf (
380
- "height %d should be in the interval first_block %d last_block %d" ,
372
+ "height %d should be in the end exclusive interval first_block %d last_block %d" ,
381
373
height ,
382
374
start ,
383
375
end ,
@@ -387,17 +379,21 @@ func validateDataRootInclusionProofRequest(height uint64, start uint64, end uint
387
379
}
388
380
389
381
// proveDataRootTuples returns the merkle inclusion proof for a height.
390
- func proveDataRootTuples (blocks []* ctypes.ResultBlock , height int64 ) (* merkle.Proof , error ) {
391
- dataRootEncodedTuples := make ([][]byte , 0 , len (blocks ))
392
- for _ , block := range blocks {
393
- encodedTuple , err := EncodeDataRootTuple (uint64 (block .Block .Height ), * (* [32 ]byte )(block .Block .DataHash ), block .Block .SquareSize )
382
+ func proveDataRootTuples (tuples []DataRootTuple , height int64 ) (* merkle.Proof , error ) {
383
+ dataRootEncodedTuples := make ([][]byte , 0 , len (tuples ))
384
+ for _ , tuple := range tuples {
385
+ encodedTuple , err := EncodeDataRootTuple (
386
+ tuple .height ,
387
+ tuple .dataRoot ,
388
+ tuple .squareSize ,
389
+ )
394
390
if err != nil {
395
391
return nil , err
396
392
}
397
393
dataRootEncodedTuples = append (dataRootEncodedTuples , encodedTuple )
398
394
}
399
395
_ , proofs := merkle .ProofsFromByteSlices (dataRootEncodedTuples )
400
- return proofs [height - blocks [0 ].Block . Height ], nil
396
+ return proofs [height - int64 ( tuples [0 ].height ) ], nil
401
397
}
402
398
403
399
// BlockResults gets ABCIResults at a given height.
@@ -525,3 +521,22 @@ func fetchBlocks(results []int64, pageSize int, skipCount int) []*ctypes.ResultB
525
521
}
526
522
return apiResults
527
523
}
524
+
525
+ // fetchDataRootTuples takes an end exclusive range of heights and fetches its
526
+ // corresponding data root tuples.
527
+ func fetchDataRootTuples (start , end uint64 ) ([]DataRootTuple , error ) {
528
+ env := GetEnvironment ()
529
+ tuples := make ([]DataRootTuple , 0 , end - start )
530
+ for height := start ; height < end ; height ++ {
531
+ block := env .BlockStore .LoadBlock (int64 (height ))
532
+ if block == nil {
533
+ return nil , fmt .Errorf ("couldn't load block %d" , height )
534
+ }
535
+ tuples = append (tuples , DataRootTuple {
536
+ height : uint64 (block .Height ),
537
+ dataRoot : * (* [32 ]byte )(block .DataHash ),
538
+ squareSize : block .SquareSize ,
539
+ })
540
+ }
541
+ return tuples , nil
542
+ }
0 commit comments