use std::fmt;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use crate::blockchain::proto::header::BlockHeader;
use crate::blockchain::proto::tx::{EvaluatedTx, RawTx};
use crate::blockchain::proto::varuint::VarUint;
use crate::blockchain::proto::Hashed;
use crate::common::utils;
pub struct Block {
pub size: u32,
pub header: Hashed<BlockHeader>,
pub tx_count: VarUint,
pub txs: Vec<Hashed<EvaluatedTx>>,
}
impl Block {
#[inline]
pub fn new(size: u32, header: BlockHeader, tx_count: VarUint, txs: Vec<RawTx>) -> Block {
let txs = txs
.into_par_iter()
.map(|raw| Hashed::double_sha256(EvaluatedTx::from(raw)))
.collect();
Block {
size,
header: Hashed::double_sha256(header),
tx_count,
txs,
}
}
#[inline]
pub fn compute_merkle_root(&self) -> [u8; 32] {
utils::merkle_root(&self.txs.iter().map(|tx| tx.hash).collect::<Vec<[u8; 32]>>())
}
pub fn verify_merkle_root(&self) {
let merkle_root = self.compute_merkle_root();
if merkle_root != self.header.value.merkle_root {
panic!(
"Invalid merkle_root!\n -> expected: {}\n -> got: {}\n",
&utils::arr_to_hex_swapped(&self.header.value.merkle_root),
&utils::arr_to_hex_swapped(&merkle_root)
);
}
}
}
impl fmt::Debug for Block {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("Block")
.field("header", &self.header)
.field("tx_count", &self.tx_count)
.finish()
}
}
pub fn get_base_reward(block_height: u64) -> u64 {
(50 * 100000000) >> (block_height / 210000)
}
#[cfg(test)]
mod tests {
use super::get_base_reward;
#[test]
fn test_get_base_reward() {
assert_eq!(get_base_reward(0), 5000000000);
assert_eq!(get_base_reward(209999), 5000000000);
assert_eq!(get_base_reward(210000), 2500000000);
assert_eq!(get_base_reward(419999), 2500000000);
assert_eq!(get_base_reward(420000), 1250000000);
assert_eq!(get_base_reward(629999), 1250000000);
assert_eq!(get_base_reward(630000), 0625000000);
}
}