1use crate::{
2 encode_bitcoin_code, encoding_utils, error::Result, ByteArray, Hashed, Script, Sha256d,
3 SigHashFlags, ToPreimages, TxPreimage,
4};
5use serde_derive::{Deserialize, Serialize};
6
7pub const DEFAULT_SEQUENCE: u32 = 0xffff_ffff;
8pub const MAX_SIGNATURE_SIZE: usize = 73; #[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Default)]
11pub struct TxOutpoint {
12 pub tx_hash: Sha256d,
13 pub vout: u32,
14}
15
16#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
17pub struct TxInput {
18 pub prev_out: TxOutpoint,
19 pub script: Script,
20 pub sequence: u32,
21
22 #[serde(skip)]
23 pub lock_script: Option<Script>,
24
25 #[serde(skip)]
26 pub value: Option<u64>,
27
28 #[serde(skip)]
29 pub is_p2sh: Option<bool>,
30}
31
32#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
33pub struct TxOutput {
34 pub value: u64,
35 pub script: Script,
36}
37
38#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
39pub struct UnhashedTx {
40 pub version: i32,
41 pub inputs: Vec<TxInput>,
42 pub outputs: Vec<TxOutput>,
43 pub lock_time: u32,
44}
45
46#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
47pub struct Tx {
48 #[serde(skip)]
49 unhashed_tx: UnhashedTx,
50
51 #[serde(skip)]
52 hash: Sha256d,
53
54 raw: ByteArray,
55}
56
57impl TxInput {
58 pub fn serialize(&self) -> Result<ByteArray> {
59 let vout = ByteArray::new("vout", encode_bitcoin_code(&self.prev_out.vout)?);
60 let sequence = ByteArray::new("sequence", encode_bitcoin_code(&self.sequence)?);
61 let script = self.script.serialize()?.named("script");
62 let mut script_len_ser = Vec::new();
63 encoding_utils::write_var_int(&mut script_len_ser, script.len() as u64)?;
64 let script_len = ByteArray::new("script_len", script_len_ser);
65 Ok(self
66 .prev_out
67 .tx_hash
68 .clone()
69 .concat(vout)
70 .concat(script_len)
71 .concat(script)
72 .concat(sequence))
73 }
74}
75
76impl TxOutput {
77 pub fn serialize(&self) -> Result<ByteArray> {
78 let value = ByteArray::new("value", encode_bitcoin_code(&self.value)?);
79 let script = self.script.serialize()?.named("script");
80 let mut script_len_ser = Vec::new();
81 encoding_utils::write_var_int(&mut script_len_ser, script.len() as u64)?;
82 let script_len = ByteArray::new("script_len", script_len_ser);
83 Ok(value.concat(script_len).concat(script))
84 }
85}
86
87impl UnhashedTx {
88 pub fn preimages(&self, sig_hash_flags: &[SigHashFlags]) -> Vec<Vec<TxPreimage>> {
89 TxPreimage::build_preimages(&SigTxPreimage {
90 tx: self,
91 sig_hash_flags,
92 })
93 }
94
95 pub fn serialize(&self) -> Result<ByteArray> {
96 let version = ByteArray::new("version", encode_bitcoin_code(&self.version)?);
97 let lock_time = ByteArray::new("lock_time", encode_bitcoin_code(&self.version)?);
98
99 let mut inputs_len_ser = Vec::new();
100 encoding_utils::write_var_int(&mut inputs_len_ser, self.inputs.len() as u64)?;
101 let inputs_len = ByteArray::new("inputs_len", inputs_len_ser);
102
103 let mut outputs_len_ser = Vec::new();
104 encoding_utils::write_var_int(&mut outputs_len_ser, self.outputs.len() as u64)?;
105 let outputs_len = ByteArray::new("outputs_len", outputs_len_ser);
106
107 let mut byte_array = version.concat(inputs_len);
108 for input in self.inputs.iter() {
109 byte_array = byte_array.concat(input.serialize()?);
110 }
111
112 byte_array = byte_array.concat(outputs_len);
113 for output in self.outputs.iter() {
114 byte_array = byte_array.concat(output.serialize()?);
115 }
116
117 Ok(byte_array.concat(lock_time))
118 }
119
120 pub fn hashed(self) -> Tx {
121 let raw = self.serialize().expect("Couldn't encode UnhashedTx");
122 let hash = Sha256d::digest(raw.clone());
123 Tx {
124 unhashed_tx: self,
125 raw,
126 hash,
127 }
128 }
129}
130
131impl Tx {
132 pub fn hash(&self) -> &Sha256d {
133 &self.hash
134 }
135
136 pub fn raw(&self) -> &ByteArray {
137 &self.raw
138 }
139
140 pub fn version(&self) -> i32 {
141 self.unhashed_tx.version
142 }
143
144 pub fn inputs(&self) -> &[TxInput] {
145 &self.unhashed_tx.inputs
146 }
147
148 pub fn outputs(&self) -> &[TxOutput] {
149 &self.unhashed_tx.outputs
150 }
151
152 pub fn lock_time(&self) -> u32 {
153 self.unhashed_tx.lock_time
154 }
155
156 pub fn preimages(&self, sig_hash_flags: &[SigHashFlags]) -> Vec<Vec<TxPreimage>> {
157 self.unhashed_tx.preimages(sig_hash_flags)
158 }
159}
160
161impl Default for UnhashedTx {
162 fn default() -> Self {
163 UnhashedTx {
164 version: 1,
165 inputs: vec![],
166 outputs: vec![],
167 lock_time: 0,
168 }
169 }
170}
171
172struct SigTxPreimage<'b> {
173 tx: &'b UnhashedTx,
174 sig_hash_flags: &'b [SigHashFlags],
175}
176
177impl ToPreimages for SigTxPreimage<'_> {
178 fn version(&self) -> i32 {
179 self.tx.version
180 }
181 fn num_inputs(&self) -> usize {
182 self.tx.inputs.len()
183 }
184 fn input_outpoint_at(&self, input_idx: usize) -> &TxOutpoint {
185 &self.tx.inputs[input_idx].prev_out
186 }
187 fn input_sequence_at(&self, input_idx: usize) -> u32 {
188 self.tx.inputs[input_idx].sequence
189 }
190 fn input_sig_hash_flags_at(&self, _input_idx: usize) -> &[SigHashFlags] {
191 &self.sig_hash_flags
192 }
193 fn input_value_at(&self, input_idx: usize) -> u64 {
194 self.tx.inputs[input_idx]
195 .value
196 .expect("No known value for input")
197 }
198 fn input_lock_script_at(&self, input_idx: usize) -> Script {
199 self.tx.inputs[input_idx]
200 .lock_script
201 .clone()
202 .expect("No known lock_script for input")
203 }
204 fn num_outputs(&self) -> usize {
205 self.tx.outputs.len()
206 }
207 fn output_at(&self, output_idx: usize) -> &TxOutput {
208 &self.tx.outputs[output_idx]
209 }
210 fn lock_time(&self) -> u32 {
211 self.tx.lock_time
212 }
213}