@@ -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 ) {
@@ -538,3 +634,114 @@ func TestSupplyTreeStoreApplySupplyUpdates(t *testing.T) {
538
634
)
539
635
require .NoError (t , err )
540
636
}
637
+
638
+ // TestSupplyTreeStoreFetchSupplyLeavesByHeight tests the
639
+ // FetchSupplyLeavesByHeight method.
640
+ func TestSupplyTreeStoreFetchSupplyLeavesByHeight (t * testing.T ) {
641
+ t .Parallel ()
642
+
643
+ supplyStore , spec , _ := setupSupplyTreeTestForProps (t )
644
+ ctxb := context .Background ()
645
+ dbTxer := supplyStore .db
646
+
647
+ groupKey , err := spec .UnwrapGroupKeyOrErr ()
648
+ require .NoError (t , err )
649
+ assetID := spec .UnwrapIdToPtr ()
650
+
651
+ fullGroupKey := & asset.GroupKey {
652
+ GroupPubKey : * groupKey ,
653
+ }
654
+
655
+ // Create events with specific block heights, we'll use these heights
656
+ // below to ensure that the new leaf height is properly set/read all the
657
+ // way down the call stack.
658
+ mintEvent100 := createMintEventWithHeight (t , groupKey , 100 )
659
+ burnEvent200 := createBurnEventWithHeight (
660
+ t , asset .RandGenesis (t , asset .Normal ), fullGroupKey , dbTxer ,
661
+ 200 ,
662
+ )
663
+ ignoreEvent300 := createIgnoreEventWithHeight (t , * assetID , dbTxer , 300 )
664
+ mintEvent400 := createMintEventWithHeight (t , groupKey , 400 )
665
+
666
+ updates := []supplycommit.SupplyUpdateEvent {
667
+ mintEvent100 , burnEvent200 , ignoreEvent300 , mintEvent400 ,
668
+ }
669
+
670
+ // Apply updates.
671
+ _ , err = supplyStore .ApplySupplyUpdates (ctxb , spec , updates )
672
+ require .NoError (t , err )
673
+
674
+ testCases := []struct {
675
+ name string
676
+ startHeight uint32
677
+ endHeight uint32
678
+ expectedCount int
679
+ expectedHeights []uint32
680
+ }{
681
+ {
682
+ name : "range including first" ,
683
+ startHeight : 0 ,
684
+ endHeight : 150 ,
685
+ expectedCount : 1 ,
686
+ expectedHeights : []uint32 {100 },
687
+ },
688
+ {
689
+ name : "range including second" ,
690
+ startHeight : 150 ,
691
+ endHeight : 250 ,
692
+ expectedCount : 1 ,
693
+ expectedHeights : []uint32 {200 },
694
+ },
695
+ {
696
+ name : "range including all" ,
697
+ startHeight : 0 ,
698
+ endHeight : 500 ,
699
+ expectedCount : 4 ,
700
+ expectedHeights : []uint32 {100 , 200 , 300 , 400 },
701
+ },
702
+ {
703
+ name : "exact range" ,
704
+ startHeight : 100 ,
705
+ endHeight : 400 ,
706
+ expectedCount : 4 ,
707
+ expectedHeights : []uint32 {100 , 200 , 300 , 400 },
708
+ },
709
+ {
710
+ name : "inner range" ,
711
+ startHeight : 101 ,
712
+ endHeight : 399 ,
713
+ expectedCount : 2 ,
714
+ expectedHeights : []uint32 {200 , 300 },
715
+ },
716
+ {
717
+ name : "range after all" ,
718
+ startHeight : 501 ,
719
+ endHeight : 1000 ,
720
+ expectedCount : 0 ,
721
+ expectedHeights : nil ,
722
+ },
723
+ {
724
+ name : "range before all" ,
725
+ startHeight : 0 ,
726
+ endHeight : 99 ,
727
+ expectedCount : 0 ,
728
+ expectedHeights : nil ,
729
+ },
730
+ }
731
+
732
+ for _ , tc := range testCases {
733
+ t .Run (tc .name , func (t * testing.T ) {
734
+ leaves , err := supplyStore .FetchSupplyLeavesByHeight (
735
+ ctxb , spec , tc .startHeight , tc .endHeight ,
736
+ )
737
+ require .NoError (t , err )
738
+ require .Len (t , leaves , tc .expectedCount )
739
+
740
+ var heights []uint32
741
+ for _ , leaf := range leaves {
742
+ heights = append (heights , leaf .BlockHeight )
743
+ }
744
+ require .ElementsMatch (t , tc .expectedHeights , heights )
745
+ })
746
+ }
747
+ }
0 commit comments