1use sha2::{Sha256, Digest};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct Transaction {
8 pub version: i32,
10 pub inputs: Vec<TxInput>,
12 pub outputs: Vec<TxOutput>,
14 pub locktime: u32,
16}
17
18impl Default for Transaction {
19 fn default() -> Self {
20 Self {
21 version: 2,
22 inputs: Vec::new(),
23 outputs: Vec::new(),
24 locktime: 0,
25 }
26 }
27}
28
29impl Transaction {
30 pub fn new() -> Self {
32 Self::default()
33 }
34
35 pub fn is_segwit(&self) -> bool {
37 self.inputs.iter().any(|input| !input.witness.is_empty())
38 }
39
40 pub fn txid(&self) -> [u8; 32] {
42 let bytes = self.serialize_legacy();
43 let hash1 = Sha256::digest(&bytes);
44 let hash2 = Sha256::digest(hash1);
45 let mut txid: [u8; 32] = hash2.into();
46 txid.reverse(); txid
48 }
49
50 pub fn wtxid(&self) -> [u8; 32] {
52 if !self.is_segwit() {
53 return self.txid();
54 }
55 let bytes = self.serialize();
56 let hash1 = Sha256::digest(&bytes);
57 let hash2 = Sha256::digest(hash1);
58 let mut wtxid: [u8; 32] = hash2.into();
59 wtxid.reverse();
60 wtxid
61 }
62
63 pub fn serialize(&self) -> Vec<u8> {
65 if self.is_segwit() {
66 self.serialize_segwit()
67 } else {
68 self.serialize_legacy()
69 }
70 }
71
72 pub fn serialize_legacy(&self) -> Vec<u8> {
74 let mut bytes = Vec::new();
75
76 bytes.extend_from_slice(&self.version.to_le_bytes());
78
79 bytes.extend_from_slice(&encode_varint(self.inputs.len() as u64));
81
82 for input in &self.inputs {
84 bytes.extend_from_slice(&input.txid);
85 bytes.extend_from_slice(&input.vout.to_le_bytes());
86 bytes.extend_from_slice(&encode_varint(input.script_sig.len() as u64));
87 bytes.extend_from_slice(&input.script_sig);
88 bytes.extend_from_slice(&input.sequence.to_le_bytes());
89 }
90
91 bytes.extend_from_slice(&encode_varint(self.outputs.len() as u64));
93
94 for output in &self.outputs {
96 bytes.extend_from_slice(&output.value.to_le_bytes());
97 bytes.extend_from_slice(&encode_varint(output.script_pubkey.len() as u64));
98 bytes.extend_from_slice(&output.script_pubkey);
99 }
100
101 bytes.extend_from_slice(&self.locktime.to_le_bytes());
103
104 bytes
105 }
106
107 fn serialize_segwit(&self) -> Vec<u8> {
109 let mut bytes = Vec::new();
110
111 bytes.extend_from_slice(&self.version.to_le_bytes());
113
114 bytes.push(0x00); bytes.push(0x01); bytes.extend_from_slice(&encode_varint(self.inputs.len() as u64));
120
121 for input in &self.inputs {
123 bytes.extend_from_slice(&input.txid);
124 bytes.extend_from_slice(&input.vout.to_le_bytes());
125 bytes.extend_from_slice(&encode_varint(input.script_sig.len() as u64));
126 bytes.extend_from_slice(&input.script_sig);
127 bytes.extend_from_slice(&input.sequence.to_le_bytes());
128 }
129
130 bytes.extend_from_slice(&encode_varint(self.outputs.len() as u64));
132
133 for output in &self.outputs {
135 bytes.extend_from_slice(&output.value.to_le_bytes());
136 bytes.extend_from_slice(&encode_varint(output.script_pubkey.len() as u64));
137 bytes.extend_from_slice(&output.script_pubkey);
138 }
139
140 for input in &self.inputs {
142 bytes.extend_from_slice(&encode_varint(input.witness.len() as u64));
143 for item in &input.witness {
144 bytes.extend_from_slice(&encode_varint(item.len() as u64));
145 bytes.extend_from_slice(item);
146 }
147 }
148
149 bytes.extend_from_slice(&self.locktime.to_le_bytes());
151
152 bytes
153 }
154
155 pub fn size(&self) -> usize {
157 self.serialize().len()
158 }
159
160 pub fn weight(&self) -> usize {
162 let base_size = self.serialize_legacy().len();
163 let total_size = self.serialize().len();
164 base_size * 3 + total_size
165 }
166
167 pub fn vsize(&self) -> usize {
169 self.weight().div_ceil(4)
170 }
171
172 pub fn to_hex(&self) -> String {
174 self.serialize()
175 .iter()
176 .map(|b| format!("{:02x}", b))
177 .collect()
178 }
179}
180
181#[derive(Debug, Clone, PartialEq, Eq)]
183pub struct TxInput {
184 pub txid: [u8; 32],
186 pub vout: u32,
188 pub script_sig: Vec<u8>,
190 pub sequence: u32,
192 pub witness: Vec<Vec<u8>>,
194}
195
196impl TxInput {
197 pub fn new(txid: [u8; 32], vout: u32) -> Self {
199 Self {
200 txid,
201 vout,
202 script_sig: Vec::new(),
203 sequence: 0xFFFFFFFF,
204 witness: Vec::new(),
205 }
206 }
207}
208
209#[derive(Debug, Clone, PartialEq, Eq)]
211pub struct TxOutput {
212 pub value: u64,
214 pub script_pubkey: Vec<u8>,
216}
217
218impl TxOutput {
219 pub fn new(value: u64, script_pubkey: Vec<u8>) -> Self {
221 Self { value, script_pubkey }
222 }
223}
224
225#[derive(Debug, Clone)]
227pub struct Utxo {
228 pub txid: [u8; 32],
230 pub vout: u32,
232 pub value: u64,
234 pub script_pubkey: Vec<u8>,
236 pub address: String,
238}
239
240pub fn encode_varint(n: u64) -> Vec<u8> {
242 if n < 0xFD {
243 vec![n as u8]
244 } else if n <= 0xFFFF {
245 let mut v = vec![0xFD];
246 v.extend_from_slice(&(n as u16).to_le_bytes());
247 v
248 } else if n <= 0xFFFFFFFF {
249 let mut v = vec![0xFE];
250 v.extend_from_slice(&(n as u32).to_le_bytes());
251 v
252 } else {
253 let mut v = vec![0xFF];
254 v.extend_from_slice(&n.to_le_bytes());
255 v
256 }
257}
258
259#[cfg(test)]
260mod tests {
261 use super::*;
262
263 #[test]
264 fn test_encode_varint() {
265 assert_eq!(encode_varint(0), vec![0x00]);
266 assert_eq!(encode_varint(252), vec![0xFC]);
267 assert_eq!(encode_varint(253), vec![0xFD, 0xFD, 0x00]);
268 assert_eq!(encode_varint(0xFFFF), vec![0xFD, 0xFF, 0xFF]);
269 }
270
271 #[test]
272 fn test_empty_transaction() {
273 let tx = Transaction::new();
274 assert_eq!(tx.version, 2);
275 assert!(tx.inputs.is_empty());
276 assert!(tx.outputs.is_empty());
277 assert!(!tx.is_segwit());
278 }
279}