bitcoin_explorer/parser/proto/
simple_proto.rs

1use crate::parser::script::evaluate_script;
2use bitcoin::{Address, Block, BlockHash, Transaction, TxIn, TxOut, Txid};
3use serde::{Deserialize, Serialize};
4
5///
6/// Block in a `simple` format.
7///
8/// A `SBlock` compared to a `Block` has the following more
9/// attributes precomputed:
10/// - `block hash`
11/// - `transaction id`
12/// - `output addresses`
13/// - `output script types`
14///
15/// But is has the following attributes removed:
16/// - `nounce`
17/// - `previous block hash`
18/// - `merkle root`
19/// - `bits`
20/// - `input witness`
21/// - `output public script key hash`
22///
23/// `SBlock` reduces the amount of data memorized or transferred.
24///
25#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
26pub struct SBlock {
27    pub header: SBlockHeader,
28    pub txdata: Vec<STransaction>,
29}
30
31impl From<Block> for SBlock {
32    ///
33    /// Add addresses, block_hash, tx_id to the bitcoin library format,
34    /// and also simplify the format.
35    ///
36    fn from(block: Block) -> SBlock {
37        let block_hash = block.header.block_hash();
38        SBlock {
39            header: SBlockHeader::parse(block.header, block_hash),
40            txdata: block.txdata.into_iter().map(|x| x.into()).collect(),
41        }
42    }
43}
44
45#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
46pub struct SBlockHeader {
47    pub block_hash: BlockHash,
48    pub time: u32,
49}
50
51impl SBlockHeader {
52    pub fn parse(blk: bitcoin::BlockHeader, block_hash: BlockHash) -> SBlockHeader {
53        SBlockHeader {
54            block_hash,
55            time: blk.time,
56        }
57    }
58}
59
60/// `STransaction` compared to `Transaction` has the following
61/// precomputed:
62/// - `transaction ID`
63/// - `output script type`
64/// - `output addresses`
65///
66/// It has the following removed:
67/// - `input witness`
68/// - `output public script key hash`
69///
70/// It reduces the amount of data memorized or transferred (to python).
71#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
72pub struct STransaction {
73    pub txid: Txid,
74    /// List of inputs
75    pub input: Vec<STxIn>,
76    /// List of outputs
77    pub output: Vec<STxOut>,
78}
79
80impl From<Transaction> for STransaction {
81    fn from(tx: Transaction) -> STransaction {
82        let is_coinbase = tx.is_coin_base();
83        let txid = tx.txid();
84        let input = if is_coinbase {
85            Vec::new()
86        } else {
87            tx.input.into_iter().map(|x| x.into()).collect()
88        };
89        STransaction {
90            txid,
91            input,
92            output: tx.output.into_iter().map(|x| x.into()).collect(),
93        }
94    }
95}
96
97#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
98pub struct STxIn {
99    pub txid: Txid,
100    pub vout: u32,
101}
102
103impl From<TxIn> for STxIn {
104    fn from(tx_in: TxIn) -> STxIn {
105        STxIn {
106            txid: tx_in.previous_output.txid,
107            vout: tx_in.previous_output.vout,
108        }
109    }
110}
111
112#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
113pub struct STxOut {
114    pub value: u64,
115    pub addresses: Box<[Address]>,
116}
117
118impl From<TxOut> for STxOut {
119    fn from(out: TxOut) -> STxOut {
120        let eval = evaluate_script(&out.script_pubkey, bitcoin::Network::Bitcoin);
121        STxOut {
122            value: out.value,
123            addresses: eval.addresses.into_boxed_slice(),
124        }
125    }
126}