@@ -248,7 +248,8 @@ func randIgnoreTupleGen(t *rapid.T,
248
248
ScriptKey : asset .ToSerialized (scriptKey .PubKey ),
249
249
OutPoint : op ,
250
250
},
251
- Amount : 100 ,
251
+ Amount : 100 ,
252
+ BlockHeight : rapid .Uint32Range (1 , 1000 ).Draw (t , "block_height" ),
252
253
}
253
254
254
255
// Create a signature for the ignore tuple.
@@ -367,6 +368,101 @@ func setupSupplyTreeTestForProps(t *testing.T) (*SupplyTreeStore,
367
368
return supplyStore , spec , eventGen
368
369
}
369
370
371
+ // createMintEventWithHeight creates a mint event with a specific block height.
372
+ func createMintEventWithHeight (t * testing.T , groupKey * btcec.PublicKey ,
373
+ height uint32 ) * supplycommit.NewMintEvent {
374
+
375
+ mintAsset := asset .RandAsset (t , asset .Normal )
376
+ mintAsset .GroupKey = & asset.GroupKey {GroupPubKey : * groupKey }
377
+ mintAsset .GroupKey .Witness = mintAsset .PrevWitnesses [0 ].TxWitness
378
+
379
+ mintProof := randProof (t , mintAsset )
380
+ mintProof .BlockHeight = height
381
+ mintProof .GroupKeyReveal = asset .NewGroupKeyRevealV0 (
382
+ asset .ToSerialized (groupKey ), nil ,
383
+ )
384
+
385
+ var proofBuf bytes.Buffer
386
+ require .NoError (t , mintProof .Encode (& proofBuf ))
387
+
388
+ mintLeaf := universe.Leaf {
389
+ GenesisWithGroup : universe.GenesisWithGroup {
390
+ Genesis : mintAsset .Genesis ,
391
+ GroupKey : mintAsset .GroupKey ,
392
+ },
393
+ Asset : & mintProof .Asset ,
394
+ Amt : mintProof .Asset .Amount ,
395
+ RawProof : proofBuf .Bytes (),
396
+ }
397
+
398
+ mintKey := universe.AssetLeafKey {
399
+ BaseLeafKey : universe.BaseLeafKey {
400
+ OutPoint : mintProof .OutPoint (),
401
+ ScriptKey : & mintProof .Asset .ScriptKey ,
402
+ },
403
+ AssetID : mintProof .Asset .ID (),
404
+ }
405
+
406
+ return & supplycommit.NewMintEvent {
407
+ LeafKey : mintKey ,
408
+ IssuanceProof : mintLeaf ,
409
+ }
410
+ }
411
+
412
+ // createBurnEventWithHeight creates a burn event with a specific block height.
413
+ func createBurnEventWithHeight (t * testing.T , baseGenesis asset.Genesis ,
414
+ groupKey * asset.GroupKey , db BatchedUniverseTree ,
415
+ height uint32 ) * supplycommit.NewBurnEvent {
416
+
417
+ burnAsset := createBurnAsset (t )
418
+ burnAsset .Genesis = baseGenesis
419
+ burnAsset .GroupKey = groupKey
420
+
421
+ burnProof := randProof (t , burnAsset )
422
+ burnProof .BlockHeight = height
423
+ burnProof .GenesisReveal = & baseGenesis
424
+
425
+ // Ensure genesis exists for this burn leaf in the DB.
426
+ ctx := context .Background ()
427
+ genesisPointID , err := upsertGenesisPoint (
428
+ ctx , db , burnAsset .Genesis .FirstPrevOut ,
429
+ )
430
+ require .NoError (t , err )
431
+ _ , err = upsertGenesis (
432
+ ctx , db , genesisPointID , burnAsset .Genesis ,
433
+ )
434
+ require .NoError (t , err )
435
+
436
+ burnLeaf := & universe.BurnLeaf {
437
+ UniverseKey : universe.AssetLeafKey {
438
+ BaseLeafKey : universe.BaseLeafKey {
439
+ OutPoint : burnProof .OutPoint (),
440
+ ScriptKey : & burnProof .Asset .ScriptKey ,
441
+ },
442
+ AssetID : burnProof .Asset .ID (),
443
+ },
444
+ BurnProof : burnProof ,
445
+ }
446
+
447
+ return & supplycommit.NewBurnEvent {
448
+ BurnLeaf : * burnLeaf ,
449
+ }
450
+ }
451
+
452
+ // createIgnoreEventWithHeight creates an ignore event with a specific block
453
+ // height.
454
+ func createIgnoreEventWithHeight (t * testing.T , baseAssetID asset.ID ,
455
+ db BatchedUniverseTree , height uint32 ) * supplycommit.NewIgnoreEvent {
456
+
457
+ signedTuple := randIgnoreTuple (t , db )
458
+ signedTuple .IgnoreTuple .Val .ID = baseAssetID
459
+ signedTuple .IgnoreTuple .Val .BlockHeight = height
460
+
461
+ return & supplycommit.NewIgnoreEvent {
462
+ SignedIgnoreTuple : signedTuple ,
463
+ }
464
+ }
465
+
370
466
// TestSupplyTreeStoreApplySupplyUpdates tests that the ApplySupplyUpdates meets
371
467
// a series of key invariant via property based testing.
372
468
func TestSupplyTreeStoreApplySupplyUpdates (t * testing.T ) {
@@ -544,3 +640,114 @@ func TestSupplyTreeStoreApplySupplyUpdates(t *testing.T) {
544
640
)
545
641
require .NoError (t , err )
546
642
}
643
+
644
+ // TestSupplyTreeStoreFetchSupplyLeavesByHeight tests the
645
+ // FetchSupplyLeavesByHeight method.
646
+ func TestSupplyTreeStoreFetchSupplyLeavesByHeight (t * testing.T ) {
647
+ t .Parallel ()
648
+
649
+ supplyStore , spec , _ := setupSupplyTreeTestForProps (t )
650
+ ctxb := context .Background ()
651
+ dbTxer := supplyStore .db .(BatchedUniverseTree )
652
+
653
+ groupKey , err := spec .UnwrapGroupKeyOrErr ()
654
+ require .NoError (t , err )
655
+ assetID := spec .UnwrapIdToPtr ()
656
+
657
+ fullGroupKey := & asset.GroupKey {
658
+ GroupPubKey : * groupKey ,
659
+ }
660
+
661
+ // Create events with specific block heights, we'll use these heights
662
+ // below to ensure that the new leaf height is properly set/read all the
663
+ // way down the call stack.
664
+ mintEvent100 := createMintEventWithHeight (t , groupKey , 100 )
665
+ burnEvent200 := createBurnEventWithHeight (
666
+ t , asset .RandGenesis (t , asset .Normal ), fullGroupKey , dbTxer ,
667
+ 200 ,
668
+ )
669
+ ignoreEvent300 := createIgnoreEventWithHeight (t , * assetID , dbTxer , 300 )
670
+ mintEvent400 := createMintEventWithHeight (t , groupKey , 400 )
671
+
672
+ updates := []supplycommit.SupplyUpdateEvent {
673
+ mintEvent100 , burnEvent200 , ignoreEvent300 , mintEvent400 ,
674
+ }
675
+
676
+ // Apply updates.
677
+ _ , err = supplyStore .ApplySupplyUpdates (ctxb , spec , updates )
678
+ require .NoError (t , err )
679
+
680
+ testCases := []struct {
681
+ name string
682
+ startHeight uint32
683
+ endHeight uint32
684
+ expectedCount int
685
+ expectedHeights []uint32
686
+ }{
687
+ {
688
+ name : "range including first" ,
689
+ startHeight : 0 ,
690
+ endHeight : 150 ,
691
+ expectedCount : 1 ,
692
+ expectedHeights : []uint32 {100 },
693
+ },
694
+ {
695
+ name : "range including second" ,
696
+ startHeight : 150 ,
697
+ endHeight : 250 ,
698
+ expectedCount : 1 ,
699
+ expectedHeights : []uint32 {200 },
700
+ },
701
+ {
702
+ name : "range including all" ,
703
+ startHeight : 0 ,
704
+ endHeight : 500 ,
705
+ expectedCount : 4 ,
706
+ expectedHeights : []uint32 {100 , 200 , 300 , 400 },
707
+ },
708
+ {
709
+ name : "exact range" ,
710
+ startHeight : 100 ,
711
+ endHeight : 400 ,
712
+ expectedCount : 4 ,
713
+ expectedHeights : []uint32 {100 , 200 , 300 , 400 },
714
+ },
715
+ {
716
+ name : "inner range" ,
717
+ startHeight : 101 ,
718
+ endHeight : 399 ,
719
+ expectedCount : 2 ,
720
+ expectedHeights : []uint32 {200 , 300 },
721
+ },
722
+ {
723
+ name : "range after all" ,
724
+ startHeight : 501 ,
725
+ endHeight : 1000 ,
726
+ expectedCount : 0 ,
727
+ expectedHeights : nil ,
728
+ },
729
+ {
730
+ name : "range before all" ,
731
+ startHeight : 0 ,
732
+ endHeight : 99 ,
733
+ expectedCount : 0 ,
734
+ expectedHeights : nil ,
735
+ },
736
+ }
737
+
738
+ for _ , tc := range testCases {
739
+ t .Run (tc .name , func (t * testing.T ) {
740
+ leaves , err := supplyStore .FetchSupplyLeavesByHeight (
741
+ ctxb , spec , tc .startHeight , tc .endHeight ,
742
+ )
743
+ require .NoError (t , err )
744
+ require .Len (t , leaves , tc .expectedCount )
745
+
746
+ var heights []uint32
747
+ for _ , leaf := range leaves {
748
+ heights = append (heights , leaf .BlockHeight )
749
+ }
750
+ require .ElementsMatch (t , tc .expectedHeights , heights )
751
+ })
752
+ }
753
+ }
0 commit comments