@@ -5,92 +5,117 @@ import (
55 "crypto/sha256"
66 "encoding/hex"
77 "fmt"
8+ "maps"
9+ "reflect"
810 "testing"
911
1012 "github.com/btcsuite/btcd/btcec/v2"
1113 "github.com/btcsuite/btcd/btcec/v2/schnorr"
1214 "github.com/lightninglabs/taproot-assets/taprpc"
1315 "github.com/lightninglabs/taproot-assets/taprpc/universerpc"
1416 "github.com/lightninglabs/taproot-assets/universe"
17+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
1518 "pgregory.net/rapid"
1619)
1720
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+
1825// Custom generators.
1926var (
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 ),
4145 }
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
5852 }
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
8160 }
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+ )
8388 PrevWitnessesGen = rapid .Custom (func (t * rapid.T ) []* taprpc.PrevWitness {
8489 witnessGen := rapid .Ptr (PrevWitnessGen , false )
8590 return rapid .SliceOf (witnessGen ).Draw (t , "prev_witnesses" )
8691 })
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 )
94119)
95120
96121// Result is used to store the output of a fallible function call.
@@ -530,68 +555,9 @@ func TestUnmarshalUniId(t *testing.T) {
530555}
531556
532557func 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-
593558 // Don't check the unmarshal output, we are only testing if we can
594559 // cause unmarshal to panic.
560+ leaf := AssetLeafPtrGen .Draw (t , "Leaf" )
595561 _ , _ = unmarshalAssetLeaf (leaf )
596562}
597563
0 commit comments