@@ -18,7 +18,7 @@ pub const NUMS_H: [u8; 32] = [
1818 0x07 , 0x8a , 0x5a , 0x0f , 0x28 , 0xec , 0x96 , 0xd5 , 0x47 , 0xbf , 0xee , 0x9a , 0xce , 0x80 , 0x3a , 0xc0 ,
1919] ;
2020
21- #[ derive( Debug , Clone , Copy ) ]
21+ #[ derive( Debug , Clone , Copy , PartialEq ) ]
2222pub enum SpInputs {
2323 P2TR ,
2424 P2WPKH ,
@@ -110,9 +110,237 @@ pub fn compute_shared_secret(sk: &SecretKey, pk: &PublicKey) -> PublicKey {
110110#[ cfg( test) ]
111111#[ cfg_attr( coverage_nightly, coverage( off) ) ]
112112mod tests {
113- use super :: * ;
114- use bitcoin:: OutPoint ;
115- use bitcoin:: Txid ;
113+ use super :: {
114+ get_smallest_lexicographic_outpoint, tag_txin, Hash , ScriptBuf , SpInputs , TxIn , NUMS_H ,
115+ } ;
116+ use bitcoin:: {
117+ hex:: test_hex_unwrap as hex, taproot:: TAPROOT_ANNEX_PREFIX , OutPoint , Sequence , Txid ,
118+ Witness ,
119+ } ;
120+
121+ #[ test]
122+ fn test_tag_txin_p2sh_p2wpkh ( ) {
123+ let script_pubkey = ScriptBuf :: from_hex ( "a914809b71783f1b55eeadeb1678baef0c994adc425987" )
124+ . expect ( "should succeed" ) ;
125+ // third input from testnet tx 65eb5594eda20b3a2437c2e2c28ba7633f0492cbb33f62ee31469b913ce8a5ca
126+ let txin = TxIn {
127+ previous_output : OutPoint {
128+ txid : "04d984cdcf728975c173c45c49a242cedee2da5dc200b2f83ca6a98aecf11280"
129+ . parse ( )
130+ . unwrap ( ) ,
131+ vout : 1 ,
132+ } ,
133+ script_sig : ScriptBuf :: from_hex ( "1600146a721dcca372f3c17b2c649b2ba61aa0fda98a91" )
134+ . unwrap ( ) ,
135+ sequence : Sequence :: MAX ,
136+ witness : Witness :: from_slice ( & [ hex ! (
137+ "304402204ebf033caf3a1a210623e98b49acb41db2220c531843106d5c50736b144b15aa02201a006be1ebc2ffef0927d4458e3bb5e41e5abc7e44fc5ceb920049b46f87971101"
138+ ) , hex ! ( "02ae68d299cbb8ab99bf24c9af79a7b13d28ac8cd21f6f7f750300eda41a589a5d" ) ] ) ,
139+ } ;
140+
141+ let tagged_input = tag_txin ( & txin, & script_pubkey) ;
142+
143+ assert_eq ! ( Some ( SpInputs :: WrappedSegwit ) , tagged_input) ;
144+ }
145+
146+ #[ test]
147+ fn test_tag_txin_p2sh_p2wsh ( ) {
148+ let script_pubkey = ScriptBuf :: from_hex ( "a914257014cec2f75c19367b2a6a0e08b9f304108e3b87" )
149+ . expect ( "should succeed" ) ;
150+ // only input from mainnet tx 55c7c71c63b87478cd30d401e7ca5344a2e159dc8d6990df695c7e0cb2f82783
151+ let txin = TxIn {
152+ previous_output : OutPoint {
153+ txid : "c57007980fabfd7c44895d8fc2c28c6ead93483b7c2bfec682ce0a3eaa4008ce"
154+ . parse ( )
155+ . unwrap ( ) ,
156+ vout : 0 ,
157+ } ,
158+ script_sig : ScriptBuf :: from_hex ( "220020973cfd44e60501c38320ab1105fb3ee3916d2952702e3c8cb4cbb7056aa6b47f" )
159+ . unwrap ( ) ,
160+ sequence : Sequence :: MAX ,
161+ witness : Witness :: from_slice ( & [ hex ! (
162+ "0400473044022047ebba593cba4048da04316b9fb6c076d95d17175d7560edc93868a7d170767502203d0ce939ae462ca685a15f5fd3a64b7a1793cb10473665d5bedd3322c55a2b1001473044022022a8a0ae1f80934abb38d4f8c3febf6f5c5c43e7e70460aa71f9a895aaea4d950220023b8f4d2fd90abdbe6f80c9bcb2b38c7326e5e9e0f3b1ea25a5499d240cacb20169522103591da02bf7c80dc5d0edee4bbbfad7e58320785e3e54d4dab117152361f7002c21027ea2bc65ce49dcd748e4e41a0c8881be388b9182ad5e47579a0de0119803827b2103c5fdaf887f76119a73a7f738d5d4a451ff07bbbc83422c529452d8a36ae59e3953ae"
163+ ) ] ) ,
164+ } ;
165+
166+ let tagged_input = tag_txin ( & txin, & script_pubkey) ;
167+
168+ assert_eq ! ( None , tagged_input) ;
169+ }
170+
171+ #[ test]
172+ fn test_tag_txin_p2tr ( ) {
173+ let script_pubkey = ScriptBuf :: from_hex (
174+ "51200f0c8db753acbd17343a39c2f3f4e35e4be6da749f9e35137ab220e7b238a667" ,
175+ )
176+ . expect ( "should succeed" ) ;
177+ // only input from mainnet tx 091d2aaadc409298fd8353a4cd94c319481a0b4623fb00872fe240448e93fcbe
178+ let txin = TxIn {
179+ previous_output : OutPoint {
180+ txid : "a7115c7267dbb4aab62b37818d431b784fe731f4d2f9fa0939a9980d581690ec"
181+ . parse ( )
182+ . unwrap ( ) ,
183+ vout : 0 ,
184+ } ,
185+ script_sig : ScriptBuf :: new ( ) ,
186+ sequence : Sequence :: MAX ,
187+ witness : Witness :: from_slice ( & [ hex ! (
188+ "b693a0797b24bae12ed0516a2f5ba765618dca89b75e498ba5b745b71644362298a45ca39230d10a02ee6290a91cebf9839600f7e35158a447ea182ea0e022ae01"
189+ ) ] ) ,
190+ } ;
191+
192+ let tagged_input = tag_txin ( & txin, & script_pubkey) ;
193+
194+ assert_eq ! ( Some ( SpInputs :: P2TR ) , tagged_input) ;
195+ }
196+
197+ #[ test]
198+ fn test_tag_txin_p2tr_nums_point ( ) {
199+ let script_pubkey = ScriptBuf :: from_hex (
200+ "51200f0c8db753acbd17343a39c2f3f4e35e4be6da749f9e35137ab220e7b238a667" ,
201+ )
202+ . expect ( "should succeed" ) ;
203+ let mut nums_in_witness = [ 0u8 ; 33 ] ;
204+ nums_in_witness[ 1 ..33 ] . clone_from_slice ( & NUMS_H ) ;
205+ // Crafted P2TR Tx with NUMS point as internal key
206+ let txin = TxIn {
207+ previous_output : OutPoint {
208+ txid : "a7115c7267dbb4aab62b37818d431b784fe731f4d2f9fa0939a9980d581690ec"
209+ . parse ( )
210+ . unwrap ( ) ,
211+ vout : 0 ,
212+ } ,
213+ script_sig : ScriptBuf :: new ( ) ,
214+ sequence : Sequence :: MAX ,
215+ witness : Witness :: from_slice ( & [
216+ hex ! ( "02ae68d299cbb8ab99bf24c9af79a7b13d28ac8cd21f6f7f750300eda41a589a5d" ) ,
217+ hex ! ( "02ae68d299cbb8ab99bf24c9af79a7b13d28ac8cd21f6f7f750300eda41a589a5d" ) ,
218+ nums_in_witness. to_vec ( ) ,
219+ vec ! [ TAPROOT_ANNEX_PREFIX ] ,
220+ ] ) ,
221+ } ;
222+
223+ let tagged_input = tag_txin ( & txin, & script_pubkey) ;
224+
225+ assert_eq ! ( None , tagged_input) ;
226+ }
227+
228+ #[ test]
229+ fn test_tag_txin_p2wpkh ( ) {
230+ let script_pubkey = ScriptBuf :: from_hex ( "001453d9c40342ee880e766522c3e2b854d37f2b3cbf" )
231+ . expect ( "should succeed" ) ;
232+ // only input from mainnet tx 091d2aaadc409298fd8353a4cd94c319481a0b4623fb00872fe240448e93fcbe
233+ let txin = TxIn {
234+ previous_output : OutPoint {
235+ txid : "a7115c7267dbb4aab62b37818d431b784fe731f4d2f9fa0939a9980d581690ec"
236+ . parse ( )
237+ . unwrap ( ) ,
238+ vout : 1 ,
239+ } ,
240+ script_sig : ScriptBuf :: new ( ) ,
241+ sequence : Sequence :: MAX ,
242+ witness : Witness :: from_slice ( & [
243+ hex ! ( "3044022025f63cdce46c749ff1953200b4fda615c7bbd6aa1717850c39297ce1087071ca0220675349fe9f9c6cf626f66abfd4ea1381b470a8315d1a8922d2573dc1410c661501" ) ,
244+ hex ! ( "03eb01a0190cb4d5da80878b20ff3823cc45b4fe55288393ee5d9f8a7f5eb65bbb" ) ,
245+ ] ) ,
246+ } ;
247+
248+ let tagged_input = tag_txin ( & txin, & script_pubkey) ;
249+
250+ assert_eq ! ( Some ( SpInputs :: P2WPKH ) , tagged_input) ;
251+ }
252+
253+ #[ test]
254+ fn test_tag_txin_invalid_p2wpkh_input_with_non_empty_script_sig ( ) {
255+ let script_pubkey = ScriptBuf :: from_hex ( "001453d9c40342ee880e766522c3e2b854d37f2b3cbf" )
256+ . expect ( "should succeed" ) ;
257+ // Crafted example taking mainnet tx 091d2aaadc409298fd8353a4cd94c319481a0b4623fb00872fe240448e93fcbe as template
258+ let txin = TxIn {
259+ previous_output : OutPoint {
260+ txid : "a7115c7267dbb4aab62b37818d431b784fe731f4d2f9fa0939a9980d581690ec"
261+ . parse ( )
262+ . unwrap ( ) ,
263+ vout : 1 ,
264+ } ,
265+ script_sig : ScriptBuf :: from_hex ( "00" ) . expect ( "should succeed" ) ,
266+ sequence : Sequence :: MAX ,
267+ witness : Witness :: from_slice ( & [
268+ hex ! ( "3044022025f63cdce46c749ff1953200b4fda615c7bbd6aa1717850c39297ce1087071ca0220675349fe9f9c6cf626f66abfd4ea1381b470a8315d1a8922d2573dc1410c661501" ) ,
269+ hex ! ( "03eb01a0190cb4d5da80878b20ff3823cc45b4fe55288393ee5d9f8a7f5eb65bbb" ) ,
270+ ] ) ,
271+ } ;
272+
273+ let tagged_input = tag_txin ( & txin, & script_pubkey) ;
274+
275+ assert_eq ! ( None , tagged_input) ;
276+ }
277+
278+ #[ test]
279+ fn test_tag_txin_p2pkh ( ) {
280+ let script_pubkey =
281+ ScriptBuf :: from_hex ( "76a9140c443537e6e31f06e6edb2d4bb80f8481e2831ac88ac" )
282+ . expect ( "should succeed" ) ;
283+ // only input from mainnet tx 4316fe7be359937317f42ffaf05ab02554297fb83096a0beb985a25f9e338215
284+ let txin = TxIn {
285+ previous_output : OutPoint {
286+ txid : "40e331b67c0fe7750bb3b1943b378bf702dce86124dc12fa5980f975db7ec930"
287+ . parse ( )
288+ . unwrap ( ) ,
289+ vout : 0 ,
290+ } ,
291+ script_sig : ScriptBuf :: from_hex ( "473044022076baac422976af25b32479ccb81df8a2d7f4f73cfb2ff98cfe10241feefdb43702204c08a9fc646150a9aceb3ebc26344e1596ddd6b7bc8aa44cb116a3adca173e3701210360a953b3da3f5cc0ec246a99411c19916fab7e72b59e105955b6e3e9d3a44773" ) . expect ( "should succeed" ) ,
292+ sequence : Sequence :: MAX ,
293+ witness : Witness :: new ( ) ,
294+ } ;
295+
296+ let tagged_input = tag_txin ( & txin, & script_pubkey) ;
297+
298+ assert_eq ! ( Some ( SpInputs :: P2PKH ) , tagged_input) ;
299+ }
300+
301+ #[ test]
302+ fn test_tag_txin_p2pk ( ) {
303+ let script_pubkey = ScriptBuf :: from_hex ( "41049464205950188c29d377eebca6535e0f3699ce4069ecd77ffebfbd0bcf95e3c134cb7d2742d800a12df41413a09ef87a80516353a2f0a280547bb5512dc03da8ac" )
304+ . expect ( "should succeed" ) ;
305+ // only input from mainnet tx e827a366ad4fc9a305e0901fe1eefc7e9fb8d70655a079877cf1ead0c3618ec0
306+ let txin = TxIn {
307+ previous_output : OutPoint {
308+ txid : "1db6251a9afce7025a2061a19e63c700dffc3bec368bd1883decfac353357a9d"
309+ . parse ( )
310+ . unwrap ( ) ,
311+ vout : 1 ,
312+ } ,
313+ script_sig : ScriptBuf :: from_hex ( "483045022100c219a522e65ca8500ebe05a70d5a49d840ccc15f2afa4ee9df783f06b2a322310220489a46c37feb33f52c586da25c70113b8eea41216440eb84771cb67a67fdb68c01" ) . expect ( "should succeed" ) ,
314+ sequence : Sequence :: MAX ,
315+ witness : Witness :: new ( ) ,
316+ } ;
317+
318+ let tagged_input = tag_txin ( & txin, & script_pubkey) ;
319+
320+ assert_eq ! ( None , tagged_input) ;
321+ }
322+
323+ #[ test]
324+ fn test_tag_txin_p2sh_no_witness_script_sig_non_empty_spk_is_not_p2wpkh ( ) {
325+ let script_pubkey = ScriptBuf :: from_hex ( "a914748284390f9e263a4b766a75d0633c50426eb87587" )
326+ . expect ( "should succeed" ) ;
327+ // Eleventh input from mainnet tx 30c239f3ae062c5f1151476005fd0057adfa6922de1b38d0f11eb657a8157b30
328+ let txin = TxIn {
329+ previous_output : OutPoint {
330+ txid : "450c309b70fb3f71b63b10ce60af17499bd21b1db39aa47b19bf22166ee67144"
331+ . parse ( )
332+ . unwrap ( ) ,
333+ vout : 1 ,
334+ } ,
335+ script_sig : ScriptBuf :: from_hex ( "00473044022100d0ed946330182916da16a6149cd313a4b1a7b41591ee52fb3e79d64e36139d66021f6ccf173040ef24cb45c4db3e9c771c938a1ba2cf8d2404416f70886e360af401475121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052ae" ) . expect ( "should succeed" ) ,
336+ sequence : Sequence :: MAX ,
337+ witness : Witness :: new ( ) ,
338+ } ;
339+
340+ let tagged_input = tag_txin ( & txin, & script_pubkey) ;
341+
342+ assert_eq ! ( None , tagged_input) ;
343+ }
116344
117345 #[ test]
118346 fn test_get_smallest_outpoint_different_txids_and_vouts ( ) {
0 commit comments