bitcoin_cash/
scripts.rs

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}