数据结构
一、区块链的数据结构
区块链结构本质为区块组成的链表。
传统链表的实现方式是通过指针将各个节点串联起来而称为最终的链。但在区块链系统中,并未采用指针,而是使用了哈希指针。
哈希指针(Hash Pointer)
一种特殊的指针,它不仅指向数据的位置,还包含该数据的哈希值(Hash)。
可以理解为:哈希指针 = 传统指针P
(该节点的地址) + 该节点的哈希值H()
。
作用在于:当节点(区块)中内容发生改变,该哈希值也会发生改变,从而保证了区块内容不能被篡改。
每个区块通过哈希指针链接到前一个区块,形成一条不可篡改的链。如果要改其中某一个节点,则意味着后续所有节点都将发生改变。因此,用户只需要记住最后一个区块链的哈希地址,就可以检测区块链上内容是否被篡改。
二、区块的数据结构
区块是区块链的基本组成单位,由区块头和区块体组合而成。
1. 区块头(Block Header)
属性名称 | 描述 |
---|---|
版本号(Version) | 区块的协议版本号,便于不同版本的节点兼容。 |
区块高度(Index / Height) | 区块在区块链中的位置,有助于快速查找区块。 |
前一个区块的哈希(Previous Block Hash) | 指向前一个区块的哈希值,用于维持区块链的连贯性和安全性。 |
时间戳(Timestamp) | 区块创建的时间。 |
难度目标(Difficulty Target) | 当前区块的挖矿难度目标,决定了生成区块所需的计算难度。 |
随机数(Nonce) | 挖矿过程中不断变化的值,用于找到满足难度目标的有效哈希值。 |
默克尔根(Merkle Root) | 交易的哈希值通过 Merkle 树结构计算出的根哈希值。 |
区块大小(Block Size) | 记录区块大小(单位:字节),优化存储和传输。 |
2. 区块体(Block Body)
属性名称 | 描述 |
---|---|
交易列表(Transaction List) | 包含该区块中所有的交易信息。 |
矿工奖励(Miner Reward) | 记录矿工的奖励交易,包括接收者和奖励金额。 |
json
// 伪代码
{
"index": 1, // 区块在区块链中的位置
"version": 1, // 区块的协议版本号
"previous_hash": "abc123...", // 前一个区块的哈希值
"timestamp": 1700000000, // 区块创建的时间
"difficulty": "0000ffffffff...", // 当前区块的挖矿难度目标
"nonce": 12345, // 挖矿过程中不断变化的值
"merkle_root": "xyz789...", // 交易的哈希值通过 Merkle 树结构计算出的根哈希值
"block_size": 1024, // 区块大小(单位:字节)
"transactions": [], // 该区块中所有的交易信息
"miner_reward": { "recipient": "MinerXYZ", "amount": 6.25 }, // 矿工的奖励交易
"hash": "def456..." // 区块的哈希值
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
三、交易(Transactions)数据结构
属性名称 | 描述 |
---|---|
交易ID(Transaction ID) | 交易的唯一标识符。 |
输入(Inputs) | 交易的输入部分,指向前一交易输出的引用。 |
输出(Outputs) | 交易的输出部分,指定接收者和发送金额。 |
附加数据(Extra Data) | 可选的附加信息。 |
json
{
"transactions": [
{
"tx_id": "tx123...", // 交易的唯一标识符
"inputs": [ // 交易的输入部分,指向前一交易输出的引用
{
"prev_tx_id": "prev_tx456...", // 前一个交易的哈希值
"output_index": 0 // 前一个交易的输出索引
}
],
"outputs": [ // 交易的输出部分,指定接收者和发送金额
{
"recipient": "Bob", // 接收者
"amount": 10 // 发送金额
}
]
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
四、账户的数据结构
字段 | 说明 |
---|---|
address | 比特币地址(公钥哈希的 Base58 编码) |
public_key | 账户的公钥(可由私钥生成) |
private_key | 账户的私钥(用于签名交易,不能公开) |
balance | 账户余额(由 UTXO 计算得出) |
utxos | 该地址未花费的交易输出(UTXO 列表) |
json
{
"address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
"public_key": "04bfcab6b4a897...",
"private_key": "L5oLswjB1G8L3...",
"balance": 1.5,
"utxos": [
{
"tx_id": "tx123...",
"output_index": 0,
"amount": 0.5,
"script_pubkey": "76a91489abcdefabbaabbaabbaabbaabbaabbaabbaabba88ac"
},
{
"tx_id": "tx456...",
"output_index": 1,
"amount": 1.0,
"script_pubkey": "76a91489abcdefabbaabbaabbaabbaabbaabbaabbaabba88ac"
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
UTXO(未花费交易输出,Unspent Transaction Output)
UTXO 是比特币交易模型的核心概念,定义了比特币的交易方式和账户余额计算方式。
1. UTXO 模型的基本概念
在比特币网络中:
- UTXO 是可用的余额,它代表了一笔交易中的 未被花费的输出。
- 当你进行交易时,你的输入必须来自之前的 UTXO,并且交易会生成新的 UTXO,供未来使用。
- 比特币钱包的余额 = 该钱包地址所有 UTXO 的总和。
2. UTXO 交易流程
示例:Alice 给 Bob 转账 3 BTC
Alice 的 UTXO 记录:
- 之前 Alice 收到了 5 BTC,该 UTXO 还未使用。
Alice 现在想给 Bob 发送 3 BTC
- Alice 的钱包使用之前的 5 BTC UTXO 作为 输入。
- 交易会生成两个新的 UTXO:
- 3 BTC 转给 Bob(Bob 可用的余额)。
- 2 BTC 找零返回 Alice(新的 UTXO)。
3. UTXO 交易示例(JSON 格式)
json
{
"tx_id": "tx123...",
"inputs": [
{
"prev_tx_id": "prev_tx456...",
"output_index": 0,
"script_sig": "signature_data..."
}
],
"outputs": [
{
"recipient": "Bob",
"amount": 3.0,
"script_pubkey": "locking_script_bob"
},
{
"recipient": "Alice",
"amount": 2.0,
"script_pubkey": "locking_script_alice"
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
inputs
(交易输入):使用 Alice 之前的 UTXO。outputs
(交易输出):- 3 BTC 给 Bob(新 UTXO)。
- 2 BTC 找零给 Alice(新 UTXO)。
注意:输入金额 必须等于 输出金额(不包括矿工费)。
- UTXO 是"未花费的交易输出",它决定了比特币交易的本质。
- 比特币余额 = 该地址下所有 UTXO 之和。
- UTXO 只能使用一次,防止双花攻击。
- 与以太坊账户模型不同,UTXO 结构更适合匿名性和并行处理。
🚀 你可以把 UTXO 想象成"现金找零",交易会拆分和生成新的 UTXO,而不会直接修改账户余额