@@ -189,6 +189,100 @@ def sec_decode(cls, data: bytearray) -> PubKey:
189189 y = - y % pabtc .secp256k1 .P
190190 return PubKey (x , y )
191191
192+
193+ class ScriptPubKey :
194+ # The Script pubkey is the locking code for an output. It's made up of script, which is a mini programming language
195+ # that allows you to place different types of locks on your outputs.
196+
197+ @classmethod
198+ def p2pk (cls , pubkey : PubKey ) -> bytearray :
199+ data = bytearray ()
200+ data .extend (pabtc .opcode .op_pushdata (pubkey .sec ()))
201+ data .append (pabtc .opcode .op_checksig )
202+ return data
203+
204+ @classmethod
205+ def p2pkh (cls , pubkey_hash : bytearray ) -> bytearray :
206+ assert len (pubkey_hash ) == 20
207+ data = bytearray ()
208+ data .append (pabtc .opcode .op_dup )
209+ data .append (pabtc .opcode .op_hash160 )
210+ data .extend (pabtc .opcode .op_pushdata (pubkey_hash ))
211+ data .append (pabtc .opcode .op_equalverify )
212+ data .append (pabtc .opcode .op_checksig )
213+ return data
214+
215+ @classmethod
216+ def p2ms (cls , m : int , pubkey : typing .List [PubKey ]) -> bytearray :
217+ data = bytearray ()
218+ data .append (pabtc .opcode .op_n (m ))
219+ for e in pubkey :
220+ data .extend (pabtc .opcode .op_pushdata (e .sec ()))
221+ data .append (pabtc .opcode .op_n (len (pubkey )))
222+ data .append (pabtc .opcode .op_checkmultisig )
223+ return data
224+
225+ @classmethod
226+ def p2sh (cls , redeem_hash : bytearray ) -> bytearray :
227+ assert len (redeem_hash ) == 20
228+ data = bytearray ()
229+ data .append (pabtc .opcode .op_hash160 )
230+ data .extend (pabtc .opcode .op_pushdata (redeem_hash ))
231+ data .append (pabtc .opcode .op_equal )
232+ return data
233+
234+ @classmethod
235+ def p2sh_p2ms (cls , m : int , pubkey : typing .List [PubKey ]) -> bytearray :
236+ redeem = cls .p2ms (m , pubkey )
237+ redeem_hash = hash160 (redeem )
238+ return cls .p2sh (redeem_hash )
239+
240+ @classmethod
241+ def p2sh_p2wpkh (cls , pubkey_hash : bytearray ) -> bytearray :
242+ assert len (pubkey_hash ) == 20
243+ redeem = cls .p2wpkh (pubkey_hash )
244+ redeem_hash = hash160 (redeem )
245+ return cls .p2sh (redeem_hash )
246+
247+ @classmethod
248+ def p2sh_p2wsh (cls , redeem_hash : bytearray ) -> bytearray :
249+ assert len (redeem_hash ) == 32
250+ redeem = cls .p2wsh (redeem_hash )
251+ redeem_hash = hash160 (redeem )
252+ return cls .p2sh (redeem_hash )
253+
254+ @classmethod
255+ def p2wpkh (cls , pubkey_hash : bytearray ) -> bytearray :
256+ assert len (pubkey_hash ) == 20
257+ data = bytearray ()
258+ data .append (pabtc .opcode .op_0 )
259+ data .extend (pabtc .opcode .op_pushdata (pubkey_hash ))
260+ return data
261+
262+ @classmethod
263+ def p2wsh (cls , redeem_hash : bytearray ) -> bytearray :
264+ # The script hash within a p2wsh is a single sha-256. It is not a double sha-256 hash (i.e. hash256) as is
265+ # commonly used everywhere else in bitcoin, nor is it the hash160 of a script like in p2sh.
266+ assert len (redeem_hash ) == 32
267+ data = bytearray ()
268+ data .append (pabtc .opcode .op_0 )
269+ data .extend (pabtc .opcode .op_pushdata (redeem_hash ))
270+ return data
271+
272+ @classmethod
273+ def p2wsh_p2ms (cls , m : int , pubkey : typing .List [PubKey ]) -> bytearray :
274+ redeem = cls .p2ms (m , pubkey )
275+ redeem_hash = hashwsh (redeem )
276+ return cls .p2wsh (redeem_hash )
277+
278+ @classmethod
279+ def p2tr (cls , root : bytearray ) -> bytearray :
280+ assert len (root ) == 32
281+ data = bytearray ()
282+ data .append (pabtc .opcode .op_1 )
283+ data .extend (pabtc .opcode .op_pushdata (root ))
284+ return data
285+
192286# Bitcoin address prefix: https://en.bitcoin.it/wiki/List_of_address_prefixes
193287
194288
@@ -210,22 +304,15 @@ def address_p2sh(redeem: bytearray) -> str:
210304
211305
212306def address_p2sh_p2ms (n : int , pubkey : typing .List [PubKey ]) -> str :
213- redeem_script = []
214- redeem_script .append (pabtc .opcode .op_n (n ))
215- for e in pubkey :
216- redeem_script .append (pabtc .opcode .op_pushdata (e .sec ()))
217- redeem_script .append (pabtc .opcode .op_n (len (pubkey )))
218- redeem_script .append (pabtc .opcode .op_checkmultisig )
219- redeem_script = script (redeem_script )
220- return address_p2sh (redeem_script )
307+ redeem = ScriptPubKey .p2ms (n , pubkey )
308+ return address_p2sh (redeem )
221309
222310
223311def address_p2sh_p2wpkh (pubkey : PubKey ) -> str :
224312 # Nested Segwit.
225313 # See https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki
226- pubkey_hash = hash160 (pubkey .sec ())
227- redeem_script = script ([pabtc .opcode .op_0 , pabtc .opcode .op_pushdata (pubkey_hash )])
228- return address_p2sh (redeem_script )
314+ redeem = ScriptPubKey .p2wpkh (pubkey .hash ())
315+ return address_p2sh (redeem )
229316
230317
231318def address_p2wpkh (pubkey : PubKey ) -> str :
@@ -737,41 +824,25 @@ def script_pubkey_p2pkh(addr: str) -> bytearray:
737824 assert data [0 ] == pabtc .config .current .prefix .base58 .p2pkh
738825 hash = data [0x01 :0x15 ]
739826 assert pabtc .core .hash256 (data [0x00 :0x15 ])[:4 ] == data [0x15 :0x19 ]
740- return script ([
741- pabtc .opcode .op_dup ,
742- pabtc .opcode .op_hash160 ,
743- pabtc .opcode .op_pushdata (hash ),
744- pabtc .opcode .op_equalverify ,
745- pabtc .opcode .op_checksig ,
746- ])
827+ return ScriptPubKey .p2pkh (hash )
747828
748829
749830def script_pubkey_p2sh (addr : str ) -> bytearray :
750831 data = pabtc .base58 .decode (addr )
751832 assert data [0 ] == pabtc .config .current .prefix .base58 .p2sh
752833 hash = data [0x01 :0x15 ]
753834 assert pabtc .core .hash256 (data [0x00 :0x15 ])[:4 ] == data [0x15 :0x19 ]
754- return script ([
755- pabtc .opcode .op_hash160 ,
756- pabtc .opcode .op_pushdata (hash ),
757- pabtc .opcode .op_equal ,
758- ])
835+ return ScriptPubKey .p2sh (hash )
759836
760837
761838def script_pubkey_p2wpkh (addr : str ) -> bytearray :
762839 hash = pabtc .bech32 .decode_segwit_addr (pabtc .config .current .prefix .bech32 , 0 , addr )
763- return script ([
764- pabtc .opcode .op_0 ,
765- pabtc .opcode .op_pushdata (hash ),
766- ])
840+ return ScriptPubKey .p2wpkh (hash )
767841
768842
769843def script_pubkey_p2tr (addr : str ) -> bytearray :
770844 pubx = pabtc .bech32 .decode_segwit_addr (pabtc .config .current .prefix .bech32 , 1 , addr )
771- return script ([
772- pabtc .opcode .op_1 ,
773- pabtc .opcode .op_pushdata (pubx ),
774- ])
845+ return ScriptPubKey .p2tr (pubx )
775846
776847
777848def script_pubkey (addr : str ) -> bytearray :
0 commit comments