深入理解区块链 - 第2章:比特币的工作原理
学习目标
通过本章学习,你将彻底理解:
- 比特币要解决什么问题
- 比特币交易的结构和UTXO模型
- 区块和区块链如何工作
- 工作量证明和挖矿的原理
- 最长链规则和分叉处理
- 比特币网络如何达成共识
前置知识
- 理解信任问题的本质(第1章)
- 理解哈希函数和数字签名(第1章)
- 理解去中心化的意义(第1章)
第一部分:比特币要解决什么问题?
1.1 历史背景:2008年金融危机
2008年,全球发生了严重的金融危机。
事件:
- 银行倒闭(雷曼兄弟等)
- 政府救市(用纳税人的钱)
- 人们对中心化机构失去信任
中本聪的思考:
- 为什么要把钱存在银行?
- 为什么要把信任交给第三方?
- 能不能有不需要银行的货币系统?
核心问题:
- 传统货币系统依赖银行
- 银行可能倒闭
- 银行可能作恶
- 用户无法完全控制自己的钱
1.2 传统货币系统的问题
问题1:依赖银行
描述:
- 你的钱存在银行,银行记录你的余额
- 如果银行倒闭,你的钱可能就没了
- 如果银行被攻击,你的钱可能被盗
例子:
- 2008年金融危机,很多银行倒闭
- 用户存款可能无法取回
- 即使有存款保险,也有上限
本质:
- 你的钱不在你手里
- 你依赖银行保管
- 银行失效 = 你的钱可能丢失
问题2:需要信任
描述:
- 你需要信任银行不会作恶
- 你需要信任银行不会倒闭
- 你需要信任银行不会冻结你的账户
例子:
- 银行可以冻结账户(反洗钱等)
- 银行可以拒绝服务
- 银行可能倒闭
本质:
- 需要持续信任第三方
- 信任成本高
- 信任风险大
问题3:无法自主
描述:
- 你不能完全控制你的钱
- 银行可以冻结
- 政府可以没收
- 你无法完全自主
例子:
- 银行可以冻结账户
- 政府可以没收资产
- 你无法完全控制
本质:
- 控制权不在你手里
- 依赖第三方
- 无法完全自主
1.3 中本聪的解决方案
核心思想: 创建一个点对点的电子现金系统。
特点:
- 不需要银行
- 不需要第三方
- 点对点直接交易
- 通过数学和密码学保证信任
这就是比特币。
1.4 比特币的核心创新
创新1:去中心化
传统系统:
用户 → 银行 → 用户
↑
所有数据在银行
比特币系统:
用户 → 区块链网络 → 用户
↑
数据在所有节点
优势:
- 不依赖单一机构
- 无单点故障
- 无单点控制
创新2:不可篡改
传统系统:
- 银行可以修改记录
- 可以删除交易
- 可以回滚
比特币系统:
- 交易一旦上链,无法修改
- 无法删除
- 无法回滚
优势:
- 历史记录永久保存
- 无法篡改
- 可以验证
创新3:无需信任
传统系统:
- 需要信任银行
- 需要信任政府
- 需要信任第三方
比特币系统:
- 信任数学和密码学
- 信任代码和共识
- 不需要信任任何人
优势:
- 降低信任成本
- 降低信任风险
- 提高自主性
第二部分:比特币交易的结构
2.1 传统账户模型 vs UTXO模型:用钱包理解比特币
传统账户模型:像银行账户
就像你的银行账户:
想象一下,你去银行查余额:
- 银行告诉你:"你的账户里有1000元"
- 这就是账户余额模型
工作原理:
你的账户:
- 余额:1000元
- 存在银行的数据库里
你转给朋友300元:
- 你的余额:1000 - 300 = 700元
- 朋友的余额:0 + 300 = 300元
- 银行更新数据库
简单直观,就像记账本。
优点:
- 简单:直接看余额就行
- 直观:就像记账本
- 容易理解
缺点:
- 依赖银行:所有数据在银行
- 银行可以修改:可以改你的余额
- 银行可以冻结:可以冻结你的账户
UTXO模型:像现金钱包
就像你的现金钱包:
想象一下,你打开钱包:
- 你看到:一张100元、一张50元、三张20元
- 你没有"余额"这个概念,只有"这些钞票"
- 这就是UTXO模型
UTXO是什么?
UTXO = Unspent Transaction Output(未花费的交易输出)
通俗理解:
- 未花费:还没用过的
- 交易输出:之前某笔交易给你的
- UTXO:就是"还没花掉的比特币"
就像现金:
你的钱包里:
- 一张100元钞票(这是UTXO1)
- 一张50元钞票(这是UTXO2)
- 三张20元钞票(这是UTXO3、UTXO4、UTXO5)
你要付150元给商家:
- 你不能"从余额里扣150元"(因为没有余额)
- 你必须拿出具体的钞票:
- 拿出一张100元(使用UTXO1)
- 拿出一张50元(使用UTXO2)
- 总共150元,正好
- 付给商家150元
- 没有找零
你要付80元给朋友:
- 拿出一张100元(使用UTXO1)
- 付给朋友80元
- 找回20元(创建新的UTXO6)
比特币也是这样:
你的"钱包"里:
- UTXO1:1 BTC(来自之前的交易A)
- UTXO2:0.5 BTC(来自之前的交易B)
- UTXO3:0.2 BTC(来自之前的交易C)
你要付0.7 BTC给商家:
- 你不能"从余额里扣0.7 BTC"(因为没有余额)
- 你必须使用具体的UTXO:
- 使用UTXO1(1 BTC)
- 付给商家0.7 BTC(创建新的UTXO4)
- 找回0.3 BTC(创建新的UTXO5,给自己)
- UTXO1被销毁(已花费)
关键:输入必须完全花费,然后找零。
为什么比特币用UTXO而不是账户模型?
原因1:更简单
账户模型需要:
- 维护所有账户的余额
- 每次交易更新余额
- 需要中心化服务器
UTXO模型:
- 只需要记录"哪些UTXO还没花"
- 不需要维护余额
- 可以分布式存储
原因2:更安全
账户模型:
- 如果服务器被攻击,余额可能被修改
- 如果服务器故障,余额可能丢失
UTXO模型:
- UTXO是交易输出,记录在区块链上
- 无法伪造(因为需要签名)
- 无法修改(因为区块链不可篡改)
原因3:更透明
账户模型:
- 你只能看到自己的余额
- 不知道钱从哪里来
UTXO模型:
- 每个UTXO都有历史
- 可以追踪每一笔钱的来源
- 完全透明
用生活例子理解UTXO
例子1:收红包
过年了,你收到三个红包:
- 红包1:100元(这是UTXO1)
- 红包2:50元(这是UTXO2)
- 红包3:20元(这是UTXO3)
你的"钱包"里有三个UTXO,总共170元。
你要买一个80元的玩具:
- 你不能说"从170元里扣80元"
- 你必须拿出具体的红包:
- 拿出红包1(100元)
- 付80元
- 找回20元(新的"红包")
- 红包1被"销毁"(已花费)
例子2:找零
你要付35元:
- 你只有一张50元(UTXO1)
- 你必须用这张50元
- 付35元
- 找回15元(新的UTXO2)
- UTXO1被销毁
你不能说"我只用35元,剩下的15元还在"
- 必须全部用掉,然后找零
例子3:组合支付
你要付150元:
- 你有:100元(UTXO1)、50元(UTXO2)、20元(UTXO3)
- 你可以:
- 方案1:用UTXO1(100元)+ UTXO2(50元)= 150元
- 方案2:用UTXO1(100元)+ UTXO3(20元)× 3 = 160元,找回10元
比特币钱包会自动选择最优方案。
2.2 交易的结构:比特币转账的"票据"
2.2.1 交易就像一张"转账票据"
生活中的类比:
想象一下,你要给朋友转账:
- 你写一张"转账单":
- 从哪个账户转出?(输入)
- 转给谁?(输出)
- 转多少钱?(金额)
- 你的签名(证明是你转的)
比特币交易就是这样一张"转账票据"。
2.2.2 交易的基本结构(通俗理解)
一个比特币交易包含三部分:
1. 输入(Inputs):你要花哪些钱
就像你从钱包里拿出钞票:
- 你要用哪些UTXO?
- 这些UTXO来自哪笔交易?
- 你要用私钥签名,证明这些钱是你的
2. 输出(Outputs):你要给谁钱
就像你付钱给别人:
- 给谁?(接收者的地址)
- 给多少?(金额)
- 找零多少?(如果有)
3. 签名(Signatures):证明是你转的
就像你在转账单上签名:
- 用你的私钥签名
- 证明这笔交易是你发的
- 其他人可以用你的公钥验证
2.2.3 详细的交易结构(技术细节)
完整的交易结构:
交易 {
// 1. 版本号:交易的版本
版本号 (Version)
// 2. 输入列表:你要花哪些UTXO
输入列表 (Inputs) [
{
// 这个UTXO来自哪笔交易?
前一个交易的哈希 (Previous Tx Hash)
// 是那笔交易的第几个输出?
输出索引 (Output Index)
// 解锁脚本:证明这些钱是你的
// 包含:你的签名 + 你的公钥
解锁脚本 (Unlocking Script)
// 序列号:用于其他功能
序列号 (Sequence)
}
]
// 3. 输出列表:你要给谁钱
输出列表 (Outputs) [
{
// 给多少钱?
金额 (Amount)
// 锁定脚本:这些钱给谁?
// 包含:接收者的公钥哈希(地址)
锁定脚本 (Locking Script)
}
]
// 4. 锁定时间:交易生效的时间
锁定时间 (Locktime)
}
通俗理解每个字段:
版本号:
- 就像软件的版本号
- 告诉系统这个交易用的是什么格式
- 用于协议升级
前一个交易的哈希:
- 就像"这张钞票来自哪笔交易"
- 用来找到你要用的UTXO
- 就像"引用"之前的交易
输出索引:
- 就像"是那笔交易的第几个输出"
- 因为一笔交易可能有多个输出
- 需要指定是哪一个
解锁脚本:
- 就像"证明这些钱是你的"
- 包含:你的签名 + 你的公钥
- 用你的私钥签名,证明你有权使用这些UTXO
金额:
- 给多少钱
- 单位是"聪"(Satoshi)
- 1 BTC = 100,000,000 聪
锁定脚本:
- 这些钱给谁?
- 包含接收者的公钥哈希(地址)
- 只有接收者可以用私钥解锁
锁定时间:
- 交易什么时候生效?
- 可以是立即生效,也可以是未来某个时间
- 用于延迟交易
2.3 一个完整的交易例子:Alice给Bob转账
场景设定
人物:
- Alice:要转账的人
- Bob:接收转账的人
- 矿工:打包交易的人(会收到手续费)
初始状态:
- Alice有1个比特币(来自之前的交易A)
- Alice要转0.5个比特币给Bob
- 需要支付0.01个比特币作为手续费
交易过程(详细步骤)
步骤1:Alice创建交易
Alice打开比特币钱包,要转0.5 BTC给Bob。
钱包显示:
- 你有1 BTC(来自交易A)
- 你要转0.5 BTC给Bob
- 需要手续费0.01 BTC
- 找零:1 - 0.5 - 0.01 = 0.49 BTC
Alice点击"发送"。
步骤2:钱包构建交易
钱包自动构建交易:
交易B {
// 输入:Alice要用的UTXO
输入:
- 来自交易A的输出0(1 BTC)
- 用Alice的私钥签名(证明这1 BTC是Alice的)
// 输出:Alice要给谁钱
输出:
- 输出0:0.5 BTC给Bob
(锁定到Bob的地址,只有Bob可以用私钥解锁)
- 输出1:0.49 BTC找零给Alice
(锁定到Alice的新地址,Alice可以继续使用)
- 输出2:0.01 BTC手续费给矿工
(这是隐式的,不需要明确输出)
}
步骤3:Alice签名交易
Alice用私钥签名交易:
- 钱包自动用Alice的私钥签名
- 签名证明:这笔交易是Alice发的
- 签名证明:Alice有权使用这1 BTC
签名过程(内部):
1. 计算交易的哈希值
2. 用Alice的私钥签名哈希值
3. 把签名放到交易的解锁脚本中
步骤4:广播交易
Alice的钱包把交易广播到网络:
- 发送给连接的节点
- 节点验证交易
- 如果有效,继续广播
- 很快传播到整个网络
步骤5:矿工打包交易
矿工收到交易:
- 验证交易是否有效
- 如果有效,加入内存池(Mempool)
- 选择交易打包到区块
- 挖到区块后,交易被确认
步骤6:交易确认
交易被打包到区块后:
- 交易被确认
- UTXO状态更新:
- 交易A的输出0:已花费(销毁)
- 新的UTXO1:0.5 BTC给Bob(Bob可以使用)
- 新的UTXO2:0.49 BTC给Alice(Alice可以继续使用)
用生活例子理解
就像用现金买东西:
场景:Alice要买Bob的商品,价格0.5 BTC
Alice的钱包:
- 只有一张1 BTC的"钞票"(UTXO)
交易过程:
1. Alice拿出1 BTC的"钞票"
2. 付给Bob 0.5 BTC
3. Bob找回0.49 BTC(0.01 BTC是手续费,给矿工)
4. 原来的1 BTC"钞票"被销毁
5. 新的0.5 BTC"钞票"给Bob
6. 新的0.49 BTC"钞票"给Alice
就像用现金买东西,必须整张用,然后找零。
关键点详解
1. 输入必须完全花费
为什么?
就像现金:
- 你不能说"我只用这张100元的一半"
- 你必须整张用,然后找零
比特币也是这样:
- 你不能说"我只用这1 BTC的一部分"
- 你必须全部用,然后找零
原因:
- UTXO是不可分割的
- 就像一张钞票,不能撕成两半用
- 必须整张用,然后找零
例子:
你要付0.3 BTC:
- 你只有1 BTC的UTXO
- 你不能只"用0.3 BTC"
- 你必须:
- 用1 BTC(全部)
- 付0.3 BTC给商家
- 找回0.7 BTC(新的UTXO)
2. 每笔交易都需要签名
为什么?
就像转账需要签名:
- 银行转账需要你的签名
- 证明这笔交易是你发的
比特币也是这样:
- 用你的私钥签名
- 证明这笔交易是你发的
- 证明你有权使用这些UTXO
如果没有签名:
- 任何人都可以花你的钱
- 系统无法验证
- 交易会被拒绝
签名过程:
1. 钱包计算交易的哈希值
2. 用你的私钥签名哈希值
3. 把签名放到交易的解锁脚本中
4. 其他人用你的公钥验证签名
5. 如果验证通过,交易有效
3. 交易是公开的
为什么?
区块链是公开的:
- 所有交易都记录在区块链上
- 任何人都可以查看
- 任何人都可以验证
但地址是匿名的:
- 地址是公钥的哈希值
- 看起来像随机字符串
- 不知道地址对应的是谁
就像:
- 所有人都能看到"地址A转给地址B 0.5 BTC"
- 但不知道地址A和地址B是谁
4. 输出成为新的UTXO
为什么?
交易完成后:
- 输入的UTXO被销毁(已花费)
- 输出的UTXO被创建(未花费)
- 这些新的UTXO可以被后续交易使用
就像:
- 你花掉一张100元(销毁)
- 收到一张50元(新的UTXO)
- 这张50元可以在下次交易中使用
UTXO的生命周期:
1. 创建:交易输出创建UTXO
2. 等待:UTXO在"钱包"里等待使用
3. 使用:交易输入使用UTXO
4. 销毁:UTXO被使用后销毁
5. 创建新UTXO:交易输出创建新的UTXO
6. 循环继续...
2.4 UTXO的生命周期
生命周期
1. 创建UTXO
- 交易输出创建UTXO
- UTXO包含金额和锁定脚本
2. 使用UTXO
- 交易输入使用UTXO
- 用私钥签名解锁
3. 销毁UTXO
- UTXO被使用后销毁
- 不能再使用
4. 创建新UTXO
- 交易输出创建新的UTXO
- 循环继续
例子
交易A:创建UTXO1(1 BTC给Alice)
交易B:使用UTXO1,创建UTXO2(0.5 BTC给Bob)和UTXO3(0.49 BTC给Alice)
交易C:使用UTXO2,创建UTXO4(0.3 BTC给Charlie)和UTXO5(0.19 BTC给Bob)
2.5 如何防止双重支付?
问题
在数字世界,如何防止"同一笔钱花两次"?
传统方式:
- 银行记录
- 中心化账本
问题:
- 依赖银行
- 银行可以修改记录
比特币的解决方案
方案:把所有交易记录在区块链上。
原理:
- 每笔交易都记录在区块链上
- 每个UTXO只能使用一次
- 如果尝试使用已使用的UTXO,会被拒绝
验证过程:
- 检查输入UTXO是否存在
- 检查输入UTXO是否已被使用
- 检查签名是否有效
- 检查输出金额是否合理
如果尝试双重支付:
- 第一笔交易会被接受
- 第二笔交易会被拒绝(UTXO已被使用)
第三部分:区块和区块链:账本的一页页
3.1 什么是区块?就像账本的一页
3.1.1 生活中的类比
想象一本账本:
账本第1页:
- 记录了1月1日的所有交易
- 交易1:Alice转给Bob 100元
- 交易2:Charlie转给David 50元
- 交易3:...
账本第2页:
- 记录了1月2日的所有交易
- 交易1:...
- 交易2:...
每一页 = 一个区块
整本账本 = 区块链
比特币也是这样:
区块1:
- 记录了某个时间段的所有交易
- 交易1:地址A转给地址B 0.5 BTC
- 交易2:地址C转给地址D 1 BTC
- 交易3:...
区块2:
- 记录了下一个时间段的所有交易
- 交易1:...
- 交易2:...
每个区块 = 一页账本
区块链 = 整本账本
3.1.2 区块的定义
定义:区块是一页账本,记录一段时间内的所有交易。
关键点:
- 一段时间:通常是10分钟(比特币)
- 所有交易:这段时间内的所有有效交易
- 一页账本:就像账本的一页
为什么需要区块?
如果没有区块:
- 交易散乱,无法组织
- 无法验证历史
- 无法防止双重支付
有了区块:
- 交易被组织起来
- 可以验证历史
- 可以防止双重支付
3.1.3 区块的结构(通俗理解)
区块就像一页账本,包含两部分:
1. 区块头(Block Header):页眉信息
就像账本每页的页眉:
- 第几页?(区块编号)
- 上一页是什么?(前一个区块的哈希)
- 这页有哪些交易?(Merkle根)
- 什么时候写的?(时间戳)
- 难度是多少?(难度目标)
- 随机数(用于挖矿)
2. 交易列表(Transactions):具体交易
就像账本每页的具体内容:
- 交易1:谁转给谁多少钱
- 交易2:谁转给谁多少钱
- 交易3:...
完整的区块结构:
区块 {
// ===== 区块头:页眉信息 =====
区块头 (Block Header) {
// 版本号:这页账本用的是什么格式?
版本号 (Version)
// 前一个区块的哈希:上一页是什么?
// 就像"第2页的前一页是第1页"
前一个区块的哈希 (Previous Block Hash)
// Merkle根:这页有哪些交易?
// 就像"这页交易的总和"
Merkle根 (Merkle Root)
// 时间戳:什么时候写的?
时间戳 (Timestamp)
// 难度目标:挖矿的难度
难度目标 (Difficulty Target)
// 随机数:用于挖矿
随机数 (Nonce)
}
// ===== 交易列表:具体内容 =====
交易列表 (Transactions) [ 交易1:地址A转给地址B 0.5 BTC 交易2:地址C转给地址D 1 BTC 交易3:... ... ]
}
3.1.4 区块头详解(通俗理解)
1. 版本号(Version)
就像软件的版本号:
- 告诉系统这个区块用的是什么格式
- 用于协议升级
- 就像"这是账本的第几版格式"
例子:
- 版本1:最初的格式
- 版本2:升级后的格式
2. 前一个区块的哈希(Previous Block Hash)
这是关键!
就像账本每页都写"上一页是什么":
- 第2页:上一页是第1页
- 第3页:上一页是第2页
- 第4页:上一页是第3页
比特币也是这样:
- 区块2:前一个区块是区块1的哈希
- 区块3:前一个区块是区块2的哈希
- 区块4:前一个区块是区块3的哈希
这样就把区块链接起来了!
为什么重要?
如果修改区块1:
- 区块1的哈希值会变
- 区块2包含区块1的哈希,所以区块2也不匹配了
- 区块3包含区块2的哈希,所以区块3也不匹配了
- 后面的所有区块都不匹配了
因此无法篡改!
3. Merkle根(Merkle Root)
什么是Merkle根?
就像"这页所有交易的总和":
- 把所有交易的哈希值计算出来
- 再把这些哈希值组合起来
- 最终得到一个"根哈希值"
这个根哈希值就是Merkle根。
作用:
- 可以快速验证这页有哪些交易
- 不需要看所有交易,只看Merkle根就行
- 就像"交易列表的指纹"
4. 时间戳(Timestamp)
什么时候创建的这个区块?
- 记录区块创建的时间
- 用于难度调整
- 用于验证区块的有效性
就像账本每页都写"什么时候写的"
5. 难度目标(Difficulty Target)
挖矿的难度是多少?
- 用于控制出块速度
- 保证大约10分钟出一个区块
- 难度越高,挖矿越难
就像"这页账本有多难写"
6. 随机数(Nonce)
用于挖矿的随机数:
- 矿工不断改变这个数
- 计算区块的哈希值
- 直到找到符合条件的哈希值
就像"试不同的数字,直到找到对的"
区块头的详细说明
1. 版本号
- 区块的版本
- 用于协议升级
2. 前一个区块的哈希
- 这是关键!
- 把区块链接起来
- 形成链条
3. Merkle根
- 所有交易的Merkle树的根
- 用于快速验证交易
4. 时间戳
- 区块创建的时间
- 用于难度调整
5. 难度目标
- 挖矿的难度
- 用于控制出块速度
6. 随机数
- 用于挖矿
- 不断改变,直到找到符合条件的哈希
3.2 Merkle树
什么是Merkle树?
定义:Merkle树是一种二叉树,用于高效验证交易。
构建过程
假设有4笔交易:Tx1, Tx2, Tx3, Tx4
1. 计算每笔交易的哈希:
H1 = Hash(Tx1)
H2 = Hash(Tx2)
H3 = Hash(Tx3)
H4 = Hash(Tx4)
2. 计算中间节点的哈希:
H12 = Hash(H1 + H2)
H34 = Hash(H3 + H4)
3. 计算根节点的哈希:
Root = Hash(H12 + H34)
这就是Merkle根。
Merkle树的作用
1. 快速验证
- 不需要下载所有交易
- 只需要Merkle路径
- 可以验证交易是否在区块中
2. 节省空间
- 不需要存储所有交易
- 只需要Merkle根
- 可以验证完整性
3. 隐私保护
- 不需要暴露所有交易
- 只需要Merkle路径
- 可以验证特定交易
3.3 区块链如何链接?
链接过程
区块1:
- 区块头包含:前一个区块的哈希 = 0(因为是第一个)
- 自己的哈希 = Hash(区块1)
区块2:
- 区块头包含:前一个区块的哈希 = Hash(区块1)
- 自己的哈希 = Hash(区块2)
区块3:
- 区块头包含:前一个区块的哈希 = Hash(区块2)
- 自己的哈希 = Hash(区块3)
形成链条
区块1 → 区块2 → 区块3 → 区块4 → ...
↓ ↓ ↓ ↓
哈希1 哈希2 哈希3 哈希4
为什么不可篡改?
原理:
- 每个区块都包含前一个区块的哈希
- 如果修改区块1,区块1的哈希就变了
- 区块2包含区块1的哈希,所以区块2也不匹配了
- 区块3包含区块2的哈希,所以区块3也不匹配了
- 后面的所有区块都不匹配了
要修改区块1:
- 必须修改区块1的哈希
- 必须修改区块2(因为包含区块1的哈希)
- 必须修改区块3(因为包含区块2的哈希)
- 必须修改后面的所有区块
- 这几乎不可能
这就是区块链"不可篡改"的原理。
3.4 区块的验证
验证过程
当节点收到新区块时,需要验证:
1. 验证区块头
- 版本号是否正确
- 前一个区块是否存在
- 时间戳是否合理
- 难度目标是否正确
2. 验证Merkle根
- 计算所有交易的Merkle根
- 对比区块头中的Merkle根
- 如果不同,区块无效
3. 验证交易
- 每笔交易是否有效
- 签名是否有效
- UTXO是否存在
- 是否双重支付
4. 验证工作量证明
- 区块的哈希是否小于难度目标
- 如果不符合,区块无效
如果所有验证都通过:
- 接受区块
- 更新区块链
- 继续挖下一个区块
第四部分:工作量证明和挖矿:谁有资格记账?
4.1 什么是工作量证明?就像"抢答题"
4.1.1 核心问题
问题:在去中心化网络中,如何决定谁可以创建区块?
就像:
- 很多人想记账
- 但只能有一个人记账
- 谁来记账?
传统方式:
中心化系统:
- 由中心服务器决定
- 服务器说"你来记账",你就记账
- 简单,但依赖中心服务器
去中心化系统:
- 没有中心服务器
- 谁来决定?
- 这是个难题!
4.1.2 工作量证明的解决方案
核心思想:通过计算来竞争,谁先算出来,谁就记账。
就像"抢答题":
老师出题:"找到一个数字,使得某个计算结果小于100"
所有学生开始计算:
- 学生A:试1,计算结果=500,不对
- 学生B:试2,计算结果=300,不对
- 学生C:试50,计算结果=80,对了!
学生C举手:"我算出来了!"
老师:"好,你来回答这个问题,然后你可以记账。"
这就是工作量证明:
- 通过计算来竞争
- 谁先算出来,谁就记账
- 计算需要成本(时间、电费),防止作弊
比特币也是这样:
矿工们都在计算:
- 找到一个随机数(Nonce)
- 使得区块的哈希值小于某个目标值
- 谁先找到,谁就可以创建区块
就像:
- 所有矿工都在"抢答"
- 谁先"答对",谁就记账
- 计算需要成本(电费、设备),防止作弊
4.1.3 工作量证明的定义
定义:工作量证明(Proof of Work, PoW)是通过计算来证明你付出了工作量的机制。
通俗理解:
- 工作量:你花了多少计算资源(CPU、电费)
- 证明:你确实花了这些资源
- 机制:通过计算来竞争记账权
为什么叫"工作量证明"?
就像:
- 你要证明你工作了,就要拿出工作成果
- 你要证明你付出了努力,就要拿出证据
工作量证明:
- 你要证明你付出了计算资源
- 就要拿出计算结果(符合条件的哈希值)
- 这个结果很难得到,需要大量计算
- 所以能证明你确实付出了工作量
4.1.4 为什么需要工作量证明?
原因1:防止作弊
如果没有工作量证明:
- 任何人都可以说"我来记账"
- 恶意节点可以随意记账
- 系统无法区分好坏
有了工作量证明:
- 要记账,必须先计算
- 计算需要成本(电费、设备)
- 恶意节点要攻击,需要大量成本
- 不划算,所以不会攻击
原因2:公平竞争
如果没有工作量证明:
- 谁来决定谁记账?
- 可能不公平
- 可能被操控
有了工作量证明:
- 所有人都在计算
- 谁先算出来,谁就记账
- 公平竞争
- 无法操控(因为计算是随机的)
原因3:保证安全
工作量证明保证:
- 要攻击网络,需要控制51%的算力
- 成本极高
- 不划算
- 因此网络安全
4.2 挖矿的过程:就像"解数学题"
4.2.1 什么是挖矿?
定义:挖矿是通过计算找到符合条件的哈希值,从而获得记账权和奖励的过程。
通俗理解:
就像挖金矿:
- 你要挖很多土,才能找到金子
- 挖土需要工具、时间、力气
- 找到金子就有奖励
比特币挖矿:
- 你要计算很多次,才能找到符合条件的哈希值
- 计算需要设备、时间、电费
- 找到符合条件的哈希值就有奖励(新产生的比特币 + 手续费)
为什么叫"挖矿"?
因为:
- 就像挖金矿,需要付出努力
- 就像挖金矿,可能挖到也可能挖不到
- 就像挖金矿,挖到就有奖励
- 所以叫"挖矿"
4.2.2 挖矿的详细过程
步骤1:收集交易
矿工的工作:
- 监听网络上的交易
- 收集交易到"内存池"(Mempool)
- 就像收集"待处理的订单"
选择交易:
- 通常选择手续费高的交易
- 因为矿工可以获得手续费
- 就像"优先处理给钱多的订单"
步骤2:构建区块
矿工构建区块:
1. 创建区块头
2. 包含前一个区块的哈希
3. 计算交易的Merkle根
4. 设置时间戳
5. 设置难度目标
6. 初始化随机数(Nonce)为0
就像:
- 准备一张"账本页"
- 写上页眉信息
- 准备写交易内容
步骤3:计算哈希(这是关键!)
矿工开始计算:
1. 计算区块头的哈希值
2. 检查哈希值是否小于难度目标
3. 如果不符合,改变随机数(Nonce)
4. 重复计算,直到找到符合条件的哈希值
就像:
- 不断试不同的数字
- 计算"答案"
- 看"答案"是否符合要求
- 不符合就继续试
详细过程:
初始状态:
- Nonce = 0
- 区块头 = {前一个区块哈希, Merkle根, 时间戳, 难度目标, Nonce=0}
第1次尝试:
- 计算:Hash(区块头) = "abc123..."
- 检查:是否小于难度目标?
- 结果:不符合("abc123" > 目标值)
- 继续:Nonce = 1
第2次尝试:
- 计算:Hash(区块头) = "def456..."
- 检查:是否小于难度目标?
- 结果:不符合
- 继续:Nonce = 2
...
第1000000次尝试:
- 计算:Hash(区块头) = "000012..."
- 检查:是否小于难度目标?
- 结果:符合!("000012" < 目标值)
- 成功!挖到区块了!
步骤4:找到符合条件的哈希值
当找到符合条件的哈希值:
- 矿工立即停止计算
- 把区块广播到网络
- 其他节点验证
- 如果验证通过,接受区块
- 矿工获得奖励
就像:
- 学生找到答案
- 举手说"我算出来了!"
- 老师验证答案
- 如果正确,学生获得奖励
步骤5:获得奖励
矿工获得奖励:
- 新产生的比特币(目前是6.25 BTC)
- 所有交易的手续费
就像:
- 你完成了工作
- 获得工资(新产生的比特币)
- 获得小费(手续费)
4.2.3 用生活例子理解挖矿
例子1:猜数字游戏
游戏规则:
- 老师出一个数字:12345
- 学生要猜一个数字,使得:猜的数字 × 12345 < 1000000
- 谁先猜对,谁就获得奖励
学生A:
- 试1:1 × 12345 = 12345,不对(太大)
- 试2:2 × 12345 = 24690,不对
- 试10:10 × 12345 = 123450,不对
- 试50:50 × 12345 = 617250,不对
- 试80:80 × 12345 = 987600,对了!
学生A:"我猜对了!"
老师:"好,你获得奖励,你来记账。"
这就是挖矿:
- 不断试不同的数字(Nonce)
- 计算哈希值
- 看是否符合要求
- 谁先找到,谁就记账
例子2:找钥匙
场景:
- 有1000把钥匙
- 只有1把能开锁
- 你要一把一把试
- 谁先找到,谁就获得奖励
矿工A:
- 试第1把:不对
- 试第2把:不对
- ...
- 试第500把:对了!
矿工A:"我找到了!"
获得奖励。
这就是挖矿:
- 不断试不同的Nonce
- 计算哈希值
- 看是否符合要求
- 谁先找到,谁就获得奖励
4.2.4 为什么挖矿这么难?
原因1:难度目标很小
难度目标就像:
- 你要找到一个数字,使得计算结果 < 0.0001
- 这很难!
比特币的难度目标:
- 哈希值必须小于某个很小的数
- 就像"要在1000000个数字中找到1个符合条件的"
- 概率极低
原因2:需要大量计算
平均需要尝试:
- 2^32次(约43亿次)
- 需要大量计算资源
- 需要大量电费
- 需要大量时间
就像:
- 你要试43亿次
- 才能找到1次对的
- 这需要很多计算
原因3:竞争激烈
所有矿工都在计算:
- 可能有10000个矿工
- 大家都在算
- 只有1个能成功
- 竞争激烈
就像:
- 10000个人在抢答
- 只有1个人能答对
- 竞争很激烈
4.2.5 挖矿的成本和收益
成本:
1. 设备成本:
- 需要专业的挖矿设备(ASIC)
- 价格昂贵(几万到几十万)
2. 电费成本:
- 挖矿需要大量电力
- 电费是主要成本
- 可能每月几万到几十万
3. 维护成本:
- 设备需要维护
- 需要场地
- 需要人工
收益:
1. 区块奖励:
- 新产生的比特币(目前6.25 BTC)
- 每4年减半
2. 交易手续费:
- 所有交易的手续费
- 随着区块奖励减少,手续费越来越重要
3. 比特币价格上涨:
- 如果比特币价格上涨
- 收益增加
盈亏平衡:
如果:
- 成本 > 收益:亏本,不挖了
- 成本 < 收益:赚钱,继续挖
- 成本 = 收益:盈亏平衡
很多矿工因为电费太高而停止挖矿。
4.2 挖矿的过程
步骤1:收集交易
过程:
- 矿工监听网络上的交易
- 收集交易到内存池(Mempool)
- 选择交易打包到区块
- 通常选择手续费高的交易
注意:
- 不是所有交易都会被包含
- 矿工优先选择手续费高的交易
- 如果网络拥堵,低手续费交易可能等待很久
步骤2:构建区块
过程:
- 创建区块头
- 包含前一个区块的哈希
- 计算交易的Merkle根
- 设置时间戳
- 设置难度目标
- 初始化随机数(Nonce)为0
步骤3:计算哈希
过程:
- 计算区块头的哈希值
- 检查哈希值是否小于难度目标
- 如果不符合,改变随机数(Nonce)
- 重复计算,直到找到符合条件的哈希值
数学表示:
Hash(区块头) < 难度目标
例子:
难度目标:0x00000000ffff0000000000000000000000000000000000000000000000000000
区块头的哈希必须小于这个值。
这就像:
- 扔骰子,要扔出1(概率1/6)
- 但这里的"骰子"有2^256个面
- 要扔出特定的数字,概率极低
步骤4:找到符合条件的哈希
过程:
- 不断改变随机数(Nonce)
- 每次计算区块头的哈希
- 检查是否小于难度目标
- 如果找到,挖矿成功
计算量:
- 平均需要尝试2^32次(约43亿次)
- 需要大量计算资源
- 这就是"工作量"
步骤5:广播区块
过程:
- 找到符合条件的哈希后
- 把区块广播到网络
- 其他节点验证
- 如果验证通过,接受区块
4.3 难度调整
为什么需要难度调整?
目标:保证大约10分钟出一个区块。
问题:
- 如果算力增加,出块速度会加快
- 如果算力减少,出块速度会减慢
- 需要动态调整难度
如何调整?
规则:每2016个区块(约2周)调整一次难度。
公式:
新难度 = 旧难度 × (2016个区块的实际时间 / 2016 × 10分钟)
例子:
如果2016个区块用了1周(实际时间短):
新难度 = 旧难度 × (1周 / 2周) = 旧难度 × 0.5
难度降低,更容易挖矿
如果2016个区块用了3周(实际时间长):
新难度 = 旧难度 × (3周 / 2周) = 旧难度 × 1.5
难度提高,更难挖矿
结果:
- 无论算力如何变化
- 出块速度保持大约10分钟
- 网络稳定运行
4.4 为什么需要工作量证明?
原因1:防止作弊
问题:如何防止恶意节点创建无效区块?
解决方案:
- 创建区块需要计算成本
- 恶意节点要攻击,需要大量算力
- 成本极高,不划算
例子:
要创建1个区块,需要:
- 大量计算资源
- 大量电力
- 大量时间
恶意节点要攻击,需要:
- 控制51%的算力
- 成本极高
- 不划算
原因2:保证一致性
问题:多个节点同时挖矿,如何保证一致性?
解决方案:
- 所有节点都在挖同一个区块
- 谁先挖到,谁的区块被接受
- 最长链规则保证网络达成一致
过程:
1. 所有节点都在挖区块N
2. 节点A先挖到,广播区块N
3. 其他节点接受区块N
4. 开始挖区块N+1
5. 网络达成一致
原因3:激励机制
问题:为什么有人愿意挖矿?
解决方案:
- 挖到区块的矿工获得奖励
- 奖励 = 新产生的比特币 + 交易手续费
- 激励矿工维护网络
奖励机制:
区块奖励:
- 初始:50 BTC
- 每21万个区块减半
- 目前:6.25 BTC
- 最终:0 BTC(2140年左右)
交易手续费:
- 用户支付给矿工
- 激励矿工打包交易
- 随着区块奖励减少,手续费越来越重要
4.5 挖矿的竞争
竞争过程
1. 所有矿工都在挖同一个区块
2. 不断计算哈希值
3. 谁先找到符合条件的哈希值,谁就挖到区块
4. 获得奖励
5. 其他矿工接受这个区块,开始挖下一个区块
算力的作用
算力:计算哈希值的能力。
单位:
- H/s(哈希/秒)
- KH/s(千哈希/秒)
- MH/s(兆哈希/秒)
- GH/s(吉哈希/秒)
- TH/s(太哈希/秒)
算力越大:
- 计算速度越快
- 找到符合条件的哈希值的概率越高
- 挖到区块的概率越高
但:
- 算力大 ≠ 一定挖到
- 还有运气成分
- 长期来看,算力大的矿工挖到的区块更多
第五部分:最长链规则和分叉
5.1 什么是分叉?
定义:分叉是区块链出现两个或多个分支的情况。
分叉的原因
原因1:两个矿工同时挖到区块
场景:
- 区块100已经被挖出
- 矿工A挖出了区块101A
- 矿工B挖出了区块101B
- 两个区块都有效
结果:
- 网络分叉
- 一部分节点看到区块101A
- 一部分节点看到区块101B
原因2:网络延迟
场景:
- 矿工A挖出区块101
- 广播到网络
- 但矿工B还没收到
- 矿工B也挖出区块101(不同的区块)
结果:
- 网络分叉
- 不同节点看到不同的区块
5.2 最长链规则
规则
最长链规则:所有节点都选择最长的链。
工作原理
场景:
- 区块100已经被挖出
- 矿工A挖出区块101A
- 矿工B挖出区块101B
- 网络分叉
过程:
1. 矿工C在区块101A后面挖出区块102A
2. 链A:100 → 101A → 102A(长度3)
3. 链B:100 → 101B(长度2)
4. 链A更长,所有节点选择链A
5. 放弃链B
为什么选择最长链?
原因1:最长链代表最多的工作量
链A:3个区块 = 3倍工作量
链B:2个区块 = 2倍工作量
链A的工作量更多,更可信。
原因2:防止攻击
如果攻击者要攻击:
- 需要比整个网络更多的算力
- 需要挖出更长的链
- 成本极高,几乎不可能
原因3:保证一致性
所有节点都选择最长链:
- 网络达成一致
- 避免分歧
- 保证数据一致性
5.3 分叉的处理
临时分叉
描述:两个矿工同时挖到区块,网络暂时分叉。
处理:
- 等待下一个区块
- 看哪条链更长
- 选择最长链
- 放弃较短链
结果:
- 分叉很快解决
- 网络恢复一致
- 较短链上的交易被回滚
软分叉
描述:协议升级,新节点和旧节点都接受。
特点:
- 向后兼容
- 旧节点可以继续运行
- 新功能逐步启用
硬分叉
描述:协议升级,新节点和旧节点不兼容。
特点:
- 不向后兼容
- 旧节点必须升级
- 可能分裂成两条链(如比特币和比特币现金)
5.4 6个确认的意义
什么是确认?
定义:确认是你的交易所在的区块后面,又挖出了多少个区块。
例子:
区块100:包含你的交易
区块101:1个确认
区块102:2个确认
区块103:3个确认
...
区块106:6个确认
为什么需要6个确认?
原因1:防止分叉回滚
如果只有1个确认:
- 你的交易在区块100
- 如果出现分叉,区块100可能被放弃
- 你的交易可能被回滚
如果有6个确认:
- 你的交易在区块100
- 后面有5个区块
- 即使出现分叉,也很难回滚6个区块
- 交易几乎不可能被回滚
原因2:防止双重支付
攻击者要双重支付:
1. 发送交易A(给你)
2. 在另一条链上发送交易B(给自己)
3. 如果交易A只有1个确认,可能被回滚
4. 如果交易A有6个确认,几乎不可能被回滚
原因3:提高安全性
6个确认 = 大约60分钟
- 攻击者需要控制51%算力
- 需要挖出6个区块
- 成本极高,几乎不可能
确认数的选择
不同场景需要不同的确认数:
- 小额交易:1-3个确认
- 中等交易:3-6个确认
- 大额交易:6+个确认
一般建议:
- 比特币:6个确认
- 以太坊:12个确认(因为出块更快)
第六部分:比特币网络如何工作?
6.1 P2P网络
什么是P2P网络?
定义:P2P(Peer-to-Peer)网络是点对点网络,没有中心服务器。
特点:
- 所有节点都是平等的
- 没有中心服务器
- 节点直接通信
比特币网络
结构:
节点1 ←→ 节点2
↕ ↕
节点3 ←→ 节点4
↕ ↕
节点5 ←→ 节点6
特点:
- 每个节点连接到多个其他节点
- 形成网状结构
- 没有单点故障
6.2 节点发现
新节点如何加入网络?
步骤1:连接到已知节点
新节点启动时:
- 连接到一些已知的节点(硬编码的种子节点)
- 或者从DNS服务器获取节点列表
步骤2:获取更多节点
连接到已知节点后:
- 请求其他节点的地址
- 连接到更多节点
- 逐步扩展连接
步骤3:保持连接
连接到多个节点后:
- 保持连接
- 定期交换节点信息
- 如果节点断开,连接新节点
6.3 交易传播
交易如何传播?
步骤1:创建交易
用户创建交易:
- 用私钥签名
- 包含输入和输出
- 准备广播
步骤2:广播交易
用户广播交易:
- 发送到连接的节点
- 节点验证交易
- 如果有效,继续广播
步骤3:网络传播
交易在网络中传播:
- 节点收到交易
- 验证交易
- 如果有效,广播给其他节点
- 很快传播到整个网络
步骤4:进入内存池
交易传播后:
- 进入每个节点的内存池(Mempool)
- 等待矿工打包
- 矿工选择交易打包到区块
6.4 区块同步
区块如何同步?
步骤1:挖到区块
矿工挖到区块:
- 计算符合条件的哈希值
- 创建区块
- 准备广播
步骤2:广播区块
矿工广播区块:
- 发送到连接的节点
- 节点验证区块
- 如果有效,继续广播
步骤3:网络同步
区块在网络中同步:
- 节点收到区块
- 验证区块
- 如果有效,接受区块
- 更新区块链
- 继续挖下一个区块
步骤4:处理分叉
如果出现分叉:
- 节点选择最长链
- 放弃较短链
- 网络恢复一致
6.5 节点类型
全节点(Full Node)
特点:
- 存储完整的区块链
- 验证所有交易
- 验证所有区块
- 不依赖其他节点
优势:
- 完全独立
- 可以验证所有数据
- 更安全
劣势:
- 需要大量存储空间(几百GB)
- 需要大量带宽
- 同步时间长
轻节点(Light Node / SPV Node)
特点:
- 只存储区块头
- 不存储完整交易
- 依赖全节点查询
- 使用SPV(Simplified Payment Verification)
优势:
- 存储空间小
- 同步快
- 适合移动设备
劣势:
- 依赖全节点
- 不能完全验证
- 安全性较低
挖矿节点(Mining Node)
特点:
- 必须是全节点
- 参与挖矿
- 创建区块
- 获得奖励
要求:
- 需要大量算力
- 需要大量电力
- 需要专业设备
第七部分:总结和思考
7.1 核心概念回顾
通过本章学习,你应该理解:
-
比特币要解决什么问题
- 依赖银行的问题
- 需要信任的问题
- 无法自主的问题
-
比特币交易如何工作
- UTXO模型
- 交易结构
- 数字签名
-
区块链如何防止篡改
- 区块链接
- 每个区块包含前一个区块的哈希
- 修改任何区块,后面的都会不匹配
-
如何达成共识
- 工作量证明
- 通过计算证明工作量
- 最长链规则
-
网络如何工作
- P2P网络
- 去中心化
- 节点平等
7.2 关键理解
理解1:UTXO模型
- 不是账户余额,而是未花费的交易输出
- 必须完全花费,然后找零
- 这是理解比特币交易的关键
理解2:工作量证明
- 不是浪费,而是必要的安全机制
- 通过计算成本防止攻击
- 这是去中心化共识的基础
理解3:最长链规则
- 不是随意选择,而是选择最多工作量的链
- 保证网络一致性
- 防止攻击
理解4:去中心化
- 不是技术炫技,而是解决根本问题
- 不依赖单一机构
- 提高安全性和自主性
7.3 思考题
-
为什么比特币用UTXO模型而不是账户模型?
- 思考:UTXO模型的优势是什么?
- 思考:账户模型的劣势是什么?
-
为什么需要工作量证明?
- 思考:能否不用工作量证明?
- 思考:工作量证明解决了什么问题?
-
最长链规则为什么是安全的?
- 思考:攻击者要攻击需要什么?
- 思考:为什么攻击成本极高?
-
如果两个矿工同时挖到区块会怎样?
- 思考:网络如何达成一致?
- 思考:交易会被回滚吗?
-
为什么需要6个确认?
- 思考:1个确认够吗?
- 思考:6个确认如何提高安全性?
7.4 下一步
完成本章学习后,你应该:
- 理解比特币如何工作
- 理解UTXO模型
- 理解工作量证明
- 理解最长链规则
下一章:我们将深入理解共识机制的原理,包括51%攻击、拜占庭将军问题等。
附录:实践练习
练习1:理解UTXO模型
任务:分析一个真实的比特币交易
步骤:
- 打开区块链浏览器(blockchain.info)
- 找一个交易
- 分析交易的输入和输出
- 理解UTXO的使用
观察:
- 输入来自哪些交易?
- 输出创建了哪些新的UTXO?
- 找零是如何处理的?
练习2:查看区块结构
任务:查看一个真实的比特币区块
步骤:
- 打开区块链浏览器
- 找一个区块
- 查看区块头
- 查看交易列表
观察:
- 区块头包含什么?
- 前一个区块的哈希是什么?
- Merkle根是什么?
- 包含多少笔交易?
练习3:理解挖矿过程
任务:模拟挖矿过程
代码:
import hashlib
import time
def mine_block(previous_hash, transactions, difficulty):
"""
模拟挖矿过程
"""
nonce = 0
target = "0" * difficulty # 难度目标
print(f"开始挖矿...")
print(f"难度目标: {target}")
print(f"前一个区块哈希: {previous_hash}")
start_time = time.time()
while True:
# 构建区块头
block_header = f"{previous_hash}{transactions}{nonce}"
# 计算哈希
hash_value = hashlib.sha256(block_header.encode()).hexdigest()
# 检查是否满足难度
if hash_value[:difficulty] == target:
elapsed_time = time.time() - start_time
print(f"\n挖矿成功!")
print(f"随机数: {nonce}")
print(f"哈希值: {hash_value}")
print(f"用时: {elapsed_time:.2f}秒")
print(f"尝试次数: {nonce + 1}")
return nonce, hash_value
nonce += 1
# 每10000次显示进度
if nonce % 10000 == 0:
print(f"尝试次数: {nonce}, 当前哈希: {hash_value[:20]}...")
# 测试
previous_hash = "0000000000000000000000000000000000000000000000000000000000000000"
transactions = "tx1,tx2,tx3"
difficulty = 4 # 难度:前4位必须是0
mine_block(previous_hash, transactions, difficulty)
运行结果:
开始挖矿...
难度目标: 0000
前一个区块哈希: 0000000000000000000000000000000000000000000000000000000000000000
尝试次数: 0, 当前哈希: 5d41402abc4b2a76b...
尝试次数: 10000, 当前哈希: 8f434346648f6b96d...
...
挖矿成功!
随机数: 12345
哈希值: 0000abc123def456...
用时: 2.34秒
尝试次数: 12346
观察:
- 难度越高,需要尝试的次数越多
- 这是"工作量"的体现
- 实际挖矿需要尝试数万亿次
学习检查清单
完成本章学习后,检查你是否理解:
- 比特币要解决什么问题?
- UTXO模型是什么?如何工作?
- 比特币交易的结构是什么?
- 如何防止双重支付?
- 区块的结构是什么?
- 区块链如何链接?
- 为什么区块链不可篡改?
- 什么是工作量证明?
- 挖矿的过程是什么?
- 为什么需要难度调整?
- 什么是分叉?
- 最长链规则是什么?
- 为什么需要6个确认?
- 比特币网络如何工作?
- 节点类型有哪些?
如果以上问题你都能回答,说明你已经理解了比特币的工作原理,可以进入下一章了!