earthbucks_lib 0.8.5

EarthBucks library for data structures and algorithms
Documentation
use crate::buf_reader::BufReader;
use crate::buf_writer::BufWriter;
use crate::error::EbxError;
use crate::header::Header;
use crate::tx::Tx;
use crate::var_int::VarInt;

pub struct Block {
    pub header: Header,
    pub txs: Vec<Tx>,
}

impl Block {
    pub fn new(header: Header, txs: Vec<Tx>) -> Self {
        Self { header, txs }
    }

    pub fn from_buf_reader(br: &mut BufReader) -> Result<Self, EbxError> {
        let header = Header::from_buf_reader(br)?;
        let tx_count_varint = VarInt::from_buf_reader(br)?;
        if !tx_count_varint.is_minimal() {
            return Err(EbxError::NonMinimalEncodingError { source: None });
        }
        let tx_count = tx_count_varint.to_u64()? as usize;
        let mut txs = vec![];
        for _ in 0..tx_count {
            let tx = Tx::from_buf_reader(br)?;
            txs.push(tx);
        }
        Ok(Self { header, txs })
    }

    pub fn to_buffer_writer(&self) -> BufWriter {
        let mut bw = BufWriter::new();
        bw.write(self.header.to_buf().to_vec());
        bw.write(VarInt::from_u64(self.txs.len() as u64).to_buf());
        for tx in &self.txs {
            bw.write(tx.to_buffer_writer().to_buf());
        }
        bw
    }

    pub fn to_buf(&self) -> Vec<u8> {
        self.to_buffer_writer().to_buf()
    }

    pub fn from_buf(buf: Vec<u8>) -> Result<Self, EbxError> {
        let mut br = BufReader::new(buf);
        Self::from_buf_reader(&mut br)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::numbers::u256;

    #[test]
    fn test_to_buffer_writer() {
        let header = Header {
            version: 0,
            prev_block_id: [0; 32],
            merkle_root: [0; 32],
            timestamp: 0,
            block_num: 0,
            target: u256::from(0u8),
            nonce: u256::from(0u8),
            work_ser_algo: 0,
            work_ser_hash: [0; 32],
            work_par_algo: 0,
            work_par_hash: [0; 32],
        };
        let tx = Tx::new(0, vec![], vec![], 1);
        let block = Block::new(header, vec![tx]);
        let bw = block.to_buffer_writer();
        assert!(!bw.to_buf().is_empty());
    }

    #[test]
    fn test_to_buf_and_from_buf() {
        let header = Header {
            version: 0,
            prev_block_id: [0; 32],
            merkle_root: [0; 32],
            timestamp: 0,
            block_num: 0,
            target: u256::from(0u8),
            nonce: u256::from(0u8),
            work_ser_algo: 0,
            work_ser_hash: [0; 32],
            work_par_algo: 0,
            work_par_hash: [0; 32],
        };
        let tx = Tx::new(0, vec![], vec![], 1);
        let block1 = Block::new(header, vec![tx]);
        let buf = block1.to_buf();
        let block2 = Block::from_buf(buf).unwrap();
        assert_eq!(block1.header.version, block2.header.version);
        assert_eq!(block1.txs[0].version, block2.txs[0].version);
    }

    #[test]
    fn test_from_buf_reader() {
        let header = Header {
            version: 0,
            prev_block_id: [0; 32],
            merkle_root: [0; 32],
            timestamp: 0,
            block_num: 0,
            target: u256::from(0u8),
            nonce: u256::from(0u8),
            work_ser_algo: 0,
            work_ser_hash: [0; 32],
            work_par_algo: 0,
            work_par_hash: [0; 32],
        };
        let tx = Tx::new(0, vec![], vec![], 1);
        let block1 = Block::new(header, vec![tx]);
        let buf = block1.to_buf();
        let mut br = BufReader::new(buf);
        let block2 = Block::from_buf_reader(&mut br).unwrap();
        assert_eq!(block1.header.version, block2.header.version);
        assert_eq!(block1.txs[0].version, block2.txs[0].version);
    }

    #[test]
    fn test_is_genesis() {
        let header = Header {
            version: 0,
            prev_block_id: [0; 32],
            merkle_root: [0; 32],
            timestamp: 0,
            block_num: 0,
            target: u256::from(0u8),
            nonce: u256::from(0u8),
            work_ser_algo: 0,
            work_ser_hash: [0; 32],
            work_par_algo: 0,
            work_par_hash: [0; 32],
        };
        let tx = Tx::new(0, vec![], vec![], 0);
        let block = Block::new(header, vec![tx]);
        assert!(block.header.is_genesis());
    }
}