1use crate::{
2 Address, AddressType, ByteArray, Opcode::*, Pubkey, Script, SigHashFlags, Signatory, TxBuilder,
3 TxOutput, TxPreimage, MAX_SIGNATURE_SIZE,
4};
5
6#[derive(Clone)]
7pub struct P2PKHSignatory {
8 pub pubkey: Pubkey,
9 pub sig_hash_flags: SigHashFlags,
10}
11
12#[crate::script(P2PKHInputs, crate = "crate")]
13pub fn p2pkh_script(address: &Address, sig: ByteArray, pubkey: ByteArray) {
14 OP_DUP(pubkey);
15 let pk_hashed = OP_HASH160(pubkey);
16 let pk_hash = address.hash();
17 OP_EQUALVERIFY(pk_hashed, pk_hash);
18 let success = OP_CHECKSIG(sig, pubkey);
19}
20
21#[crate::script(P2SHInputs, crate = "crate")]
22pub fn p2sh_script(address: &Address, redeem_script: ByteArray) {
23 let script_hashed = OP_HASH160(redeem_script);
24 let script_hash = address.hash();
25 let success = OP_EQUAL(script_hashed, script_hash);
26}
27
28impl Into<Script> for &'_ Address<'_> {
29 fn into(self) -> Script {
30 match self.addr_type() {
31 AddressType::P2SH => p2sh_script(self).into(),
32 AddressType::P2PKH => p2pkh_script(self).into(),
33 }
34 }
35}
36
37impl Into<Script> for Address<'_> {
38 fn into(self) -> Script {
39 match self.addr_type() {
40 AddressType::P2SH => p2sh_script(&self).into(),
41 AddressType::P2PKH => p2pkh_script(&self).into(),
42 }
43 }
44}
45
46impl<'b> Signatory for P2PKHSignatory {
47 type Script = P2PKHInputs;
48 type Signatures = ByteArray;
49 fn sig_hash_flags(&self) -> Vec<SigHashFlags> {
50 vec![self.sig_hash_flags]
51 }
52 fn placeholder_signatures(&self) -> Self::Signatures {
53 ByteArray::new_unnamed(vec![0; MAX_SIGNATURE_SIZE])
54 }
55 fn build_script(
56 &self,
57 _tx_preimage: &[TxPreimage],
58 _unsigned_tx: &TxBuilder,
59 sigs: Self::Signatures,
60 _lock_script: &Script,
61 _tx_outputs: &[TxOutput],
62 ) -> Self::Script {
63 P2PKHInputs {
64 pubkey: self.pubkey.as_slice().into(),
65 sig: sigs.concat(ByteArray::new(
66 "sig_hash",
67 [self.sig_hash_flags.bits() as u8].as_ref(),
68 )),
69 }
70 }
71 fn is_p2sh(&self) -> bool {
72 false
73 }
74}