NAC_Blockchain/nac-cbpp/src/block.rs

216 lines
5.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 区块结构定义
use serde::{Deserialize, Serialize};
use sha3::{Digest, Sha3_384};
use chrono::{DateTime, Utc};
/// 区块头
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BlockHeader {
pub version: u32,
pub height: u64,
pub timestamp: DateTime<Utc>,
pub prev_hash: String,
pub merkle_root: String,
pub state_root: String,
pub validator: String,
pub signature: String,
}
impl BlockHeader {
pub fn new(height: u64, prev_hash: String, validator: String) -> Self {
BlockHeader {
version: 1,
height,
timestamp: Utc::now(),
prev_hash,
merkle_root: String::new(),
state_root: String::new(),
validator,
signature: String::new(),
}
}
/// 计算区块头哈希
pub fn hash(&self) -> String {
let data = format!(
"{}{}{}{}{}{}{}",
self.version,
self.height,
self.timestamp.timestamp(),
self.prev_hash,
self.merkle_root,
self.state_root,
self.validator
);
let hash = Sha3_384::digest(data.as_bytes());
hex::encode(hash)
}
}
/// 交易结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Transaction {
pub from: String,
pub to: String,
pub amount: u64,
pub nonce: u64,
pub signature: String,
}
impl Transaction {
pub fn new(from: String, to: String, amount: u64, nonce: u64) -> Self {
Transaction {
from,
to,
amount,
nonce,
signature: String::new(),
}
}
/// 计算交易哈希
pub fn hash(&self) -> String {
let data = format!(
"{}{}{}{}",
self.from, self.to, self.amount, self.nonce
);
let hash = Sha3_384::digest(data.as_bytes());
hex::encode(hash)
}
}
/// 区块体
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BlockBody {
pub transactions: Vec<Transaction>,
}
impl BlockBody {
pub fn new() -> Self {
BlockBody {
transactions: Vec::new(),
}
}
pub fn add_transaction(&mut self, tx: Transaction) {
self.transactions.push(tx);
}
/// 计算Merkle根
pub fn calculate_merkle_root(&self) -> String {
if self.transactions.is_empty() {
return String::from("0000000000000000000000000000000000000000000000000000000000000000");
}
let mut hashes: Vec<String> = self.transactions
.iter()
.map(|tx| tx.hash())
.collect();
while hashes.len() > 1 {
let mut new_hashes = Vec::new();
for chunk in hashes.chunks(2) {
let combined = if chunk.len() == 2 {
format!("{}{}", chunk[0], chunk[1])
} else {
format!("{}{}", chunk[0], chunk[0])
};
let hash = Sha3_384::digest(combined.as_bytes());
new_hashes.push(hex::encode(hash));
}
hashes = new_hashes;
}
hashes[0].clone()
}
}
impl Default for BlockBody {
fn default() -> Self {
Self::new()
}
}
/// 完整区块
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Block {
pub header: BlockHeader,
pub body: BlockBody,
}
impl Block {
pub fn new(height: u64, prev_hash: String, validator: String) -> Self {
Block {
header: BlockHeader::new(height, prev_hash, validator),
body: BlockBody::new(),
}
}
pub fn add_transaction(&mut self, tx: Transaction) {
self.body.add_transaction(tx);
}
/// 完成区块计算Merkle根和哈希
pub fn finalize(&mut self) {
self.header.merkle_root = self.body.calculate_merkle_root();
}
/// 获取区块哈希
pub fn hash(&self) -> String {
self.header.hash()
}
/// 获取区块高度
pub fn height(&self) -> u64 {
self.header.height
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_block_creation() {
let block = Block::new(1, "genesis".to_string(), "validator1".to_string());
assert_eq!(block.height(), 1);
}
#[test]
fn test_transaction_hash() {
let tx = Transaction::new(
"alice".to_string(),
"bob".to_string(),
100,
1
);
let hash = tx.hash();
assert!(!hash.is_empty());
assert_eq!(hash.len(), 96); // SHA3-384 = 48 bytes = 96 hex chars
}
#[test]
fn test_merkle_root() {
let mut body = BlockBody::new();
body.add_transaction(Transaction::new("a".to_string(), "b".to_string(), 10, 1));
body.add_transaction(Transaction::new("c".to_string(), "d".to_string(), 20, 2));
let root = body.calculate_merkle_root();
assert!(!root.is_empty());
}
#[test]
fn test_block_finalize() {
let mut block = Block::new(1, "genesis".to_string(), "validator1".to_string());
block.add_transaction(Transaction::new("alice".to_string(), "bob".to_string(), 100, 1));
block.finalize();
assert!(!block.header.merkle_root.is_empty());
}
}