extern crate serde; extern crate serde_json; use std::fmt::Debug; use serde::{Deserialize, Serialize}; use crate::blockchain::hash_utils::{hash_difficulty, key_hash_difficulty}; use crate::blockchain::transaction::TransactionType; use crate::bytes::Bytes; use crate::Transaction; #[derive(Clone, Serialize, Deserialize, PartialEq, Debug)] pub struct Block { pub index: u64, pub timestamp: i64, pub version: u32, pub difficulty: u32, pub random: u32, pub nonce: u64, #[serde(default, skip_serializing_if = "Bytes::is_zero")] pub hash: Bytes, #[serde(default, skip_serializing_if = "Bytes::is_zero")] pub prev_block_hash: Bytes, #[serde(default, skip_serializing_if = "Bytes::is_zero")] pub pub_key: Bytes, #[serde(default, skip_serializing_if = "Bytes::is_zero")] pub signature: Bytes, #[serde(skip_serializing_if = "Option::is_none")] pub transaction: Option } impl Block { pub fn new(transaction: Option, pub_key: Bytes, prev_block_hash: Bytes, difficulty: u32) -> Self { Block { index: 0, timestamp: 0, version: 0, difficulty, random: 0, nonce: 0, transaction, prev_block_hash, hash: Bytes::default(), pub_key, signature: Bytes::default() } } #[allow(clippy::too_many_arguments)] pub fn from_all_params(index: u64, timestamp: i64, version: u32, difficulty: u32, random: u32, nonce: u64, prev_block_hash: Bytes, hash: Bytes, pub_key: Bytes, signature: Bytes, transaction: Option) -> Self { Block { index, timestamp, version, difficulty, random, nonce, transaction, prev_block_hash, hash, pub_key, signature } } pub fn from_bytes(data: &[u8]) -> serde_cbor::Result { serde_cbor::from_slice(data) } pub fn is_genesis(&self) -> bool { self.index == 1 && matches!(Transaction::get_type(&self.transaction), TransactionType::Origin) && self.prev_block_hash == Bytes::default() } /// Serializes block to CBOR for network pub fn as_bytes(&self) -> Vec { serde_cbor::to_vec(&self).unwrap() } /// Serializes block to bincode format for hashing. pub fn as_bytes_compact(&self) -> Vec { bincode::serialize(&self).unwrap() } /// Checks if this block is superior than the other pub fn is_better_than(&self, other: &Block) -> bool { if self.transaction.is_some() && other.transaction.is_none() { return true; } let hash_diff = hash_difficulty(self.hash.as_slice()) + key_hash_difficulty(self.hash.as_slice()); let my_diff = (hash_diff << 16) + (self.hash.get_tail_u64() % 0xFFFF) as u32; let hash_diff = hash_difficulty(other.hash.as_slice()) + key_hash_difficulty(other.hash.as_slice()); let it_diff = (hash_diff << 16) + (other.hash.get_tail_u64() % 0xFFFF) as u32; if my_diff > it_diff { return true; } false } }