bitcoin_explorer/parser/proto/
full_proto.rs

1//!
2//! Add addresses, block_hash, tx_id to the bitcoin library format
3//!
4use crate::api::Block;
5use crate::parser::script::{evaluate_script, ScriptType};
6use bitcoin::{Address, BlockHash, Transaction, TxMerkleNode, TxOut, Txid};
7use serde::{Deserialize, Serialize};
8
9///
10/// Block in a `full` format.
11///
12/// A `FBlock` compared to a `Block` has the following more
13/// attributes computed:
14/// - `block hash`
15/// - `transaction id`
16/// - `output addresses`
17/// - `output script types`
18///
19#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
20pub struct FBlock {
21    pub header: FBlockHeader,
22    pub txdata: Vec<FTransaction>,
23}
24
25impl From<Block> for FBlock {
26    /// obtain addresses for each output of each transactions
27    fn from(block: bitcoin::Block) -> FBlock {
28        let block_hash = block.header.block_hash();
29        FBlock {
30            header: FBlockHeader::parse(block.header, block_hash),
31            txdata: block.txdata.into_iter().map(|x| x.into()).collect(),
32        }
33    }
34}
35
36#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
37pub struct FBlockHeader {
38    pub version: i32,
39    pub block_hash: BlockHash,
40    pub prev_blockhash: BlockHash,
41    pub merkle_root: TxMerkleNode,
42    pub time: u32,
43    pub bits: u32,
44    pub nonce: u32,
45}
46
47impl FBlockHeader {
48    /// obtain addresses for each output
49    pub fn parse(b: bitcoin::BlockHeader, block_hash: BlockHash) -> FBlockHeader {
50        FBlockHeader {
51            version: b.version,
52            block_hash,
53            prev_blockhash: b.prev_blockhash,
54            merkle_root: b.merkle_root,
55            time: b.time,
56            bits: b.bits,
57            nonce: b.nonce,
58        }
59    }
60}
61
62/// `FTransaction` compared to `Transaction` has the following
63/// precomputed:
64/// - `transaction ID`
65/// - `output script type`
66/// - `output addresses`
67#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
68pub struct FTransaction {
69    pub version: i32,
70    pub lock_time: u32,
71    pub txid: Txid,
72    /// List of inputs
73    pub input: Vec<bitcoin::TxIn>,
74    /// List of outputs
75    pub output: Vec<FTxOut>,
76}
77
78impl From<Transaction> for FTransaction {
79    fn from(tx: Transaction) -> FTransaction {
80        let is_coinbase = tx.is_coin_base();
81        let txid = tx.txid();
82        let input = if is_coinbase { Vec::new() } else { tx.input };
83        FTransaction {
84            version: tx.version,
85            lock_time: tx.lock_time,
86            txid,
87            input,
88            output: tx.output.into_iter().map(FTxOut::from).collect(),
89        }
90    }
91}
92
93#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
94pub struct FTxOut {
95    pub value: u64,
96    pub script_pubkey: bitcoin::Script,
97    pub script_type: ScriptType,
98    pub addresses: Box<[Address]>,
99}
100
101impl From<TxOut> for FTxOut {
102    fn from(out: bitcoin::TxOut) -> FTxOut {
103        let eval = evaluate_script(&out.script_pubkey, bitcoin::Network::Bitcoin);
104        FTxOut {
105            value: out.value,
106            script_pubkey: out.script_pubkey,
107            script_type: eval.pattern,
108            addresses: eval.addresses.into_boxed_slice(),
109        }
110    }
111}