区块链的数据结构
区块头
区块头一般由本区块ID、上一个区块ID、版本号、时间戳、计算难度和Nonce值组成。其中,本区块ID和上一个区块ID用于实现区块的链接功能,计算难度和Nonce值用于用于实现区块的打包机制。
1 区块ID和上一个区块ID
这两个部分的工作机制类似于链表中的指针和地址,基于哈希算法的高随机性质和低重复性质,区块ID可以视作某区块在网络中的唯一标示,区块链通过记录本区块ID和上一个区块ID,实现了区块们的链接功能。
2 版本号和时间戳
版本号和时间戳分别标示了区块生成的时间和当前区块链使用的版本类型。
3 计算难度和Nonce值
具有计算难度和Nonce值部分的区块采用了工作量证明的共识机制,使用了不同共识机制的区块链应用有不同的结构用于实现具体的共识机制。计算难度用于控制终端打包形成新的区块所需要的时间,Nonce对打包工作的实现进行辅助。
区块体
区块体是区块链中存储交易信息的部分,它由操作记录格式、Merkle树机制和记录加密机制三部分组成。
1 操作记录格式
不同的区块链应用可能会针对自身应用的性质设计不同的操作数据记录格式。比特币中记录的操作是货币交易记录,比特币设计的交易记录格式良好地完成了对交易的可追踪记录。一个完整的交易条目记录由三个部分组成,分别是输入记录、输出记录和交易索引。
2 Merkle树机制
Merkle树是一种建立在哈希函数基础上的树形数据结构,Merkle树只在其叶节点上进行操作记录。所有经过加密的操作记录会首先被转化为哈希值,记录在操作记录的父节点中;随后,所有操作记录的哈希值会两两捉对,计算其和的哈希值,记录在两个捉对的哈希值的共同的父节点中;两两捉对计算哈希值记录的进程将会不断重复,直至产生最后的总的哈希值。
3 记录加密机制
Merkle树的叶节点是历史操作的记录,这些操作记录并非直接记录在树中,而是经过密钥机制进行非对称加密以保护隐私和确认交易双方的身份。
数据结构实现
下面是用rust语言实现的区块链数据结构例子
use std::error::Error;
use std::time::{SystemTime};
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
/// Block keeps block headers
#[derive(Debug)]
pub struct Block {
timestamp: u128, // 时间戳
data: String, // 区块存储的实际有效信息,也就是交易
prev_block_hash: String, // 前一个块的哈希,即父哈希
hash: String, // 当前块的哈希
}
impl Block {
/// SetHash calculates and sets block hash
pub fn set_hash(&mut self) -> Result {
self.timestamp = SystemTime::now() // 获取当前时间戳
.duration_since(SystemTime::UNIX_EPOCH)? // 获取自1970年1月1日以来经过的时间
.as_millis(); // 转换为毫秒
let content = (self.data.clone(), self.prev_block_hash.clone(), self.timestamp); // 将区块中的数据、前一个块的哈希和时间戳拼接起来
let bytes = serialize(&content)?; // 将拼接后的数据序列化为字节数组
let mut hasher = Sha256::new(); // 创建SHA-256哈希器
hasher.input(&bytes[..]); // 将字节数组输入到哈希器中
self.hash = hasher.result_str(); // 计算哈希值并赋值给当前块的哈希字段
Ok(())
}
/// NewBlock creates and returns Block
pub fn new_block(data: String, prev_block_hash: String) -> Result {
let mut block = Block {
timestamp: 0,
data,
prev_block_hash,
hash: String::new(),
};
block.set_hash()?; // 计算当前块的哈希值
Ok(block)
}
/// NewGenesisBlock creates and returns genesis Block
pub fn new_genesis_block() -> Block {
Block::new_block(String::from("Genesis Block"), String::new()).unwrap() // 创建创世块并返回
}
/// GetHash returns block hash
pub fn get_hash(&self) -> &String {
&self.hash // 返回当前块的哈希值
}
}
/// Blockchain keeps a sequence of Blocks
#[derive(Debug)]
pub struct Blockchain {
blocks: Vec, // 区块链中所有区块组成的向量
}
impl Blockchain {
/// AddBlock saves provided data as a block in the blockchain
pub fn add_block(&mut self, data: String) -> Result {
let prev = self.blocks.last().unwrap(); // 获取区块链中最后一个区块(即前一个块)
let newblock = Block::new_block(data, prev.get_hash().clone())?; // 创建新区块并计算其哈希值
self.blocks.push(newblock); // 将新区块添加到区块链中
Ok(())
}
/// NewBlockchain creates a new Blockchain with genesis Block
pub fn new() -> Blockchain {
Blockchain {
blocks: vec![Block::new_genesis_block()], // 创建创世块并将其作为第一个区块添加到区块链中
}
}
}
from刘金,转载请注明原文链接。感谢!