mirror of https://github.com/Revertron/Alfis
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
3.6 KiB
Rust
120 lines
3.6 KiB
Rust
extern crate serde;
|
|
extern crate serde_json;
|
|
|
|
use std::cell::RefCell;
|
|
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<Transaction>,
|
|
#[serde(default, skip)]
|
|
hash_good: RefCell<bool>
|
|
}
|
|
|
|
impl Block {
|
|
pub fn new(transaction: Option<Transaction>, 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(),
|
|
hash_good: RefCell::new(false)
|
|
}
|
|
}
|
|
|
|
#[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<Transaction>) -> Self {
|
|
Block {
|
|
index,
|
|
timestamp,
|
|
version,
|
|
difficulty,
|
|
random,
|
|
nonce,
|
|
transaction,
|
|
prev_block_hash,
|
|
hash,
|
|
pub_key,
|
|
signature,
|
|
hash_good: RefCell::new(false)
|
|
}
|
|
}
|
|
|
|
pub fn from_bytes(data: &[u8]) -> serde_cbor::Result<Self> {
|
|
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()
|
|
}
|
|
|
|
pub fn is_hash_good(&self) -> bool {
|
|
*self.hash_good.borrow()
|
|
}
|
|
|
|
pub fn set_hash_good(&self, good: bool) {
|
|
*self.hash_good.borrow_mut() = good;
|
|
}
|
|
|
|
/// Serializes block to CBOR for network
|
|
pub fn as_bytes(&self) -> Vec<u8> {
|
|
serde_cbor::to_vec(&self).unwrap()
|
|
}
|
|
|
|
/// Serializes block to bincode format for hashing.
|
|
pub fn as_bytes_compact(&self) -> Vec<u8> {
|
|
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;
|
|
}
|
|
|
|
if my_diff == it_diff && self.nonce != other.nonce {
|
|
return self.nonce < other.nonce;
|
|
}
|
|
|
|
false
|
|
}
|
|
} |