zcash_transparent/pczt/
signer.rs

1use crate::sighash::SignableInput;
2use alloc::vec::Vec;
3
4impl super::Input {
5    /// Signs the transparent spend with the given spend authorizing key.
6    ///
7    /// It is the caller's responsibility to perform any semantic validity checks on the
8    /// PCZT (for example, comfirming that the change amounts are correct) before calling
9    /// this method.
10    pub fn sign<C: secp256k1::Signing, F>(
11        &mut self,
12        index: usize,
13        calculate_sighash: F,
14        sk: &secp256k1::SecretKey,
15        secp: &secp256k1::Secp256k1<C>,
16    ) -> Result<(), SignerError>
17    where
18        F: FnOnce(SignableInput) -> [u8; 32],
19    {
20        let pubkey = sk.public_key(secp).serialize();
21
22        // Check that the corresponding pubkey appears in either `script_pubkey` or
23        // `redeem_script`.
24        // TODO
25
26        let sighash = calculate_sighash(SignableInput {
27            hash_type: self.sighash_type,
28            index,
29            // for p2pkh, always the same as script_pubkey
30            script_code: self.redeem_script.as_ref().unwrap_or(&self.script_pubkey),
31            script_pubkey: &self.script_pubkey,
32            value: self.value,
33        });
34
35        let msg = secp256k1::Message::from_digest_slice(&sighash).expect("32 bytes");
36        let sig = secp.sign_ecdsa(&msg, sk);
37
38        // Signature has to have the SighashType appended to it.
39        let mut sig_bytes: Vec<u8> = sig.serialize_der()[..].to_vec();
40        sig_bytes.extend([self.sighash_type.encode()]);
41
42        self.partial_signatures.insert(pubkey, sig_bytes);
43
44        Ok(())
45    }
46}
47
48/// Errors that can occur while signing a transparent input in a PCZT.
49#[derive(Debug)]
50pub enum SignerError {
51    /// The provided `sk` does not match any pubkey involved with spend control of the
52    /// input's spent coin.
53    WrongSpendingKey,
54}