qualia_client_core/wallet/
signer.rs1use crate::wallet::transaction::{encode_varint, Transaction};
2use bip32::XPrv;
3use k256::ecdsa::{signature::Signer, SigningKey};
4use sha2::{Digest, Sha256};
5
6pub const SIGHASH_ALL: u32 = 0x01;
7pub const SIGHASH_FORKID: u32 = 0x40;
8
9pub fn double_sha256(data: &[u8]) -> Vec<u8> {
10 let hash1 = Sha256::digest(data);
11 let hash2 = Sha256::digest(&hash1);
12 hash2.to_vec()
13}
14
15pub fn hash160(data: &[u8]) -> Vec<u8> {
16 use ripemd::{Digest as _, Ripemd160};
17 let sha = Sha256::digest(data);
18 let rip = Ripemd160::digest(&sha);
19 rip.to_vec()
20}
21
22pub fn sign_p2pkh_input(
23 tx: &Transaction,
24 input_index: usize,
25 prev_value: u64,
26 priv_key: &XPrv,
27) -> Vec<u8> {
28 let sighash_type = SIGHASH_ALL | SIGHASH_FORKID;
29
30 let mut hash_prevouts = Vec::new();
31 for input in &tx.inputs {
32 let mut txid_bytes = hex::decode(&input.prev_txid).unwrap_or_else(|_| vec![0; 32]);
33 txid_bytes.reverse();
34 hash_prevouts.extend_from_slice(&txid_bytes);
35 hash_prevouts.extend_from_slice(&input.prev_out_idx.to_le_bytes());
36 }
37 let hash_prevouts = double_sha256(&hash_prevouts);
38
39 let mut hash_sequence = Vec::new();
40 for input in &tx.inputs {
41 hash_sequence.extend_from_slice(&input.sequence.to_le_bytes());
42 }
43 let hash_sequence = double_sha256(&hash_sequence);
44
45 let mut hash_outputs = Vec::new();
46 for output in &tx.outputs {
47 hash_outputs.extend_from_slice(&output.value.to_le_bytes());
48 hash_outputs.extend_from_slice(&encode_varint(output.pk_script.len() as u64));
49 hash_outputs.extend_from_slice(&output.pk_script);
50 }
51 let hash_outputs = double_sha256(&hash_outputs);
52
53 let mut preimage = Vec::new();
54 preimage.extend_from_slice(&tx.version.to_le_bytes());
55 preimage.extend_from_slice(&hash_prevouts);
56 preimage.extend_from_slice(&hash_sequence);
57
58 let input = &tx.inputs[input_index];
59 let mut txid_bytes = hex::decode(&input.prev_txid).unwrap_or_else(|_| vec![0; 32]);
60 txid_bytes.reverse();
61 preimage.extend_from_slice(&txid_bytes);
62 preimage.extend_from_slice(&input.prev_out_idx.to_le_bytes());
63
64 let pubkey = priv_key.public_key().to_bytes();
66 let pubkey_hash = hash160(&pubkey);
67 let mut script_code = vec![0x76, 0xa9, 0x14];
68 script_code.extend_from_slice(&pubkey_hash);
69 script_code.extend_from_slice(&[0x88, 0xac]);
70 preimage.extend_from_slice(&encode_varint(script_code.len() as u64));
71 preimage.extend_from_slice(&script_code);
72
73 preimage.extend_from_slice(&prev_value.to_le_bytes());
74 preimage.extend_from_slice(&input.sequence.to_le_bytes());
75 preimage.extend_from_slice(&hash_outputs);
76 preimage.extend_from_slice(&tx.lock_time.to_le_bytes());
77 preimage.extend_from_slice(&sighash_type.to_le_bytes());
78
79 let sighash = double_sha256(&preimage);
80
81 let private_key_bytes = priv_key.private_key().to_bytes();
82 let signing_key = SigningKey::from_slice(private_key_bytes.as_slice()).expect("Valid key");
83 let signature: k256::ecdsa::Signature = signing_key.sign(&sighash);
84 let mut der_sig = signature.to_der().to_bytes().to_vec();
85
86 der_sig.push(sighash_type as u8);
88
89 let mut script_sig = Vec::new();
91 script_sig.push(der_sig.len() as u8);
92 script_sig.extend_from_slice(&der_sig);
93 script_sig.push(pubkey.len() as u8);
94 script_sig.extend_from_slice(&pubkey);
95
96 script_sig
97}