@@ -5,92 +5,117 @@ import (
5
5
"crypto/sha256"
6
6
"encoding/hex"
7
7
"fmt"
8
+ "maps"
9
+ "reflect"
8
10
"testing"
9
11
10
12
"github.com/btcsuite/btcd/btcec/v2"
11
13
"github.com/btcsuite/btcd/btcec/v2/schnorr"
12
14
"github.com/lightninglabs/taproot-assets/taprpc"
13
15
"github.com/lightninglabs/taproot-assets/taprpc/universerpc"
14
16
"github.com/lightninglabs/taproot-assets/universe"
17
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
15
18
"pgregory.net/rapid"
16
19
)
17
20
21
+ type rapidFieldGen = map [string ]* rapid.Generator [any ]
22
+ type rapidFieldMap = map [reflect.Type ]rapidFieldGen
23
+ type rapidTypeMap = map [reflect.Type ]* rapid.Generator [any ]
24
+
18
25
// Custom generators.
19
26
var (
20
- ByteSliceGen = rapid .SliceOf (rapid .Byte ())
21
- GenesisInfoGen = rapid .Custom (func (t * rapid.T ) taprpc.GenesisInfo {
22
- return taprpc.GenesisInfo {
23
- GenesisPoint : rapid .String ().Draw (t , "genesis_point" ),
24
- Name : rapid .String ().Draw (t , "name" ),
25
- MetaHash : ByteSliceGen .Draw (t , "meta_hash" ),
26
- AssetId : ByteSliceGen .Draw (t , "id" ),
27
- AssetType : taprpc .AssetType (
28
- rapid .Int32 ().Draw (t , "asset_type" ),
29
- ),
30
- OutputIndex : rapid .Uint32 ().Draw (t , "output_index" ),
31
- }
32
- })
33
- AssetGroupGen = rapid .Custom (func (t * rapid.T ) taprpc.AssetGroup {
34
- return taprpc.AssetGroup {
35
- RawGroupKey : ByteSliceGen .Draw (t , "raw_group_key" ),
36
- TweakedGroupKey : ByteSliceGen .Draw (
37
- t , "tweaked_group_key" ,
38
- ),
39
- AssetWitness : ByteSliceGen .Draw (t , "asset_witness" ),
40
- TapscriptRoot : ByteSliceGen .Draw (t , "tapscript_root" ),
27
+ ByteSliceGen = rapid .SliceOf (rapid .Byte ())
28
+
29
+ // Ignore private gRPC fields of messages, which we don't read when
30
+ // unmarshalling and cause issues with rapid.Make().
31
+ ignorePrivateRPCFields = rapidFieldGen {
32
+ "state" : rapid .Just (protoimpl.MessageState {}).AsAny (),
33
+ "sizeCache" : rapid .Just (protoimpl .SizeCache (0 )).AsAny (),
34
+ "unknownFields" : rapid .Just (protoimpl.UnknownFields {}).AsAny (),
35
+ }
36
+
37
+ // Create a generator config for a gRPC message, which may include
38
+ // custom generators or type generator overrides.
39
+ genMakeConfig = func (rpcType any , customGens rapidFieldGen ,
40
+ genOverrides rapidTypeMap ) rapid.MakeConfig {
41
+
42
+ cfg := rapid.MakeConfig {
43
+ Types : make (rapidTypeMap ),
44
+ Fields : make (rapidFieldMap ),
41
45
}
42
- })
43
- AnchorInfoGen = rapid .Custom (func (t * rapid.T ) taprpc.AnchorInfo {
44
- return taprpc.AnchorInfo {
45
- AnchorTx : ByteSliceGen .Draw (t , "anchor_tx" ),
46
- AnchorBlockHash : rapid .String ().Draw (
47
- t , "anchor_block_hash" ,
48
- ),
49
- AnchorOutpoint : rapid .String ().Draw (
50
- t , "anchor_outpoint" ,
51
- ),
52
- InternalKey : ByteSliceGen .Draw (t , "internal_key" ),
53
- MerkleRoot : ByteSliceGen .Draw (t , "merkle_root" ),
54
- TapscriptSibling : ByteSliceGen .Draw (
55
- t , "tapscript_sibling" ,
56
- ),
57
- BlockHeight : rapid .Uint32 ().Draw (t , "block_height" ),
46
+
47
+ // Add custom generators for fields, by field name, to override
48
+ // default rapid.Make() behavior.
49
+ ignoredFields := maps .Clone (ignorePrivateRPCFields )
50
+ for k , v := range customGens {
51
+ ignoredFields [k ] = v
58
52
}
59
- })
60
- PrevInputAssetGen = rapid .Custom (
61
- func (t * rapid.T ) taprpc.PrevInputAsset {
62
-
63
- return taprpc.PrevInputAsset {
64
- AnchorPoint : rapid .String ().Draw (
65
- t , "anchor_point" ,
66
- ),
67
- AssetId : ByteSliceGen .Draw (t , "asset_id" ),
68
- ScriptKey : ByteSliceGen .Draw (t , "script_key" ),
69
- Amount : rapid .Uint64 ().Draw (t , "amount" ),
70
- }
71
- })
72
- PrevWitnessGen = rapid .Custom (func (t * rapid.T ) taprpc.PrevWitness {
73
- // Leave the split commitment as nil.
74
- return taprpc.PrevWitness {
75
- PrevId : rapid .Ptr (PrevInputAssetGen , true ).Draw (
76
- t , "prev_id" ,
77
- ),
78
- TxWitness : rapid .SliceOf (ByteSliceGen ).Draw (
79
- t , "tx_witnesses" ,
80
- ),
53
+
54
+ cfg .Fields [reflect .TypeOf (rpcType )] = ignoredFields
55
+
56
+ // Add custom generators that will override the generators
57
+ // rapid.Make() would create for struct member types.
58
+ for k , v := range genOverrides {
59
+ cfg .Types [k ] = v
81
60
}
82
- })
61
+
62
+ return cfg
63
+ }
64
+
65
+ GenesisInfoGen = rapid .Ptr (rapid.MakeCustom [taprpc.GenesisInfo ](
66
+ genMakeConfig (taprpc.GenesisInfo {}, nil , nil ),
67
+ ), true )
68
+ AssetGroupGen = rapid .Ptr (rapid.MakeCustom [taprpc.AssetGroup ](
69
+ genMakeConfig (taprpc.AssetGroup {}, nil , nil ),
70
+ ), true )
71
+ AnchorInfoGen = rapid .Ptr (rapid.MakeCustom [taprpc.AnchorInfo ](
72
+ genMakeConfig (taprpc.AnchorInfo {}, nil , nil ),
73
+ ), true )
74
+ PrevInputAssetGen = rapid.MakeCustom [taprpc.PrevInputAsset ](
75
+ genMakeConfig (taprpc.PrevInputAsset {}, nil , nil ),
76
+ )
77
+
78
+ // Leave the split commitment for prev witnesses as nil.
79
+ emptySplitCommitmentGen = rapid .Just (taprpc.SplitCommitment {})
80
+ splitCommitPtrGen = rapid .Ptr (emptySplitCommitmentGen , true )
81
+ nilSplitCommitment = rapidTypeMap {
82
+ //nolint:lll
83
+ reflect .TypeOf (& taprpc.SplitCommitment {}): splitCommitPtrGen .AsAny (),
84
+ }
85
+ PrevWitnessGen = rapid.MakeCustom [taprpc.PrevWitness ](
86
+ genMakeConfig (taprpc.PrevWitness {}, nil , nilSplitCommitment ),
87
+ )
83
88
PrevWitnessesGen = rapid .Custom (func (t * rapid.T ) []* taprpc.PrevWitness {
84
89
witnessGen := rapid .Ptr (PrevWitnessGen , false )
85
90
return rapid .SliceOf (witnessGen ).Draw (t , "prev_witnesses" )
86
91
})
87
- DecDisplayGen = rapid .Custom (func (t * rapid.T ) taprpc.DecimalDisplay {
88
- return taprpc.DecimalDisplay {
89
- DecimalDisplay : rapid .Uint32 ().Draw (
90
- t , "decimal_display" ,
91
- ),
92
- }
93
- })
92
+ DecDisplayGen = rapid .Ptr (rapid.MakeCustom [taprpc.DecimalDisplay ](
93
+ genMakeConfig (taprpc.DecimalDisplay {}, nil , nil ),
94
+ ), true )
95
+
96
+ // Set generator overrides for members of taprpc.Asset that are gRPC
97
+ // messages.
98
+ assetMemberGens = rapidTypeMap {
99
+ reflect .TypeOf (& taprpc.GenesisInfo {}): GenesisInfoGen .AsAny (),
100
+ reflect .TypeOf (& taprpc.AssetGroup {}): AssetGroupGen .AsAny (),
101
+ reflect .TypeOf (& taprpc.AnchorInfo {}): AnchorInfoGen .AsAny (),
102
+ //nolint:lll
103
+ reflect .TypeOf ([]* taprpc.PrevWitness {}): PrevWitnessesGen .AsAny (),
104
+ reflect .TypeOf (& taprpc.DecimalDisplay {}): DecDisplayGen .AsAny (),
105
+ }
106
+ AssetGen = rapid.MakeCustom [taprpc.Asset ](
107
+ genMakeConfig (taprpc.Asset {}, nil , assetMemberGens ),
108
+ )
109
+ AssetPtrGen = rapid .Ptr (AssetGen , true )
110
+
111
+ // Use the custom taprpc.Asset generator for *universerpc.AssetLeaf.
112
+ leafMemberGens = rapidTypeMap {
113
+ reflect .TypeOf (& taprpc.Asset {}): AssetPtrGen .AsAny (),
114
+ }
115
+ AssetLeafGen = rapid.MakeCustom [universerpc.AssetLeaf ](
116
+ genMakeConfig (universerpc.AssetLeaf {}, nil , leafMemberGens ),
117
+ )
118
+ AssetLeafPtrGen = rapid .Ptr (AssetLeafGen , true )
94
119
)
95
120
96
121
// Result is used to store the output of a fallible function call.
@@ -530,68 +555,9 @@ func TestUnmarshalUniId(t *testing.T) {
530
555
}
531
556
532
557
func testUnmarshalAssetLeaf (t * rapid.T ) {
533
- // rapid.Make failed on the private gRPC-specific fields of
534
- // taprpc.Asset, so we'll populate only the public fields.
535
- LeafAssetGen := rapid .Custom (func (t * rapid.T ) taprpc.Asset {
536
- vers := taprpc .AssetVersion (rapid .Int32 ().Draw (t , "version" ))
537
- genesis := rapid .Ptr (GenesisInfoGen , true ).Draw (t , "genesis" )
538
- amount := rapid .Uint64 ().Draw (t , "amount" )
539
- lockTime := rapid .Int32 ().Draw (t , "lock_time" )
540
- relativeLockTime := rapid .Int32 ().Draw (t , "relative_lock_time" )
541
- scriptVersion := rapid .Int32 ().Draw (t , "script_version" )
542
- scriptKey := ByteSliceGen .Draw (t , "script_key" )
543
- scriptKeyIsLocal := rapid .Bool ().Draw (t , "script_key_is_local" )
544
- group := rapid .Ptr (AssetGroupGen , true ).Draw (t , "asset_group" )
545
- chainAnchor := rapid .Ptr (AnchorInfoGen , true ).Draw (
546
- t , "chain_anchor" ,
547
- )
548
- prevWitnesses := PrevWitnessesGen .Draw (t , "prev_witnesses" )
549
- isSpent := rapid .Bool ().Draw (t , "is_spent" )
550
- leaseOwner := ByteSliceGen .Draw (t , "lease_owner" )
551
- leaseExpiry := rapid .Int64 ().Draw (t , "lease_expiry" )
552
- isBurn := rapid .Bool ().Draw (t , "is_burn" )
553
- scriptKeyDeclaredKnown := rapid .Bool ().Draw (
554
- t , "script_key_declared_known" ,
555
- )
556
- scriptKeyHasScriptPath := rapid .Bool ().Draw (
557
- t , "script_key_has_script_path" ,
558
- )
559
- decimalDisplay := rapid .Ptr (DecDisplayGen , true ).Draw (
560
- t , "decimal_display" ,
561
- )
562
-
563
- return taprpc.Asset {
564
- Version : vers ,
565
- AssetGenesis : genesis ,
566
- Amount : amount ,
567
- LockTime : lockTime ,
568
- RelativeLockTime : relativeLockTime ,
569
- ScriptVersion : scriptVersion ,
570
- ScriptKey : scriptKey ,
571
- ScriptKeyIsLocal : scriptKeyIsLocal ,
572
- AssetGroup : group ,
573
- ChainAnchor : chainAnchor ,
574
- PrevWitnesses : prevWitnesses ,
575
- IsSpent : isSpent ,
576
- LeaseOwner : leaseOwner ,
577
- LeaseExpiry : leaseExpiry ,
578
- IsBurn : isBurn ,
579
- ScriptKeyDeclaredKnown : scriptKeyDeclaredKnown ,
580
- ScriptKeyHasScriptPath : scriptKeyHasScriptPath ,
581
- DecimalDisplay : decimalDisplay ,
582
- }
583
- })
584
-
585
- leafGen := rapid .Custom (func (t * rapid.T ) universerpc.AssetLeaf {
586
- return universerpc.AssetLeaf {
587
- Asset : rapid .Ptr (LeafAssetGen , true ).Draw (t , "Asset" ),
588
- Proof : ByteSliceGen .Draw (t , "Proof" ),
589
- }
590
- })
591
- leaf := rapid .Ptr (leafGen , true ).Draw (t , "Leaf" )
592
-
593
558
// Don't check the unmarshal output, we are only testing if we can
594
559
// cause unmarshal to panic.
560
+ leaf := AssetLeafPtrGen .Draw (t , "Leaf" )
595
561
_ , _ = unmarshalAssetLeaf (leaf )
596
562
}
597
563
0 commit comments