anychain_bitcoin/
transaction.rs

1use crate::{
2    BitcoinAddress, BitcoinAmount, BitcoinFormat, BitcoinNetwork, BitcoinPublicKey, WitnessProgram,
3    BASE32_DECODE_TABLE,
4};
5use anychain_core::{
6    crypto::checksum as double_sha2, Transaction, TransactionError, TransactionId,
7};
8use anychain_core::{
9    hex,
10    no_std::{io::Read, *},
11    PublicKey,
12};
13use libsecp256k1::Signature;
14
15use base58::FromBase58;
16use bech32::{u5, FromBase32};
17use core::{fmt, str::FromStr};
18use serde::Serialize;
19pub use sha2::{Digest, Sha256};
20
21/// Returns the variable length integer of the given value.
22/// `<https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer>`
23pub fn variable_length_integer(value: u64) -> Result<Vec<u8>, TransactionError> {
24    match value {
25        // bounded by u8::max_value()
26        0..=252 => Ok(vec![value as u8]),
27        // bounded by u16::max_value()
28        253..=65535 => Ok([vec![0xfd], (value as u16).to_le_bytes().to_vec()].concat()),
29        // bounded by u32::max_value()
30        65536..=4294967295 => Ok([vec![0xfe], (value as u32).to_le_bytes().to_vec()].concat()),
31        // bounded by u64::max_value()
32        _ => Ok([vec![0xff], value.to_le_bytes().to_vec()].concat()),
33    }
34}
35
36/// Decode the value of a variable length integer.
37/// `<https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer>`
38pub fn read_variable_length_integer<R: Read>(mut reader: R) -> Result<usize, TransactionError> {
39    let mut flag = [0u8; 1];
40    let _ = reader.read(&mut flag)?;
41
42    match flag[0] {
43        0..=252 => Ok(flag[0] as usize),
44        0xfd => {
45            let mut size = [0u8; 2];
46            let _ = reader.read(&mut size)?;
47            match u16::from_le_bytes(size) {
48                s if s < 253 => Err(TransactionError::InvalidVariableSizeInteger(s as usize)),
49                s => Ok(s as usize),
50            }
51        }
52        0xfe => {
53            let mut size = [0u8; 4];
54            let _ = reader.read(&mut size)?;
55            match u32::from_le_bytes(size) {
56                s if s < 65536 => Err(TransactionError::InvalidVariableSizeInteger(s as usize)),
57                s => Ok(s as usize),
58            }
59        }
60        _ => {
61            let mut size = [0u8; 8];
62            let _ = reader.read(&mut size)?;
63            match u64::from_le_bytes(size) {
64                s if s < 4294967296 => {
65                    Err(TransactionError::InvalidVariableSizeInteger(s as usize))
66                }
67                s => Ok(s as usize),
68            }
69        }
70    }
71}
72
73pub struct BitcoinVector;
74
75impl BitcoinVector {
76    /// Read and output a vector with a variable length integer
77    pub fn read<R: Read, E, F>(mut reader: R, func: F) -> Result<Vec<E>, TransactionError>
78    where
79        F: Fn(&mut R) -> Result<E, TransactionError>,
80    {
81        let count = read_variable_length_integer(&mut reader)?;
82        (0..count).map(|_| func(&mut reader)).collect()
83    }
84
85    /// Read and output a vector with a variable length integer and the integer itself
86    pub fn read_witness<R: Read, E, F>(
87        mut reader: R,
88        func: F,
89    ) -> Result<(usize, Result<Vec<E>, TransactionError>), TransactionError>
90    where
91        F: Fn(&mut R) -> Result<E, TransactionError>,
92    {
93        let count = read_variable_length_integer(&mut reader)?;
94        Ok((count, Self::read(reader, func)))
95    }
96}
97
98/// Generate the script_pub_key of a corresponding address
99pub fn create_script_pub_key<N: BitcoinNetwork>(
100    address: &BitcoinAddress<N>,
101) -> Result<Vec<u8>, TransactionError> {
102    match address.format() {
103        BitcoinFormat::P2PKH => {
104            let bytes = &address.to_string().from_base58()?;
105
106            // Trim the prefix (1st byte) and the checksum (last 4 bytes)
107            let pub_key_hash = bytes[1..(bytes.len() - 4)].to_vec();
108
109            let mut script = vec![];
110            script.push(Opcode::OP_DUP as u8);
111            script.push(Opcode::OP_HASH160 as u8);
112            script.extend(variable_length_integer(pub_key_hash.len() as u64)?);
113            script.extend(pub_key_hash);
114            script.push(Opcode::OP_EQUALVERIFY as u8);
115            script.push(Opcode::OP_CHECKSIG as u8);
116            Ok(script)
117        }
118        BitcoinFormat::P2SH_P2WPKH => {
119            let script_bytes = &address.to_string().from_base58()?;
120            let script_hash = script_bytes[1..(script_bytes.len() - 4)].to_vec();
121
122            let mut script = vec![];
123            script.push(Opcode::OP_HASH160 as u8);
124            script.extend(variable_length_integer(script_hash.len() as u64)?);
125            script.extend(script_hash);
126            script.push(Opcode::OP_EQUAL as u8);
127            Ok(script)
128        }
129        BitcoinFormat::P2WSH => {
130            let (_, data, _) = bech32::decode(&address.to_string())?;
131            let (v, script) = data.split_at(1);
132            let script = Vec::from_base32(script)?;
133            let mut script_bytes = vec![v[0].to_u8(), script.len() as u8];
134            script_bytes.extend(script);
135            Ok(script_bytes)
136        }
137        BitcoinFormat::Bech32 => {
138            let (_, data, _) = bech32::decode(&address.to_string())?;
139            let (v, program) = data.split_at(1);
140            let program = Vec::from_base32(program)?;
141            let mut program_bytes = vec![v[0].to_u8(), program.len() as u8];
142            program_bytes.extend(program);
143            Ok(WitnessProgram::new(&program_bytes)?.to_scriptpubkey())
144        }
145        BitcoinFormat::CashAddr => {
146            let address = address.to_string();
147            let prefix = N::to_address_prefix(BitcoinFormat::CashAddr)?.prefix();
148
149            let start = if address.starts_with(&prefix) {
150                prefix.len() + 1
151            } else {
152                0
153            };
154
155            // trim the prefix and the checksum
156            let bytes_u8 = address.as_bytes()[start..address.len() - 8].to_vec();
157
158            let bytes_u5: Vec<u5> = bytes_u8
159                .iter()
160                .map(|byte| u5::try_from_u8(BASE32_DECODE_TABLE[*byte as usize] as u8).unwrap())
161                .collect();
162            let payload = Vec::<u8>::from_base32(&bytes_u5)?;
163            // trim the version byte, left the public key hash
164            let hash = payload[1..].to_vec();
165
166            let mut script = vec![];
167            script.push(Opcode::OP_DUP as u8);
168            script.push(Opcode::OP_HASH160 as u8);
169            script.extend(variable_length_integer(hash.len() as u64)?);
170            script.extend(hash);
171            script.push(Opcode::OP_EQUALVERIFY as u8);
172            script.push(Opcode::OP_CHECKSIG as u8);
173
174            Ok(script)
175        }
176    }
177}
178
179/// Construct and return the OP_RETURN script for the data
180/// output of a tx that spends 'amount' basic units of omni
181/// layer asset as indicated by 'property_id'.
182pub fn create_script_op_return(property_id: u32, amount: i64) -> Result<Vec<u8>, TransactionError> {
183    let mut script = vec![];
184
185    let msg_type: u16 = 0;
186    let msg_version: u16 = 0;
187
188    script.push(Opcode::OP_RETURN as u8);
189    script.push(Opcode::OP_PUSHBYTES_20 as u8);
190    script.push(b'o');
191    script.push(b'm');
192    script.push(b'n');
193    script.push(b'i');
194    script.append(&mut msg_version.to_be_bytes().to_vec());
195    script.append(&mut msg_type.to_be_bytes().to_vec());
196    script.append(&mut property_id.to_be_bytes().to_vec());
197    script.append(&mut amount.to_be_bytes().to_vec());
198
199    Ok(script)
200}
201
202/// Represents a Bitcoin signature hash
203/// `<https://en.bitcoin.it/wiki/OP_CHECKSIG>`
204#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
205#[allow(non_camel_case_types)]
206pub enum SignatureHash {
207    /// Signs all inputs and outputs.
208    SIGHASH_ALL = 0x01,
209
210    /// Signs all inputs and none of the outputs.
211    /// (e.g. "blank check" transaction, where any address can redeem the output)
212    SIGHASH_NONE = 0x02,
213
214    /// Signs all inputs and one corresponding output per input.
215    /// (e.g. signing vin 0 will result in signing vout 0)
216    SIGHASH_SINGLE = 0x03,
217
218    SIGHASH_ALL_SIGHASH_FORKID = 0x41,
219    SIGHASH_NONE_SIGHASH_FORKID = 0x42,
220    SIGHASH_SINGLE_SIGHASH_FORKID = 0x43,
221
222    /// Signs only one input and all outputs.
223    /// Allows anyone to add or remove other inputs, forbids changing any outputs.
224    /// (e.g. "crowdfunding" transaction, where the output is the "goal" address)
225    SIGHASH_ALL_SIGHASH_ANYONECANPAY = 0x81,
226
227    /// Signs only one input and none of the outputs.
228    /// Allows anyone to add or remove other inputs or any outputs.
229    /// (e.g. "dust collector" transaction, where "dust" can be aggregated and spent together)
230    SIGHASH_NONE_SIGHASH_ANYONECANPAY = 0x82,
231
232    /// Signs only one input and one corresponding output per input.
233    /// Allows anyone to add or remove other inputs.
234    SIGHASH_SINGLE_SIGHASH_ANYONECANPAY = 0x83,
235
236    SIGHASH_ALL_SIGHASH_FORKID_SIGHASH_ANYONECANPAY = 0xc1,
237    SIGHASH_NONE_SIGHASH_FORKID_SIGHASH_ANYONECANPAY = 0xc2,
238    SIGHASH_SINGLE_SIGHASH_FORKID_SIGHASH_ANYONECANPAY = 0xc3,
239}
240
241impl fmt::Display for SignatureHash {
242    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243        match self {
244            SignatureHash::SIGHASH_ALL => write!(f, "SIGHASH_ALL"),
245            SignatureHash::SIGHASH_NONE => write!(f, "SIGHASH_NONE"),
246            SignatureHash::SIGHASH_SINGLE => write!(f, "SIGHASH_SINGLE"),
247            SignatureHash::SIGHASH_ALL_SIGHASH_FORKID => {
248                write!(f, "SIGHASH_ALL | SIGHASH_FORKID")
249            }
250            SignatureHash::SIGHASH_NONE_SIGHASH_FORKID => {
251                write!(f, "SIGHASH_NONE | SIGHASH_FORKID")
252            }
253            SignatureHash::SIGHASH_SINGLE_SIGHASH_FORKID => {
254                write!(f, "SIGHASH_SINGLE | SIGHASH_FORKID")
255            }
256            SignatureHash::SIGHASH_ALL_SIGHASH_ANYONECANPAY => {
257                write!(f, "SIGHASH_ALL | SIGHASH_ANYONECANPAY")
258            }
259            SignatureHash::SIGHASH_NONE_SIGHASH_ANYONECANPAY => {
260                write!(f, "SIGHASH_NONE | SIGHASH_ANYONECANPAY")
261            }
262            SignatureHash::SIGHASH_SINGLE_SIGHASH_ANYONECANPAY => {
263                write!(f, "SIGHASH_SINGLE | SIGHASH_ANYONECANPAY")
264            }
265            SignatureHash::SIGHASH_ALL_SIGHASH_FORKID_SIGHASH_ANYONECANPAY => {
266                write!(f, "SIGHASH_ALL | SIGHASH_FORKID | SIGHASH_ANYONECANPAY")
267            }
268            SignatureHash::SIGHASH_NONE_SIGHASH_FORKID_SIGHASH_ANYONECANPAY => {
269                write!(f, "SIGHASH_NONE | SIGHASH_FORKID | SIGHASH_ANYONECANPAY")
270            }
271            SignatureHash::SIGHASH_SINGLE_SIGHASH_FORKID_SIGHASH_ANYONECANPAY => {
272                write!(f, "SIGHASH_SINGLE | SIGHASH_FORKID | SIGHASH_ANYONECANPAY")
273            }
274        }
275    }
276}
277
278impl SignatureHash {
279    pub fn from_byte(byte: &u8) -> Self {
280        match byte {
281            0x02 => SignatureHash::SIGHASH_NONE,
282            0x03 => SignatureHash::SIGHASH_SINGLE,
283            0x41 => SignatureHash::SIGHASH_ALL_SIGHASH_FORKID,
284            0x42 => SignatureHash::SIGHASH_NONE_SIGHASH_FORKID,
285            0x43 => SignatureHash::SIGHASH_SINGLE_SIGHASH_FORKID,
286            0x81 => SignatureHash::SIGHASH_ALL_SIGHASH_ANYONECANPAY,
287            0x82 => SignatureHash::SIGHASH_NONE_SIGHASH_ANYONECANPAY,
288            0x83 => SignatureHash::SIGHASH_SINGLE_SIGHASH_ANYONECANPAY,
289            0xc1 => SignatureHash::SIGHASH_ALL_SIGHASH_FORKID_SIGHASH_ANYONECANPAY,
290            0xc2 => SignatureHash::SIGHASH_NONE_SIGHASH_FORKID_SIGHASH_ANYONECANPAY,
291            0xc3 => SignatureHash::SIGHASH_SINGLE_SIGHASH_FORKID_SIGHASH_ANYONECANPAY,
292            _ => SignatureHash::SIGHASH_ALL,
293        }
294    }
295}
296
297/// Represents the commonly used script opcodes
298#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
299#[allow(non_camel_case_types)]
300pub enum Opcode {
301    OP_DUP = 0x76,
302    OP_HASH160 = 0xa9,
303    OP_CHECKSIG = 0xac,
304    OP_EQUAL = 0x87,
305    OP_EQUALVERIFY = 0x88,
306    OP_RETURN = 0x6a,
307    OP_PUSHBYTES_20 = 0x14,
308}
309
310impl fmt::Display for Opcode {
311    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
312        match self {
313            Opcode::OP_DUP => write!(f, "OP_DUP"),
314            Opcode::OP_HASH160 => write!(f, "OP_HASH160"),
315            Opcode::OP_CHECKSIG => write!(f, "OP_CHECKSIG"),
316            Opcode::OP_EQUAL => write!(f, "OP_EQUAL"),
317            Opcode::OP_EQUALVERIFY => write!(f, "OP_EQUALVERIFY"),
318            Opcode::OP_RETURN => write!(f, "OP_RETURN"),
319            Opcode::OP_PUSHBYTES_20 => write!(f, "OP_PUSHBYTES_20"),
320        }
321    }
322}
323
324/// Represents a Bitcoin transaction outpoint
325#[derive(Debug, Clone, PartialEq, Eq)]
326pub struct Outpoint {
327    /// Hash of the previous transaction (32 bytes) (uses reversed hash order from Bitcoin RPC)
328    pub reverse_transaction_id: Vec<u8>,
329    /// The index of certain utxo in the previous transaction (4 bytes)
330    pub index: u32,
331}
332
333impl Outpoint {
334    /// Returns a new Bitcoin transaction outpoint
335    pub fn new(reverse_transaction_id: Vec<u8>, index: u32) -> Self {
336        Self {
337            reverse_transaction_id,
338            index,
339        }
340    }
341}
342
343/// Represents a Bitcoin transaction input
344#[derive(Debug, Clone, PartialEq, Eq)]
345pub struct BitcoinTransactionInput<N: BitcoinNetwork> {
346    /// The outpoint (36 bytes)
347    pub outpoint: Outpoint,
348    /// The balance of the utxo pointed by this input (used for SegWit transaction signatures)
349    pub balance: Option<BitcoinAmount>,
350    /// The address of the utxo pointed by this input
351    pub address: Option<BitcoinAddress<N>>,
352    /// The address format of the utxo pointed by this input
353    pub format: Option<BitcoinFormat>,
354    /// The 'scriptPubkey' of the utxo pointed by this input
355    pub script_pub_key: Option<Vec<u8>>,
356    /// An optional redeem script in case of an SegWit utxo
357    pub redeem_script: Option<Vec<u8>>,
358    /// The transaction input script (variable size)
359    pub script_sig: Vec<u8>,
360    /// The sequence number (4 bytes) (0xFFFFFFFF unless lock > 0)
361    /// Also used in replace-by-fee (BIP 125)
362    pub sequence: Vec<u8>,
363    /// The signature hash (4 bytes) (used in signing raw transaction only)
364    pub sighash_code: SignatureHash,
365    /// The witnesses in a SegWit transaction
366    pub witnesses: Vec<Vec<u8>>,
367    /// If true, the input has been signed
368    pub is_signed: bool,
369    /// Provide more flexibility for multiple signatures (for P2WSH)
370    pub additional_witness: Option<(Vec<u8>, bool)>,
371    /// Option for additional witness stack script args
372    pub witness_script_data: Option<Vec<u8>>,
373}
374
375impl<N: BitcoinNetwork> BitcoinTransactionInput<N> {
376    const DEFAULT_SEQUENCE: [u8; 4] = [0xf2, 0xff, 0xff, 0xff];
377
378    /// Returns a new Bitcoin transaction input.
379    pub fn new(
380        transaction_id: Vec<u8>,
381        index: u32,
382        public_key: Option<BitcoinPublicKey<N>>,
383        format: Option<BitcoinFormat>,
384        address: Option<BitcoinAddress<N>>,
385        balance: Option<BitcoinAmount>,
386        sighash: SignatureHash,
387    ) -> Result<Self, TransactionError> {
388        if transaction_id.len() != 32 {
389            return Err(TransactionError::InvalidTransactionId(transaction_id.len()));
390        }
391
392        // Byte-wise reverse of computed SHA-256 hash values
393        // https://bitcoin.org/en/developer-reference#hash-byte-order
394        let mut reverse_transaction_id = transaction_id;
395        reverse_transaction_id.reverse();
396
397        let format = match format {
398            Some(f) => Some(f),
399            None => Some(BitcoinFormat::P2PKH),
400        };
401
402        let (address, script_pub_key, redeem_script) = match public_key {
403            Some(pk) => {
404                let addr = pk.to_address(&format.clone().unwrap())?;
405                if let Some(v) = address {
406                    if v != addr {
407                        return Err(TransactionError::Message(format!(
408                            "Provided address {} does not match the provided public key {}",
409                            addr, pk,
410                        )));
411                    }
412                }
413                let script_pub_key = create_script_pub_key(&addr)?;
414                let redeem_script = match format {
415                    Some(BitcoinFormat::P2SH_P2WPKH) => {
416                        Some(BitcoinAddress::<N>::create_redeem_script(&pk).to_vec())
417                    }
418                    _ => None,
419                };
420                (Some(addr), Some(script_pub_key), redeem_script)
421            }
422            None => match address {
423                Some(addr) => {
424                    let script_pub_key = create_script_pub_key(&addr)?;
425                    (Some(addr), Some(script_pub_key), None)
426                }
427                None => (None, None, None),
428            },
429        };
430
431        Ok(Self {
432            outpoint: Outpoint::new(reverse_transaction_id, index),
433            balance,
434            address,
435            format,
436            script_pub_key,
437            redeem_script,
438            script_sig: vec![],
439            sequence: BitcoinTransactionInput::<N>::DEFAULT_SEQUENCE.to_vec(),
440            sighash_code: sighash,
441            witnesses: vec![],
442            is_signed: false,
443            additional_witness: None,
444            witness_script_data: None,
445        })
446    }
447
448    pub fn set_public_key(
449        &mut self,
450        public_key: BitcoinPublicKey<N>,
451        format: BitcoinFormat,
452    ) -> Result<(), TransactionError> {
453        let address = public_key.to_address(&format)?;
454        self.format = Some(format.clone());
455        self.script_pub_key = Some(create_script_pub_key(&address)?);
456        self.address = Some(address);
457        self.redeem_script = match format {
458            BitcoinFormat::P2SH_P2WPKH => {
459                Some(BitcoinAddress::<N>::create_redeem_script(&public_key).to_vec())
460            }
461            _ => None,
462        };
463        Ok(())
464    }
465
466    pub fn set_redeem_script(&mut self, redeem_script: Vec<u8>) -> Result<(), TransactionError> {
467        self.redeem_script = Some(redeem_script);
468        Ok(())
469    }
470
471    pub fn set_format(&mut self, format: BitcoinFormat) -> Result<(), TransactionError> {
472        self.format = Some(format);
473        Ok(())
474    }
475
476    pub fn set_balance(&mut self, balance: i64) -> Result<(), TransactionError> {
477        self.balance = Some(BitcoinAmount(balance));
478        Ok(())
479    }
480
481    pub fn set_sequence(&mut self, sequence: u32) -> Result<(), TransactionError> {
482        self.sequence = u32::to_le_bytes(sequence).to_vec();
483        Ok(())
484    }
485
486    pub fn set_sighash(&mut self, sighash: SignatureHash) -> Result<(), TransactionError> {
487        self.sighash_code = sighash;
488        Ok(())
489    }
490
491    pub fn get_address(&self) -> Option<BitcoinAddress<N>> {
492        self.address.clone()
493    }
494
495    pub fn get_format(&self) -> Option<BitcoinFormat> {
496        self.format.clone()
497    }
498
499    pub fn get_balance(&self) -> Option<BitcoinAmount> {
500        self.balance
501    }
502
503    pub fn get_sequence(&self) -> u32 {
504        let sequence: [u8; 4] = self.sequence.clone().try_into().unwrap();
505        u32::from_le_bytes(sequence)
506    }
507
508    pub fn get_sighash(&self) -> SignatureHash {
509        self.sighash_code
510    }
511
512    /// Read and output a Bitcoin transaction input
513    pub fn read<R: Read>(mut reader: &mut R) -> Result<Self, TransactionError> {
514        let mut transaction_hash = [0u8; 32];
515        let mut vin = [0u8; 4];
516        let mut sequence = [0u8; 4];
517
518        let _ = reader.read(&mut transaction_hash)?;
519        let _ = reader.read(&mut vin)?;
520
521        let outpoint = Outpoint::new(transaction_hash.to_vec(), u32::from_le_bytes(vin));
522
523        let script_sig: Vec<u8> = BitcoinVector::read(&mut reader, |s| {
524            let mut byte = [0u8; 1];
525            let _ = s.read(&mut byte)?;
526            Ok(byte[0])
527        })?;
528
529        let _ = reader.read(&mut sequence)?;
530
531        let script_sig_len = read_variable_length_integer(&script_sig[..])?;
532
533        let sighash_code = SignatureHash::from_byte(&match script_sig_len {
534            0 => 0x01,
535            length => script_sig[length],
536        });
537
538        Ok(Self {
539            outpoint,
540            balance: None,
541            address: None,
542            format: None,
543            script_pub_key: None,
544            redeem_script: None,
545            script_sig: script_sig.to_vec(),
546            sequence: sequence.to_vec(),
547            sighash_code,
548            witnesses: vec![],
549            is_signed: !script_sig.is_empty(),
550            additional_witness: None,
551            witness_script_data: None,
552        })
553    }
554
555    /// Returns the serialized transaction input.
556    pub fn serialize(&self, raw: bool) -> Result<Vec<u8>, TransactionError> {
557        let mut input = vec![];
558        input.extend(&self.outpoint.reverse_transaction_id);
559        input.extend(&self.outpoint.index.to_le_bytes());
560        match raw {
561            true => input.extend(vec![0x00]),
562            false => match self.script_sig.len() {
563                0 => match &self.address {
564                    Some(address) => match address.format() {
565                        BitcoinFormat::P2PKH => {
566                            let script_pub_key = match &self.script_pub_key {
567                                Some(script) => script,
568                                None => {
569                                    return Err(TransactionError::MissingOutpointScriptPublicKey)
570                                }
571                            };
572                            input.extend(variable_length_integer(script_pub_key.len() as u64)?);
573                            input.extend(script_pub_key);
574                        }
575                        _ => input.extend(vec![0x00]),
576                    },
577                    None => input.extend(vec![0x00]),
578                },
579                _ => {
580                    input.extend(variable_length_integer(self.script_sig.len() as u64)?);
581                    input.extend(&self.script_sig);
582                }
583            },
584        };
585
586        input.extend(&self.sequence);
587
588        Ok(input)
589    }
590
591    /// Insert 'signature' and 'public_key' into this input to make it signed
592    pub fn sign(
593        &mut self,
594        signature: Vec<u8>,
595        public_key: Vec<u8>,
596    ) -> Result<(), TransactionError> {
597        let mut signature = Signature::parse_standard_slice(&signature)
598            .map_err(|error| TransactionError::Crate("libsecp256k1", format!("{:?}", error)))?
599            .serialize_der()
600            .as_ref()
601            .to_vec();
602        signature.push(self.sighash_code as u8);
603
604        let signature = [variable_length_integer(signature.len() as u64)?, signature].concat();
605        let public_key = [
606            variable_length_integer(public_key.len() as u64)?,
607            public_key,
608        ]
609        .concat();
610
611        match self.get_format().unwrap() {
612            BitcoinFormat::P2PKH | BitcoinFormat::CashAddr => {
613                self.script_sig = [signature, public_key].concat()
614            }
615            BitcoinFormat::P2SH_P2WPKH => {
616                let input_script = match &self.redeem_script {
617                    Some(script) => script.clone(),
618                    None => {
619                        return Err(TransactionError::Message(
620                            "Missing redeem script".to_string(),
621                        ))
622                    }
623                };
624                self.script_sig = [
625                    variable_length_integer(input_script.len() as u64)?,
626                    input_script,
627                ]
628                .concat();
629                self.witnesses.append(&mut vec![signature, public_key]);
630            }
631            BitcoinFormat::Bech32 => self.witnesses.append(&mut vec![signature, public_key]),
632            BitcoinFormat::P2WSH => {
633                return Err(TransactionError::Message(
634                    "P2WSH signing not supported".to_string(),
635                ))
636            }
637        }
638
639        self.is_signed = true;
640
641        Ok(())
642    }
643}
644
645/// Represents a Bitcoin transaction output
646#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
647pub struct BitcoinTransactionOutput {
648    /// The amount (in Satoshi)
649    pub amount: BitcoinAmount,
650    /// The public key script
651    pub script_pub_key: Vec<u8>,
652}
653
654impl BitcoinTransactionOutput {
655    /// Returns a Bitcoin transaction output.
656    pub fn new<N: BitcoinNetwork>(
657        address: BitcoinAddress<N>,
658        amount: BitcoinAmount,
659    ) -> Result<Self, TransactionError> {
660        Ok(Self {
661            amount,
662            script_pub_key: create_script_pub_key::<N>(&address)?,
663        })
664    }
665
666    /// Returns the data output for a tx that spends 'amount' basic
667    /// units of omni-layer asset as indicated by 'property_id'.
668    pub fn omni_data_output(
669        property_id: u32,
670        amount: BitcoinAmount,
671    ) -> Result<Self, TransactionError> {
672        let data_output = BitcoinTransactionOutput {
673            amount: BitcoinAmount(0),
674            script_pub_key: create_script_op_return(property_id, amount.0)?,
675        };
676
677        Ok(data_output)
678    }
679
680    /// Read and output a Bitcoin transaction output
681    pub fn read<R: Read>(mut reader: &mut R) -> Result<Self, TransactionError> {
682        let mut amount = [0u8; 8];
683        let _ = reader.read(&mut amount)?;
684
685        let script_pub_key: Vec<u8> = BitcoinVector::read(&mut reader, |s| {
686            let mut byte = [0u8; 1];
687            let _ = s.read(&mut byte)?;
688            Ok(byte[0])
689        })?;
690
691        Ok(Self {
692            amount: BitcoinAmount::from_satoshi(u64::from_le_bytes(amount) as i64)?,
693            script_pub_key,
694        })
695    }
696
697    /// Returns the serialized transaction output.
698    pub fn serialize(&self) -> Result<Vec<u8>, TransactionError> {
699        let mut output = vec![];
700        output.extend(&self.amount.0.to_le_bytes());
701        output.extend(variable_length_integer(self.script_pub_key.len() as u64)?);
702        output.extend(&self.script_pub_key);
703        Ok(output)
704    }
705}
706
707/// Represents an Bitcoin transaction id and witness transaction id
708/// `<https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#transaction-id>`
709#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
710pub struct BitcoinTransactionId {
711    pub txid: Vec<u8>,
712    pub wtxid: Vec<u8>,
713}
714
715impl TransactionId for BitcoinTransactionId {}
716
717impl fmt::Display for BitcoinTransactionId {
718    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
719        write!(f, "{}", &hex::encode(&self.txid))
720    }
721}
722
723/// Represents the Bitcoin transaction parameters
724#[derive(Debug, Clone, PartialEq, Eq)]
725pub struct BitcoinTransactionParameters<N: BitcoinNetwork> {
726    /// The version number (4 bytes)
727    pub version: u32,
728    /// The transaction inputs
729    pub inputs: Vec<BitcoinTransactionInput<N>>,
730    /// The transaction outputs
731    pub outputs: Vec<BitcoinTransactionOutput>,
732    /// The lock time (4 bytes)
733    pub lock_time: u32,
734    /// An optional 2 bytes to indicate SegWit transactions
735    pub segwit_flag: bool,
736}
737
738impl<N: BitcoinNetwork> BitcoinTransactionParameters<N> {
739    /// Returns a BitcoinTransactionParameters given the inputs and outputs
740    pub fn new(
741        inputs: Vec<BitcoinTransactionInput<N>>,
742        outputs: Vec<BitcoinTransactionOutput>,
743    ) -> Result<Self, TransactionError> {
744        Ok(Self {
745            version: 2,
746            inputs,
747            outputs,
748            lock_time: 0,
749            segwit_flag: false,
750        })
751    }
752
753    /// Read and output the Bitcoin transaction parameters
754    pub fn read<R: Read>(mut reader: R) -> Result<Self, TransactionError> {
755        let mut version = [0u8; 4];
756        let _ = reader.read(&mut version)?;
757
758        let mut inputs = BitcoinVector::read(&mut reader, BitcoinTransactionInput::<N>::read)?;
759
760        let segwit_flag = match inputs.is_empty() {
761            true => {
762                let mut flag = [0u8; 1];
763                let _ = reader.read(&mut flag)?;
764                match flag[0] {
765                    1 => {
766                        inputs =
767                            BitcoinVector::read(&mut reader, BitcoinTransactionInput::<N>::read)?;
768                        true
769                    }
770                    _ => return Err(TransactionError::InvalidSegwitFlag(flag[0] as usize)),
771                }
772            }
773            false => false,
774        };
775
776        let outputs = BitcoinVector::read(&mut reader, BitcoinTransactionOutput::read)?;
777
778        // if segwit_flag {
779        //     for input in &mut inputs {
780        //         let witnesses: Vec<Vec<u8>> = BitcoinVector::read(&mut reader, |s| {
781        //             let (size, witness) = BitcoinVector::read_witness(s, |sr| {
782        //                 let mut byte = [0u8; 1];
783        //                 let _ = sr.read(&mut byte)?;
784        //                 Ok(byte[0])
785        //             })?;
786        //             Ok([variable_length_integer(size as u64)?, witness?].concat())
787        //         })?;
788
789        //         if !witnesses.is_empty() {
790        //             input.sighash_code =
791        //                 SignatureHash::from_byte(&witnesses[0][&witnesses[0].len() - 1]);
792        //             input.is_signed = true;
793        //         }
794
795        //         input.witnesses = witnesses;
796        //     }
797        // }
798
799        let params = BitcoinTransactionParameters::<N> {
800            version: u32::from_le_bytes(version),
801            inputs,
802            outputs,
803            lock_time: 0,
804            segwit_flag,
805        };
806
807        Ok(params)
808    }
809}
810
811/// Represents a Bitcoin transaction
812#[derive(Debug, Clone, PartialEq, Eq)]
813pub struct BitcoinTransaction<N: BitcoinNetwork> {
814    /// The transaction parameters (version, inputs, outputs, lock_time, segwit_flag)
815    pub parameters: BitcoinTransactionParameters<N>,
816}
817
818impl<N: BitcoinNetwork> fmt::Display for BitcoinTransaction<N> {
819    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
820        write!(f, "{}", hex::encode(self.to_bytes().unwrap()))
821    }
822}
823
824impl<N: BitcoinNetwork> Transaction for BitcoinTransaction<N> {
825    type Address = BitcoinAddress<N>;
826    type Format = BitcoinFormat;
827    type PublicKey = BitcoinPublicKey<N>;
828    type TransactionId = BitcoinTransactionId;
829    type TransactionParameters = BitcoinTransactionParameters<N>;
830
831    /// Returns an unsigned transaction given the transaction parameters.
832    fn new(parameters: &Self::TransactionParameters) -> Result<Self, TransactionError> {
833        Ok(Self {
834            parameters: parameters.clone(),
835        })
836    }
837
838    /// Returns a transaction given the transaction bytes.
839    /// Note:: Raw transaction hex does not include enough
840    fn from_bytes(transaction: &[u8]) -> Result<Self, TransactionError> {
841        Ok(Self {
842            parameters: Self::TransactionParameters::read(transaction)?,
843        })
844    }
845
846    /// Returns the transaction in bytes.
847    fn to_bytes(&self) -> Result<Vec<u8>, TransactionError> {
848        let mut transaction = self.parameters.version.to_le_bytes().to_vec();
849
850        if self.parameters.segwit_flag {
851            transaction.extend(vec![0x00, 0x01]);
852        }
853
854        transaction.extend(variable_length_integer(self.parameters.inputs.len() as u64)?);
855        let mut has_witness = false;
856        for input in &self.parameters.inputs {
857            if !has_witness {
858                has_witness = !input.witnesses.is_empty();
859            }
860            transaction.extend(input.serialize(!input.is_signed)?);
861        }
862
863        transaction.extend(variable_length_integer(
864            self.parameters.outputs.len() as u64
865        )?);
866        for output in &self.parameters.outputs {
867            transaction.extend(output.serialize()?);
868        }
869
870        if has_witness {
871            for input in &self.parameters.inputs {
872                match input.witnesses.len() {
873                    0 => transaction.extend(vec![0x00]),
874                    _ => {
875                        transaction.extend(variable_length_integer(input.witnesses.len() as u64)?);
876                        for witness in &input.witnesses {
877                            transaction.extend(witness);
878                        }
879                    }
880                };
881            }
882        }
883
884        transaction.extend(&self.parameters.lock_time.to_le_bytes());
885
886        Ok(transaction)
887    }
888
889    /// Returns the transaction id.
890    fn to_transaction_id(&self) -> Result<Self::TransactionId, TransactionError> {
891        let mut txid = double_sha2(&self.to_transaction_bytes_without_witness()?).to_vec();
892        let mut wtxid = double_sha2(&self.to_bytes()?).to_vec();
893
894        txid.reverse();
895        wtxid.reverse();
896
897        Ok(Self::TransactionId { txid, wtxid })
898    }
899
900    fn sign(&mut self, _signature: Vec<u8>, _recid: u8) -> Result<Vec<u8>, TransactionError> {
901        panic!(
902            "trait method sign() deprecated for bitcoin, use custom methods for signature\
903             insertion in its own impl block instead."
904        );
905    }
906}
907
908impl<N: BitcoinNetwork> BitcoinTransaction<N> {
909    /// Return the P2PKH hash preimage of the raw transaction.
910    pub fn p2pkh_hash_preimage(
911        &self,
912        vin: usize,
913        sighash: SignatureHash,
914    ) -> Result<Vec<u8>, TransactionError> {
915        let mut preimage = self.parameters.version.to_le_bytes().to_vec();
916        preimage.extend(variable_length_integer(self.parameters.inputs.len() as u64)?);
917        for (index, input) in self.parameters.inputs.iter().enumerate() {
918            preimage.extend(input.serialize(index != vin)?);
919        }
920        preimage.extend(variable_length_integer(
921            self.parameters.outputs.len() as u64
922        )?);
923        for output in &self.parameters.outputs {
924            preimage.extend(output.serialize()?);
925        }
926        preimage.extend(&self.parameters.lock_time.to_le_bytes());
927        preimage.extend(&(sighash as u32).to_le_bytes());
928        Ok(preimage)
929    }
930
931    /// Return the SegWit hash preimage of the raw transaction
932    /// `<https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification>`
933    pub fn segwit_hash_preimage(
934        &self,
935        vin: usize,
936        sighash: SignatureHash,
937    ) -> Result<Vec<u8>, TransactionError> {
938        let mut prev_outputs = vec![];
939        let mut prev_sequences = vec![];
940        let mut outputs = vec![];
941
942        for input in &self.parameters.inputs {
943            prev_outputs.extend(&input.outpoint.reverse_transaction_id);
944            prev_outputs.extend(&input.outpoint.index.to_le_bytes());
945            prev_sequences.extend(&input.sequence);
946        }
947
948        for output in &self.parameters.outputs {
949            outputs.extend(&output.serialize()?);
950        }
951
952        let input = &self.parameters.inputs[vin];
953        let format = match &input.address {
954            Some(address) => address.format(),
955            None => return Err(TransactionError::MissingOutpointAddress),
956        };
957
958        let script = match format {
959            BitcoinFormat::Bech32 => match &input.script_pub_key {
960                Some(script) => script[1..].to_vec(),
961                None => return Err(TransactionError::MissingOutpointScriptPublicKey),
962            },
963            BitcoinFormat::CashAddr => match &input.script_pub_key {
964                Some(script) => script.to_vec(),
965                None => return Err(TransactionError::MissingOutpointScriptPublicKey),
966            },
967            BitcoinFormat::P2WSH => match &input.redeem_script {
968                Some(redeem_script) => redeem_script.to_vec(),
969                None => return Err(TransactionError::InvalidInputs("P2WSH".into())),
970            },
971            BitcoinFormat::P2SH_P2WPKH => match &input.redeem_script {
972                Some(redeem_script) => redeem_script[1..].to_vec(),
973                None => return Err(TransactionError::InvalidInputs("P2SH_P2WPKH".into())),
974            },
975            _ => return Err(TransactionError::UnsupportedPreimage("P2PKH".into())),
976        };
977
978        let mut script_code = vec![];
979        if format == BitcoinFormat::P2WSH || format == BitcoinFormat::CashAddr {
980            script_code.extend(script);
981        } else {
982            script_code.push(Opcode::OP_DUP as u8);
983            script_code.push(Opcode::OP_HASH160 as u8);
984            script_code.extend(script);
985            script_code.push(Opcode::OP_EQUALVERIFY as u8);
986            script_code.push(Opcode::OP_CHECKSIG as u8);
987        }
988        let script_code = [
989            variable_length_integer(script_code.len() as u64)?,
990            script_code,
991        ]
992        .concat();
993        let hash_prev_outputs = double_sha2(&prev_outputs);
994        let hash_sequence = double_sha2(&prev_sequences);
995        let hash_outputs = double_sha2(&outputs);
996        let balance = match &input.balance {
997            Some(balance) => balance.0.to_le_bytes(),
998            None => return Err(TransactionError::MissingOutpointAmount),
999        };
1000
1001        let mut preimage = vec![];
1002        preimage.extend(&self.parameters.version.to_le_bytes());
1003        preimage.extend(hash_prev_outputs);
1004        preimage.extend(hash_sequence);
1005        preimage.extend(&input.outpoint.reverse_transaction_id);
1006        preimage.extend(&input.outpoint.index.to_le_bytes());
1007        preimage.extend(&script_code);
1008        preimage.extend(&balance);
1009        preimage.extend(&input.sequence);
1010        preimage.extend(hash_outputs);
1011        preimage.extend(&self.parameters.lock_time.to_le_bytes());
1012        preimage.extend(&(sighash as u32).to_le_bytes());
1013
1014        Ok(preimage)
1015    }
1016
1017    /// Returns the transaction with the traditional serialization (no witness).
1018    pub fn to_transaction_bytes_without_witness(&self) -> Result<Vec<u8>, TransactionError> {
1019        let mut transaction = self.parameters.version.to_le_bytes().to_vec();
1020
1021        transaction.extend(variable_length_integer(self.parameters.inputs.len() as u64)?);
1022        for input in &self.parameters.inputs {
1023            transaction.extend(input.serialize(false)?);
1024        }
1025
1026        transaction.extend(variable_length_integer(
1027            self.parameters.outputs.len() as u64
1028        )?);
1029        for output in &self.parameters.outputs {
1030            transaction.extend(output.serialize()?);
1031        }
1032
1033        transaction.extend(&self.parameters.lock_time.to_le_bytes());
1034
1035        Ok(transaction)
1036    }
1037
1038    pub fn input(
1039        &mut self,
1040        index: u32,
1041    ) -> Result<&mut BitcoinTransactionInput<N>, TransactionError> {
1042        if index as usize >= self.parameters.inputs.len() {
1043            return Err(TransactionError::Message(format!(
1044                "you are referring to input {}, which is out of bound",
1045                index
1046            )));
1047        }
1048        Ok(&mut self.parameters.inputs[index as usize])
1049    }
1050
1051    pub fn digest(&mut self, index: u32) -> Result<Vec<u8>, TransactionError> {
1052        let input = self.input(index)?;
1053        let sighash = input.sighash_code;
1054        match input.get_address() {
1055            Some(addr) => {
1056                let preimage = match addr.format() {
1057                    BitcoinFormat::P2PKH => self.p2pkh_hash_preimage(index as usize, sighash)?,
1058                    _ => self.segwit_hash_preimage(index as usize, sighash)?,
1059                };
1060                Ok(double_sha2(&preimage).to_vec())
1061            }
1062            None => Err(TransactionError::MissingOutpointAddress),
1063        }
1064    }
1065
1066    pub fn set_segwit(&mut self) -> Result<(), TransactionError> {
1067        for input in self.parameters.inputs.clone() {
1068            if self.parameters.segwit_flag {
1069                break;
1070            }
1071            if input.is_signed {
1072                match input.get_format() {
1073                    Some(BitcoinFormat::P2SH_P2WPKH) | Some(BitcoinFormat::Bech32) => {
1074                        self.parameters.segwit_flag = true
1075                    }
1076                    _ => {}
1077                }
1078            }
1079        }
1080
1081        Ok(())
1082    }
1083}
1084
1085impl<N: BitcoinNetwork> FromStr for BitcoinTransaction<N> {
1086    type Err = TransactionError;
1087
1088    fn from_str(transaction: &str) -> Result<Self, Self::Err> {
1089        Self::from_bytes(&hex::decode(transaction)?)
1090    }
1091}