@@ -11,6 +11,7 @@ import (
1111 "github.com/btcsuite/btcd/btcec/v2"
1212 "github.com/btcsuite/btcd/btcutil"
1313 "github.com/btcsuite/btcd/chaincfg"
14+ "github.com/btcsuite/btcd/txscript"
1415 "github.com/stretchr/testify/require"
1516)
1617
@@ -67,7 +68,7 @@ func TestBIP322_Verify(t *testing.T) {
6768 witness , err := bip322 .SimpleSigToWitness (emptyBytesSig )
6869 require .NoError (t , err )
6970
70- err = bip322 .Verify (msg , witness , addressDecoded , net )
71+ err = bip322 .VerifyP2WPKHAndP2TR (msg , witness , addressDecoded , net )
7172 require .NoError (t , err )
7273}
7374
@@ -84,7 +85,7 @@ func FuzzBip322ValidP2WPKHSignature(f *testing.F) {
8485 witnessDecoded , err := bip322 .SimpleSigToWitness (witness )
8586 require .NoError (t , err )
8687
87- err = bip322 .Verify (
88+ err = bip322 .VerifyP2WPKHAndP2TR (
8889 dataToSign ,
8990 witnessDecoded ,
9091 address ,
@@ -107,7 +108,7 @@ func FuzzBip322ValidP2TrSpendSignature(f *testing.F) {
107108 witnessDecoded , err := bip322 .SimpleSigToWitness (witness )
108109 require .NoError (t , err )
109110
110- err = bip322 .Verify (
111+ err = bip322 .VerifyP2WPKHAndP2TR (
111112 dataToSign ,
112113 witnessDecoded ,
113114 address ,
@@ -116,3 +117,126 @@ func FuzzBip322ValidP2TrSpendSignature(f *testing.F) {
116117 require .NoError (t , err )
117118 })
118119}
120+
121+ func FuzzBip322SigHashTypeP2WPKH (f * testing.F ) {
122+ // Add corpus entries: seed and sigHashType
123+ // Valid SIGHASH types
124+ f .Add (int64 (1 ), uint8 (0x01 )) // SIGHASH_ALL - valid
125+ // Invalid SIGHASH types
126+ f .Add (int64 (2 ), uint8 (0x02 )) // SIGHASH_NONE
127+ f .Add (int64 (3 ), uint8 (0x03 )) // SIGHASH_SINGLE
128+ f .Add (int64 (4 ), uint8 (0x81 )) // SIGHASH_ALL_ANYONECANPAY
129+ f .Add (int64 (5 ), uint8 (0x82 )) // SIGHASH_NONE_ANYONECANPAY
130+ f .Add (int64 (6 ), uint8 (0x83 )) // SIGHASH_SINGLE_ANYONECANPAY
131+
132+ f .Fuzz (func (t * testing.T , seed int64 , sigHashTypeByte uint8 ) {
133+ r := rand .New (rand .NewSource (seed ))
134+ privkey , err := btcec .NewPrivateKey ()
135+ require .NoError (t , err )
136+
137+ dataLen := r .Int31n (200 ) + 1
138+ dataToSign := datagen .GenRandomByteArray (r , uint64 (dataLen ))
139+
140+ sigHashType := txscript .SigHashType (sigHashTypeByte )
141+ address , witness , err := datagen .SignWithP2WPKHAddressWithSigHashType (
142+ dataToSign ,
143+ privkey ,
144+ net ,
145+ sigHashType ,
146+ )
147+
148+ // btcd's WitnessSignature does not validate SIGHASH types during signing for P2WPKH
149+ // It allows any SIGHASH type to be signed, leaving validation to script execution
150+ // Therefore, signing should ALWAYS succeed regardless of SIGHASH type
151+ require .NoError (t , err , "P2WPKH signing should always succeed with any sighash type, got error for 0x%02x: %v" , sigHashTypeByte , err )
152+
153+ witnessDecoded , err := bip322 .SimpleSigToWitness (witness )
154+ require .NoError (t , err )
155+
156+ err = bip322 .VerifyP2WPKHAndP2TR (
157+ dataToSign ,
158+ witnessDecoded ,
159+ address ,
160+ net ,
161+ )
162+
163+ // BIP-322 requires SIGHASH_ALL for P2WPKH
164+ // btcd allowed signing with any sighash type (no validation during signing)
165+ // Our verification layer must enforce the BIP-322 requirement
166+ if sigHashType == txscript .SigHashAll {
167+ require .NoError (t , err , "BIP-322 should accept SIGHASH_ALL (0x01) for P2WPKH" )
168+ } else {
169+ // btcd allowed signing, but our BIP-322 verification must reject
170+ require .Error (t , err , "BIP-322 should reject sighash type 0x%02x for P2WPKH (only SIGHASH_ALL is allowed)" , sigHashTypeByte )
171+ require .Contains (t , err .Error (), "sighash validation failed" )
172+ }
173+ })
174+ }
175+
176+ func FuzzBip322SigHashTypeP2TR (f * testing.F ) {
177+ // Add corpus entries: seed and sigHashType
178+ // Valid SIGHASH types
179+ f .Add (int64 (1 ), uint8 (0x00 )) // SIGHASH_DEFAULT - valid
180+ f .Add (int64 (2 ), uint8 (0x01 )) // SIGHASH_ALL - valid
181+ // Invalid SIGHASH types
182+ f .Add (int64 (3 ), uint8 (0x02 )) // SIGHASH_NONE
183+ f .Add (int64 (4 ), uint8 (0x03 )) // SIGHASH_SINGLE
184+ f .Add (int64 (5 ), uint8 (0x81 )) // SIGHASH_ALL_ANYONECANPAY
185+ f .Add (int64 (6 ), uint8 (0x82 )) // SIGHASH_NONE_ANYONECANPAY
186+ f .Add (int64 (7 ), uint8 (0x83 )) // SIGHASH_SINGLE_ANYONECANPAY
187+
188+ f .Fuzz (func (t * testing.T , seed int64 , sigHashTypeByte uint8 ) {
189+ r := rand .New (rand .NewSource (seed ))
190+ privkey , err := btcec .NewPrivateKey ()
191+ require .NoError (t , err )
192+
193+ dataLen := r .Int31n (200 ) + 1
194+ dataToSign := datagen .GenRandomByteArray (r , uint64 (dataLen ))
195+
196+ sigHashType := txscript .SigHashType (sigHashTypeByte )
197+ address , witness , err := datagen .SignWithP2TrSpendAddressWithSigHashType (
198+ dataToSign ,
199+ privkey ,
200+ net ,
201+ sigHashType ,
202+ )
203+
204+ // btcd's TaprootWitnessSignature validates SIGHASH types according to BIP 341
205+ // Valid Taproot sighash types are: 0x00-0x03 (DEFAULT, ALL, NONE, SINGLE)
206+ // and 0x81-0x83 (with ANYONECANPAY flag)
207+ isValidTaprootSigHash := (sigHashTypeByte <= 0x03 ) ||
208+ (sigHashTypeByte >= 0x81 && sigHashTypeByte <= 0x83 )
209+
210+ if isValidTaprootSigHash {
211+ // btcd should allow signing with any valid BIP 341 sighash type
212+ require .NoError (t , err , "Signing with valid Taproot sighash type 0x%02x should succeed: %v" , sigHashTypeByte , err )
213+ } else {
214+ // btcd should reject invalid sighash types during signing for Taproot
215+ require .Error (t , err , "btcd should reject invalid Taproot sighash type 0x%02x during signing" , sigHashTypeByte )
216+ // Can't test our verification layer if btcd rejects during signing
217+ return
218+ }
219+
220+ witnessDecoded , err := bip322 .SimpleSigToWitness (witness )
221+ require .NoError (t , err )
222+
223+ err = bip322 .VerifyP2WPKHAndP2TR (
224+ dataToSign ,
225+ witnessDecoded ,
226+ address ,
227+ net ,
228+ )
229+
230+ // BIP-322 is more restrictive than BIP 341 for Taproot
231+ // BIP 341 allows: 0x00-0x03, 0x81-0x83 (btcd validated this during signing)
232+ // BIP-322 only allows: 0x00 (DEFAULT) and 0x01 (ALL)
233+ // Our verification layer must reject all other sighash types
234+ if sigHashType == txscript .SigHashDefault || sigHashType == txscript .SigHashAll {
235+ require .NoError (t , err , "BIP-322 should accept SIGHASH_DEFAULT (0x00) and SIGHASH_ALL (0x01) for P2TR" )
236+ } else {
237+ // btcd allowed signing (valid BIP 341), but our BIP-322 verification must reject
238+ require .Error (t , err , "BIP-322 should reject sighash type 0x%02x for P2TR (even though it's valid in BIP 341)" , sigHashTypeByte )
239+ require .Contains (t , err .Error (), "sighash validation failed" )
240+ }
241+ })
242+ }
0 commit comments