1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use crate::parser::script::evaluate_script;
use bitcoin::{Address, Block, BlockHash, Transaction, TxIn, TxOut, Txid};
use serde::{Deserialize, Serialize};

///
/// Block in a `simple` format.
///
/// A `SBlock` compared to a `Block` has the following more
/// attributes precomputed:
/// - `block hash`
/// - `transaction id`
/// - `output addresses`
/// - `output script types`
///
/// But is has the following attributes removed:
/// - `nounce`
/// - `previous block hash`
/// - `merkle root`
/// - `bits`
/// - `input witness`
/// - `output public script key hash`
///
/// `SBlock` reduces the amount of data memorized or transferred.
#[derive(Serialize, Deserialize)]
pub struct SBlock {
    pub header: SBlockHeader,
    pub txdata: Vec<STransaction>,
}

impl From<Block> for SBlock {
    ///
    /// Add addresses, block_hash, tx_id to the bitcoin library format,
    /// and also simplify the format.
    ///
    fn from(block: Block) -> SBlock {
        let block_hash = block.header.block_hash();
        SBlock {
            header: SBlockHeader::parse(block.header, block_hash),
            txdata: block.txdata.into_iter().map(|x| x.into()).collect(),
        }
    }
}

#[derive(Serialize, Deserialize)]
pub struct SBlockHeader {
    pub block_hash: BlockHash,
    pub time: u32,
}

impl SBlockHeader {
    pub fn parse(blk: bitcoin::BlockHeader, block_hash: BlockHash) -> SBlockHeader {
        SBlockHeader {
            block_hash,
            time: blk.time,
        }
    }
}

/// `STransaction` compared to `Transaction` has the following
/// precomputed:
/// - `transaction ID`
/// - `output script type`
/// - `output addresses`
///
/// It has the following removed:
/// - `input witness`
/// - `output public script key hash`
///
/// It reduces the amount of data memorized or transferred (to python).
#[derive(Serialize, Deserialize)]
pub struct STransaction {
    pub txid: Txid,
    /// List of inputs
    pub input: Vec<STxIn>,
    /// List of outputs
    pub output: Vec<STxOut>,
}

impl From<Transaction> for STransaction {
    fn from(tx: Transaction) -> STransaction {
        STransaction {
            txid: tx.txid(),
            input: tx.input.into_iter().map(|x| x.into()).collect(),
            output: tx.output.into_iter().map(|x| x.into()).collect(),
        }
    }
}

#[derive(Serialize, Deserialize)]
pub struct STxIn {
    pub txid: Txid,
    pub vout: u32,
}

impl From<TxIn> for STxIn {
    fn from(tx_in: TxIn) -> STxIn {
        STxIn {
            txid: tx_in.previous_output.txid,
            vout: tx_in.previous_output.vout,
        }
    }
}

#[derive(Serialize, Deserialize, Clone)]
pub struct STxOut {
    pub value: u64,
    pub addresses: Box<[Address]>,
}

impl From<TxOut> for STxOut {
    fn from(out: TxOut) -> STxOut {
        let eval = evaluate_script(&out.script_pubkey, bitcoin::Network::Bitcoin);
        STxOut {
            value: out.value,
            addresses: eval.addresses.into_boxed_slice(),
        }
    }
}