# 区块链技术
Table of Contents
复习材料,不建议阅读
第一章 概述
1.1 什么是区块链技术
1.1.1 比特币与区块链的诞生
区块 (Block) 一词指代一个包含了数据的基本结构单元(块),而链 (Chain) 则代表了由区块产生的哈希链表。
区块链技术是一种按照时间顺序将数据区块以顺序相连的方式组合成链式数据结构,并以密码学方式保证不可篡改和不可伪造的分布式账本技术。
三要素:交易、区块、链。
1.1.2 比特币与区块链
先驱:e-Cash、e-gold、Hashcash、B-money
2008/10/31 中本聪发表了比特币白皮书。
区块链是比特币的底层技术.是比特币的核心与基础架构。
区块链不仅仅是比特币。
1.1.3 区块链的特点
- 去中心化
- 透明性
- 不可篡改性
- 多方共识
1.1.4 智能合约与世界计算机
- “智能合约”概念的提出远早于区块链,最早由计算机科学家、密码学专家 Nick Szabo 提出。
- 设想将现实世界中的合约、契约等概念引入数字领域,约束参与数字金融各方的行为,使违反规定者受到惩罚。
- 在 Vitalik Buterin 的创意中,通过区块链技术,人们可以很好地实现智能合约的约束条件,而不用依赖外部力量。智能合约的概念逐渐向”区块链上运行的计算机程序”转变。
- 通过在区块链系统中引入智能合约和编程逻辑,人们可以将自定义的执行逻辑放置到区块链上运行,而不只是简单的交易转账。
- 由于区块链的特性,链上的计算机程序会伴随着区块被分发到以太坊系统中的各个参与者的手上。这样一来,整个以太坊系统便是一个随着系统运行永不停歇的智能合约分布式平台,可以看成是一台去中心化的计算机。Vitalik Buterin 将其称为世界计算机(World Computer)。
- 智能合约和以太坊的出现是区块链技术发展的里程碑事件。伴随着智能合约的到来,区块链系统的应用更加丰富,其实用性也进入了一个新的阶段。
- 博彩、游戏、代币等基于智能合约的应用不断涌现,智能合约越发成为区块链系统中不可或缺的重要组成部分。它给区块链系统的使用者一定的自由发挥空间来实现自定义的特殊功能,也使得区块链系统真正成为一个基础的底层架构。
1.1.5 区块链的分类
- 公有链
- 私有链
- 联盟链
1.2 区块链技术的现状
1.2.1 区块链的应用
公有链
- 比特币:加密数字资产代表,PoW共识,总量约2100万枚;区块1MB限制,3~7 TPS,交易速度瓶颈;存在价格波动、算力浪费等问题。
- 以太坊:Vitalik Buterin提出,2015年上线;图灵完备智能合约平台,吞吐量约15~20 TPS;经历数次分叉,引入PoS共识机制。
联盟链
- 将区块链与数字货币剥离,面向企业级应用。
- Hyperledger项目(Linux基金会2015年启动):Hyperledger Fabric提供分布式账本,支持权限控制、通道隔离、可插拔共识(SOLO/Kafka/SBFT)。
应用领域
- 金融、供应链、物联网、司法存证、政务公开等需要多方互信、数据安全的场景。
产业现状
- 2018年中国区块链公司达448家,产业初步形成规模。
1.2.2 区块链的挑战
技术层面
- 效率问题:比特币约3~7 TPS,难以满足日常支付;联盟链吞吐量提升有限。
- 共识机制问题:难以兼顾安全性与效率,部分机制存在逻辑漏洞,且大量哈希计算浪费算力。
- 数据冗余问题:每个节点存储完整账本,数据冗余随链增长而增大。
- 安全问题:智能合约漏洞频发,The DAO事件损失约6000万美元。
法律层面
- 匿名化问题:难以监管追踪,易被用于非法交易和绕过外汇管制。
- 欺诈问题:庞氏骗局、虚假区块链项目利用信息不对称骗取投资。
- 冲击铸币权:加密货币挑战法定货币地位,可能威胁国家经济稳定。
1.2.3 区块链技术的发展环境
全球布局
- 美国:国土安全部、NIST、NSF等提供资金支持;至少8州制定区块链立法;纳斯达克用区块链记录私募证券交易;MIT、斯坦福等开设区块链课程,MIT试点用区块链签发毕业证。
- 欧洲:22国签署区块链合作伙伴声明;欧洲央行持开放态度。
- 亚洲:日本承认比特币合法地位,FSA推动银行间区块链信息共享;韩国三星SDS、高丽大学推动区块链研究。
- 中国:清华、北大、浙大等高校开设课程并成立研究中心;“十三五”规划将区块链列为战略性前沿技术;杭州建全国首个区块链产业园及百亿创新基金;2019年中共中央政治局就区块链发展进行第十八次集体学习。
课后习题
核心知识点
- 比特币创世区块诞生于2009年
- 联盟链(许可链)需要授权才能加入,公有链无准入门槛
- 比特币创始人:Satoshi Nakamoto(中本聪);Vitalik 是以太坊创始人
- 去中心化系统代表:以太坊;支付宝、微信、银行均为中心化系统
- 命名最早:智能合约(Nick Szabo 提出)→ 区块链 → 比特币
- 底层技术:P2P网络、密码学、共识算法、分布式存储等
简答题要点
- 交易:数字资产转移记录;区块:打包交易的容器;链:哈希指针链接的区块序列
- 分类对比:公有链(完全开放)、联盟链(多主体授权)、私有链(单一组织内部)
- 中心化系统弊端:单点故障风险、数据易被篡改、依赖第三方信任、透明度低
第二章 比特币
2.1 比特币简介
- 2008/10/31,中本聪发表论文《比特币:一种点对点的电子货币系统》。
- 2009/1,中本聪挖出创世区块,首批50个比特币诞生。
- 比特币宣告了加密数字货币的诞生:去中心化、交易匿名、公开透明分布式账本、不可篡改。
- 区块链作为底层技术,不仅用于加密货币,更在供应链金融、智能物流、物联网等领域解决安全与信任问题。
2.2 基础知识
2.2.1 哈希算法
- 区块链应用中的哈希函数特点:单向不可逆、抗碰撞。
- 比特币采用 SHA2-256(SHA256)算法,用于挖矿和生成地址。
- 以太坊采用 SHA3 族的 Keccak-256 算法。
2.2.2 非对称加密
略
2.2.3 数字签名
略
2.2.4 主网与测试网
- 主网(Mainnet):正式的比特币网络,流通的比特币具有真实经济价值,是比特币的主要网络,代表了比特币系统。
- 测试网(Testnet):独立的测试网络,测试币无实际经济价值,容易获取;用于开发测试客户端、交易脚本及新特性,比本地私链更接近主网环境。
- Regtest(Regression Test):本地私有测试网络,仅本地节点,性质与测试网类似,用于本地功能测试。
2.3 交易
区块链系统中账户(地址)之间货币的转移通过交易实现。
- 两种账户模型:UTXO(比特币为代表)和账户状态转移(以太坊为代表),交易结构不同。
- 比特币采用UTXO模型,用户余额通过未花费交易输出表示。
- 交易结构分为输入(Input)和输出(Output):输入表示比特币来源,输出表示去向;输入和输出本身是不可分割的整体,尽管金额可以细分。
- 类比借据交易:Alice 将借据所有权转让给 Bob,原借据作废,Bob 获得新借据。
- 比特币交易中,全网参与者共同充当公证人,密码学原理充当具有法律效力的印章和签名。
2.3.1 交易简介
2.3.2 输出
- 交易输出表示这笔交易的比特币最终由谁持有。
- 一个交易可包含多个输出,支持同时向多个地址转账。
输出结构
| 字段 | 类型 | 大小 | 说明 |
|---|---|---|---|
| nValue | 64位无符号整型 | 8字节 | 输出中的比特币数量,单位:聪(satoshi),1 BTC = 100,000,000 satoshi |
| scriptPubKey长度 | 变长无符号整型 | 1~9字节 | 锁定脚本的长度 |
| scriptPubKey | 字节串 | 不定 | 锁定脚本,用于对输出上锁;只有持有对应私钥的地址才能生成正确的解锁脚本,使用该笔比特币 |
2.3.3 输入
- 交易输入必须引用并解锁一个已完成的前序交易输出,比特币不能凭空产生。
- 一个交易可以包含多个输入,可引用多个前序交易的输出以凑足转账金额。
输入结构
| 字段 | 类型 | 大小 | 说明 |
|---|---|---|---|
| prevout哈希值 | 哈希值 | 32字节 | 所引用前序交易的哈希值 |
| prevout索引 | 无符号整型 | 4字节 | 前序交易输出在该交易中的位置索引 |
| scriptSig长度 | 变长无符号整型 | 1~9字节 | 解锁脚本的长度 |
| scriptSig | 字节串 | 不定 | 解锁脚本,用于证明对该输出拥有支配权,通常由用户私钥生成 |
| nSequence | 无符号整型 | 4字节 | 序列号,用于部分解锁功能(如时间锁) |
2.3.4 UTXO模型
- UTXO(Unspent Transaction Output):未花费的交易输出,是比特币账户余额的真实体现。
- 交易输出一旦被花费,即使原始交易记录仍存在,该输出也不能再使用。
- 用户余额 = 所有可被该用户解锁的未花费交易输出(UTXO)之和。
- 比特币是”数字签名链”,任意比特币可通过逐层交易签名确认追溯到创世区块。
- 最新交易接收人通过验证输出锁定脚本来确认所有权。
比特币交易数据结构
| 字段 | 类型 | 大小 | 说明 |
|---|---|---|---|
| nVersion | 整数 | 4字节 | 交易版本号,用于功能升级 |
| vIn数量 | 变长无符号整型 | 1~9字节 | 交易输入个数 |
| vIn | 数组 | 不定 | 所有输入,按顺序排列 |
| vOut数量 | 变长无符号整型 | 1~9字节 | 交易输出个数 |
| vOut | 数组 | 不定 | 所有输出,按顺序排列 |
| nLockTime | 无符号整型 | 4字节 | 时间锁定时间戳,用于定时锁定交易 |
2.4 脚本系统
2.4.1 锁定与解锁
- 交易合法性验证:解锁脚本(输入脚本 scriptSig) + 锁定脚本(输出脚本 scriptPubKey) 共同执行,返回
True则交易有效。 - 执行顺序:先执行解锁脚本,再执行锁定脚本。
- 运行环境:比特币基于栈式虚拟机执行脚本。
Alice → Bob → Cathy 转账流程
Alice to Bob 输出脚本: <Bob公钥> OP_CHECKSIG (把币"锁"到Bob公钥上)
Bob to Cathy 解锁脚本: <Bob签名> 输出脚本: <Cathy公钥> OP_CHECKSIG验证过程
- Bob 对交易哈希用私钥签名,签名放入解锁脚本
- 节点合并执行:解锁脚本(签名入栈)+ 锁定脚本(公钥入栈 → OP_CHECKSIG)
- OP_CHECKSIG 验证签名是否匹配公钥,返回
True则验证通过
本质
- 锁定脚本附带公钥 = 智能合约:凡持有对应私钥签名的交易均可花费该 UTXO
- 脚本语言由解释器执行,支持条件判断等逻辑
2.4.2 常见脚本类型
| 类型 | 锁定脚本(输出) | 解锁脚本(输入) | 关键栈操作 | 特点 |
|---|---|---|---|---|
| P2PK | <公钥> OP_CHECKSIG | <签名> | 签名入栈 → 公钥入栈 → OP_CHECKSIG 验证 | 最直接方式,但公钥暴露 |
| P2PKH | OP_DUP OP_HASH160 <公钥哈希> OP_EQUALVERIFY OP_CHECKSIG | <签名> <公钥> | 签名入栈 → 公钥入栈 → OP_DUP 复制公钥 → OP_HASH160 求哈希 → 与存储的公钥哈希比对 → OP_EQUALVERIFY → OP_CHECKSIG | 更安全(公钥不直接暴露)、手续费更低;最常用 |
| P2SH | OP_HASH160 <脚本哈希> OP_EQUAL | < redeemScript > <解锁参数...> | 解锁脚本入栈 → 锁定脚本验证脚本哈希匹配 → redeemScript 反序列化执行 | 灵活委托支付,常用于多重签名 |
| Null-Data | OP_RETURN <数据> | 不可花费 | 执行 OP_RETURN 立即返回 False,输出标记为假UTXO | 用于存证、数据存储、币销毁证明 |
2.4.3 多重签名钱包
- 基本作用:n个人共同管理一笔钱,至少m个人同意才能花费(m-of-n)。
- 实际应用中通常通过 P2SH 实现。
以2-of-3多重签名为例( RedeemScript 逻辑)
OP_PUSHNUM_2 # m=2,至少需2人签名<公钥1> # 3人中第1人的公钥<公钥2> # 3人中第2人的公钥<公钥3> # 3人中第3人的公钥OP_PUSHNUM_3 # n=3,共3人可签名OP_CHECKMULTISIG # 检查栈顶是否有m个有效签名完整验证流程(P2SH)
| 步骤 | 脚本 | 操作 | 栈状态 |
|---|---|---|---|
| 1 | 解锁脚本 | OP_0 <签名1> <签名2> <RedeemScript> 入栈 | 0、签名1、签名2、RedeemScript |
| 2 | 锁定脚本 | OP_HASH160 <脚本哈希> OP_EQUAL | 验证RedeemScript哈希匹配 |
| 3 | RedeemScript执行 | 反序列化后执行:OP_PUSHNUM_2 <pk1> <pk2> <pk3> OP_PUSHNUM_3 OP_CHECKMULTISIG | 提取签名与公钥,验证m-of-n |
关键特性
- 比特币脚本不是图灵完备的,不支持循环等复杂操作。
- 智能合约通过代码在各节点独立执行、区块链保证共识难以篡改。
- 以太坊项目正是为支持图灵完备智能合约而产生。
2.5 公私密钥与地址
2.5.1 私钥
- 区块链系统无中心化权威保存”用户名-密码”映射,地址由私钥通过密码学直接生成。
- 比特币采用 椭圆曲线非对称加密(ECDSA)。
- 私钥:32字节(256位) 随机整数,取值范围
[1, n-1],其中 n 为椭圆曲线阶。 - 私钥是确认UTXO所有权的 唯一凭证,代表地址中比特币的使用权,必须严格保密,一旦泄露,比特币将被他人控制。
2.5.2 公钥
- 公钥通过私钥在特定椭圆曲线(secp256k1)上乘以固定基点(Generator Point)得到,为一对坐标值 (x, y)。
- Raw格式(非压缩):65字节,前缀
0x04+ 64字节十六进制坐标(x、y各32字节)。 - 压缩格式:33字节,前缀
0x02(y为偶数)或0x03(y为奇数)+ 32字节x坐标(利用曲线性质只需保存x及y的奇偶性)。 - 私钥 → 公钥为单向计算(椭圆曲线乘法不可逆),从公钥无法反推私钥。
2.5.3 普通地址
- 普通地址(Legacy Address):对应 P2PKH 脚本类型,是最常用的比特币地址格式。
- 生成步骤:
- 公钥 → SHA256 哈希
- SHA256 结果 → RIPEMD160 哈希(得到20字节)
- RIPEMD160 结果 → 两次 SHA256 → 取前4字节作为校验和
- 主网前缀
00(1字节)+ RIPEMD160 哈希(20字节)+ 校验和(4字节)→ 组成25字节地址
- 地址结构:前2位
00表示主网,中间20字节为公钥哈希值,末尾4字节用于校验公钥正确性。 - 最终25字节结果经 Base58 编码(见 2.5.4)得到可读地址。
2.5.4 Base58编码
略
2.5.5 其他地址
地址类型与前缀对照表
| 地址类型 | 十六进制前缀 | Base58 首字符 | 说明 |
|---|---|---|---|
| P2PKH(公钥哈希) | 00 | 1 | 普通地址(Legacy Address) |
| P2SH(脚本哈希) | 05 | 3 | 用于多重签名等脚本 |
| WIF私钥(未压缩) | 80 | 5 | 未压缩公钥对应私钥 |
| WIF私钥(压缩) | 80 | K / L | 压缩公钥对应私钥 |
| 测试网 P2PKH | 6F | m / n | 测试网公钥哈希地址 |
| 测试网 P2SH | C4 | 2 | 测试网脚本哈希地址 |
| 测试网私钥 | EF | 9 / c | 测试网私钥 |
| Bech32(SegWit) | — | bc1 | 隔离见证地址,采用Bech32编码 |
2.6 区块与链
- 交易需验证执行后由全网节点达成共识确认,解决双花等冲突问题。
- 为防冲突交易被同时确认,设置确认门槛(如PoW),节点竞争确认权。
- 批量打包交易形成区块(Block),减少系统开销。
- 区块包含上一个区块的哈希引用,形成单向哈希链表,即区块链(Blockchain)。
- 区块由**区块头(Header)和区块体(Body)**组成:区块头存元信息,区块体存放交易等详细数据。
2.6.1 区块
- 区块是区块链账本的”一页”,记录一批交易并完成一次集体确认。
- 区块由**区块头(Header)和区块体(Body)**组成:
- 区块头:包含该区块的所有元信息(如版本号、前一个区块哈希、Merkle根、时间戳、难度目标、Nonce等)。
- 区块体:存放交易等详细数据(如交易列表)。
区块结构图
graph TD
A[区块 Block] --> B[区块头 Header]
A --> C[区块体 Body]
B --> B1[版本号 Version]
B --> B2[前一个区块哈希 Prev Block Hash]
B --> B3[Merkle 根 Merkle Root]
B --> B4[时间戳 Timestamp]
B --> B5[难度目标 Bits]
B --> B6[Nonce]
C --> C1[交易计数器]
C --> C2[交易列表 Transactions]
C2 --> T1[交易1]
C2 --> T2[交易2]
C2 --> T3[...]
C2 --> Tn[交易n]2.6.2 区块头
- 区块头是区块的摘要,用于在网络间传输,体积小、效率高。
- 不存放交易详情,只存储交易列表的Merkle根哈希。
区块头数据结构
| 字段 | 大小 | 说明 |
|---|---|---|
| nVersion | 4字节 | 区块版本号 |
| hashPrevBlock | 32字节 | 前一个区块的哈希值(链接成链) |
| hashMerkleRoot | 32字节 | 本区块交易列表的Merkle根哈希 |
| nTime | 4字节 | 区块产生时间戳 |
| nBits | 4字节 | 难度目标(Bits编码) |
| nNonce | 4字节 | 随机数,用于PoW寻找满足难度的区块 |
Nonce的作用
- 区块其他字段固定时,哈希值不变,无法满足难度门槛。
- 通过调整 Nonce,矿工可”凑出”满足难度条件的区块哈希。
2.6.3 Merkle树
- 区块头通过Merkle根哈希来校验区块体中所有交易的完整性。
- 比特币采用Merkle树(Ralph Merkle, 1979年提出)计算交易列表哈希,是一种二叉树结构。
构建过程
- 叶子节点:对每笔交易计算哈希值
- 中间节点:对左右子节点哈希值两两配对,计算上层哈希(
H(h左 || h右)) - 逐层向上,直到得到唯一的Merkle根
三大优点
| 优点 | 说明 |
|---|---|
| 篡改检测 | 任意交易改动会导致从该交易到根路径上所有哈希值变化,最终Merkle根不匹配 |
| 增量计算 | 数据项变化时,只需重新计算受影响节点的哈希,无需全量重算 |
| 轻节点验证(Merkle证明) | 轻节点只需存储区块头,验证某笔交易是否存在时,只需提供该交易到根的路径哈希(Merkle分支),无需下载全部交易 |
轻节点验证示意
需要验证交易T4提供路径: H(T3), H(H12), H(根)轻节点: H(T4) → H(H34) → H(H1234) = 区块头中的Merkle根?2.6.4 区块链
- 每个区块包含前一个区块的哈希引用(通过区块头中的
hashPrevBlock),形成单向哈希链表。 - 链的起点是创世区块(Genesis Block),从创世区块到当前区块的数目称为区块高度(Height)。
- 篡改任意中间区块会导致该区块哈希值剧烈变化,与后续区块的引用冲突,必须逐个重算后续所有区块。
- 由于每个区块产生都有难度要求(PoW),篡改成本随区块高度指数级增加,保证了区块链的不可篡改性。
区块链结构示意
graph LR
G[创世区块<br>Height=0] --> B1[区块1<br>Height=1]
B1 --> B2[区块2<br>Height=2]
B2 --> B3[区块3<br>Height=3]
B3 --> BN[...<br>Height=n]
B2 -.->|篡改| B2X[篡改区块2<br>哈希值变化]
B2X -.->|冲突| B3X[需重算区块3]
B3X -.->|冲突| B4X[需重算区块4...]2.7 共识
- 共识机制:区块链节点就交易确认和区块打包达成一致意见的过程。
2.7.1 PoW
- 工作量证明(Proof of Work, PoW):区块哈希值必须满足一定难度条件(如前N位为0)。
- Nonce:区块头中可动态调整的4字节随机数,矿工通过穷举不同 Nonce 寻找满足难度的区块哈希。
- 哈希函数的单向性决定了无法从目标哈希逆推 Nonce,只能暴力尝试。
- 挖矿过程类似”幸运大抽奖”:代价是计算时间/资源,奖品是打包区块的权利。
- 区块奖励:成功打包区块的矿工获得新发行的比特币奖励 + 交易手续费,这是比特币的唯二来源。
- 在哈希函数随机、矿工足够多的情况下,找到有效 Nonce 的期望时间与难度正相关。
PoW示意
目标: 区块哈希前2位为0 (难度=2)尝试 Nonce=0x12345678 → H = 0x12AB... (前两位不是0) ✗尝试 Nonce=0x00ABCD → H = 0x00EF... (前两位是0) ✓ 找到!2.7.2 分叉
- 分叉(Fork):两个矿工几乎同时产生两个合法区块,导致区块链出现两条合法分支。
- 分叉原因:
- 难度过低 → 出块速度过快 → 多矿工同时出块
- 网络通信延迟 → 新区块传播不及时 → 部分矿工不知道新区块而继续挖矿
- 分叉导致双花风险:同一 UTXO 在不同分支上被不同交易花费。
分叉示意
graph TD
A[区块N] --> B[区块N+1-A]
A --> C[区块N+1-B]
B --> D[区块N+2-A...]
C --> E[区块N+2-B...]2.7.3 算力与难度调整
- 哈希算力:全网单位时间内可进行的哈希计算次数,随矿工增加/机器性能提升而提高。
- 难度调整:比特币每2016个区块(约两周)调整一次,使平均出块时间稳定在10分钟。
- 实际出块时间 < 10分钟 → 难度上调(算力增加)
- 实际出块时间 > 10分钟 → 难度下调(算力减少)
- 难度与前序区块产生时间挂钩,所有矿工对难度调整无分歧。
2.7.4 最长链原则
- 最长链原则:分叉时,节点选择累计工作量最大的(最长的)链作为有效链。
- 矿工在更短链上挖矿的区块更难被全网认可,因此会切换到最长链继续挖矿。
- 51%攻击:攻击者若要篡改历史区块,必须在该区块后产生比当前合法链更长的链,需掌握全网51%以上算力。
课后习题
核心知识点
- 比特币交易模型:UTXO(未花费交易输出)
- 防止双花:维护UTXO表,确保同一输出只能被花费一次
- 区块大小限制:1MB(隔离见证后约2MB等效)
- 所有权证明:私钥是唯一凭证,拥有私钥即可控制对应地址的比特币
- 签名机制:用私钥签名,用公钥验证
- 分叉处理:采用最长链原则,选择累计工作量最大的链
- 锁定脚本字段:scriptPubKey
- 比特币主要密码算法:ECDSA、SHA256、RIPEMD160;不包含 RSA、SM2、AES、TEE
- 加密账户机制由非对称密钥技术建立
- 私钥丢失 = 资产永久丢失,无法重置或恢复
- 理论上至少1个矿工即可维持网络运行
- 难度调整:每2016区块(约两周)调整一次,控制平均出块时间在10分钟
- 编码系统:采用Base58编码提升可读性
- 用户余额通过UTXO(未花费交易输出)表示
简答题要点
- 区块头信息:nVersion(版本)、hashPrevBlock(前区块哈希)、hashMerkleRoot(Merkle根)、nTime(时间戳)、nBits(难度)、nNonce(随机数)
- 哈希算法:单向不可逆、抗碰撞;常见如SHA256、RIPEMD160
- 数据透明性:所有交易公开可查;不可篡改性:篡改需重算后续所有区块,成本随高度指数增加
- 单签名钱包:1把私钥控制;多签名钱包:m-of-n,需m人签名才能花费
- 交易结构:输入(prevout引用 + scriptSig解锁脚本)+ 输出(nValue金额 + scriptPubKey锁定脚本)
- 脚本类型:P2PK、P2PKH、P2SH、Null-Data
- Merkle树作用:校验交易完整性、支持轻节点验证(Merkle证明)
- 主网与测试网区别:主网币有真实价值,测试网币无价值仅用于测试
- 时间戳作用:记录出块时间,用于难度调整计算
- 私钥→公钥→地址:私钥通过ECDSA生成公钥,公钥经SHA256+RIPEMD160+Base58编码生成地址
第三章 以太坊
3.1 以太坊简介
3.1.1 以太坊的诞生
- 比特币开创区块链先河,但后续项目(莱特币、点点币、门罗币)可扩展性有限,无法支持多种使用场景的自定义数字资产。
- 比特币脚本语言图灵不完备,不足以构建高级去中心化应用。
- 2013年,19岁的 Vitalik Buterin 提出以太坊设计思想:内置图灵完备编程语言,允许将区块链拓展到更多应用场景。
- 2014年,以太坊基金会成立,开始项目研发。
- 2015年7月,以太坊网上线,开启智能合约时代。
- 用户可以基于公共区块链平台开发 分布式应用(DApp) 及发布代币,使区块链商业应用成为可能。
- 以太币(Ether)成为继比特币之后的第二大加密数字货币。
- 未来规划:增加分片技术、新一代虚拟机 Ewasm,向更安全、更持久的去中心化平台发展。
3.1.2 以太坊与比特币对比
相同点
- 均为公有链平台,节点对等无特权,均可发起/验证交易,数据公开透明、不可篡改。
- 均通过矿工打包交易、全网广播和共识机制达成分布式账本一致性。
不同点
| 维度 | 比特币 | 以太坊 |
|---|---|---|
| 技术特点 | 仅支持比特币流通,脚本语言图灵不完备 | 支持智能合约,图灵完备;账户模型实时保存状态;Gas机制限制合约执行 |
| 账户模型 | UTXO模型 | 账户模型(Address + State) |
| 共识机制 | PoW(SHA256) | 初期Ethash(PoW),后逐步转向PoS(Casper)+ 分片 |
| 叔块奖励 | 无 | 有,未被纳入主链的区块也能获得奖励,对矿工更友好 |
| 抗ASIC | 无专门设计 | Ethash依赖内存,降低强算力矿机优势,减少矿池攻击风险 |
| 社区生态 | 相对保守,版本迭代慢 | 活跃,GitHub 2000+开源项目,积极拥抱变化 |
3.1.3 以太坊的特色与应用
- 以太坊开启区块链 2.0时代,以智能合约为核心的”可编程金融”。
- 交易不只是加密货币转账,还可以是智能合约的创建和调用。
智能合约
- 本质:一段可根据预先指定条件被触发执行的代码。
- 以太坊提供 EVM(以太坊虚拟机) 作为执行环境,支持图灵完备的高级语言(Solidity 最常用)。
- 合约部署后生成合约账户,用户通过发送交易并指定函数/参数来调用合约。
- 执行过程和结果通过全网共识确认,随区块存储在链上,不可篡改。
核心应用场景
| 场景 | 说明 |
|---|---|
| 溯源存证 | 利用区块链不可篡改、公开透明、分布式存储特性,解决纸质/中心化存储易丢失、易伪造问题(如发票、物流溯源) |
| 数字资产发行与流通 | 智能合约支持自定义数字资产(积分、股权、游戏币等),在用户间自由流通 |
| 数据共享 | 利用多方验证、不可伪造特性,提供可信信息共享环境(征信黑名单、路况信息、联邦学习梯度共享等) |
| DApp | 目前多集中于金融交易、游戏等领域,如 MakerDAO、Uniswap、Axie Infinity 等 |
代表性 DApp
| 类别 | 代表项目 | 功能描述 |
|---|---|---|
| 金融 | MakerDAO | 去中心化借贷平台,采用 DAI 稳定币 + MKR 治理代币双币模式,累计交易额超 20 亿美元 |
| 金融 | Uniswap | 去中心化代币交换协议(AMM) |
| 金融 | Synthetix | 去中心化合成资产平台 |
| 广告 | Brave/BAT | 基于区块链的数字广告平台,保护用户隐私,用代币奖励用户和内容商 |
3.2 以太坊基本架构及原理
- 以太坊是一个分布式状态机,而非单纯的分布式账本。
- 所有账户、余额、智能合约代码、合约状态等统称为状态(State)。
- 状态转换函数:
Y(S, T) = S',给定旧状态 S 和新交易集合 T,生成新状态 S’。 - EVM(以太坊虚拟机) 是所有节点独立执行状态转换代码的沙箱环境,使用 Gas 衡量计算成本。
- 状态存储在 梅克尔-帕特里夏树(MPT) 中,树根
stateRoot登记在区块头中,全网共识确认,分叉时可快速回滚。
基本架构三要素
| 组件 | 说明 |
|---|---|
| 区块链数据 | 前后相连的区块,每区块含区块头(含 stateRoot)和区块体(交易列表) |
| 智能合约 | 按预设逻辑改变以太坊状态的代码,存储在状态数据中,由交易触发执行 |
| 节点 | 独立维护区块链数据、执行智能合约、通过 P2P 网络通信、采用共识机制(PoS)达成全网状态一致 |
交易执行流程(以”张三买电影票”为例)
1. 交易产生 → 广播到网络2. 各节点独立读取智能合约代码和状态,在 EVM 中执行3. 执行结果(余额变化、余票变化等)写回状态4. 区块中包含执行后的 stateRoot,全网共识确认5. 若节点执行结果与其他节点不符(被篡改),则无法参与后续共识分叉处理对比
| 维度 | 比特币(UTXO模型) | 以太坊(状态模型) |
|---|---|---|
| 分叉回滚 | 重新计算回滚 UTXO 集合 | 需要回滚到分叉前的完整状态 |
| 效率 | 较高效 | 若无优化则开销巨大 |
| 解决方案 | 最长链原则 | 状态树独立于区块存储,通过 stateRoot 快速校验和回滚 |
状态存储优势
- 状态树(MPT)独立于区块链存在,仅将根哈希存入区块。
- 分叉时无需复制全部状态,只需验证 stateRoot 即可快速切换分支。
3.3 账户模型与转账
3.3.1 账户模型
- 比特币采用UTXO模型记录用户余额,以太坊采用更直观的账户模型(类似银行系统)。
- 账户记录保存在所有以太坊节点中,由全网共同维护,去中心化。
地址与账户
- 地址是用户的身份标识,账户代表该地址对应的信息(如以太币余额)。
- 以太坊无中心化权威保存”用户名-密码”映射,通过非对称密码学进行认证和控制。
地址生成
- 私钥 → 公钥(ECDSA,secp256k1曲线)→ Keccak256 哈希 → 取最后 40位(20字节) 作为以太坊地址。
- 以太坊地址为42字符十六进制字符串,带
0x前缀(如0x238661F085A338F04B0C7C956A796B57018151F0)。
账户结构
- 地址(Address):20字节,唯一标识账户。
- 余额(Balance):账户持有的以太币数量,最小单位为 Wei,1 ETH = 10^18 Wei。
- Nonce:记录该地址发起的交易次数(从0开始),每确认一笔交易后 Nonce +1,用于防重放和排序。
3.3.2 转账
- 以太坊转账通过交易实现,格式类似日常转账:
From: Alice, To: Bob, value: 1 ETH。 - 交易经 Alice 私钥签名,节点验证签名有效性后执行:
- Alice 账户余额 -1 ETH
- Bob 账户余额 +1 ETH
- 若交易被篡改,签名验证失败,节点可识别并拒绝。
3.3.3 Nonce
- 防重放攻击:若没有 Nonce,同一笔已签名交易可被无限次重新提交。Nonce 确保每笔交易只能执行一次。
- 交易确认后,账户 Nonce +1,原交易 Nonce 失效。
- 节点仅接受 Nonce 与账户当前 Nonce 匹配的交易。
- 控制交易顺序:Nonce 严格递增,确保交易按发起顺序执行。
- 撤销功能:可通过提交相同 Nonce 的新交易(覆盖旧交易)实现一定程度的撤销。
3.4 智能合约
3.4.1 状态模型
- 以太坊账户模型最大优点:简单,无需维护大量 UTXO 数据,可方便扩展实现智能合约。
- 账户余额通过地址上的账户数据表示;转账交易改变发起者和接收者的余额。
- 抽象:余额 → 状态,转账 → 状态变换规则。只要变换规则固定无歧义,相同初始状态 + 相同变换过程 = 相同结果。
- 状态模型是账户模型的扩充,原账户模型只是状态模型的有限子集(状态 = 余额,变换原语 = 转账)。
3.4.2 智能合约简介
- 智能合约是一段在区块链上执行的代码,依托区块链系统在参与者之间实现对执行的一致认可。
- 智能合约通过交易驱动,执行过程和结果全网共识确认。
核心特性
- 确定性(单射):相同输入必须得到相同输出,合约中不能包含随机数等非确定性逻辑。
- 自包含:合约代码和状态存储在链上,由交易触发执行。
账户类型
| 类型 | 说明 |
|---|---|
| 外部账户(EOA) | 由私钥控制,可发起交易,地址由公钥生成 |
| 合约账户 | 由代码控制,无私钥,地址由创建者地址 + Nonce(或创建者地址 + 初始化值 + 代码哈希)计算生成 |
合约账户结构
| 字段 | 说明 |
|---|---|
| 地址 | 20字节,非由公钥生成 |
| 余额 | 合约持有的 ETH |
| Nonce | 合约创建其他合约的次数 |
| 合约代码 | 机器码形式存储在合约机器码字段 |
| 合约存储 | 键值映射表,账户内只存存储表的哈希值 |
合约账户(Contract Account)
以太坊存在两种账户类型:外部账户(EOA) 和 合约账户。
| 特性 | 外部账户(EOA) | 合约账户 |
|---|---|---|
| 控制方式 | 由私钥控制 | 由代码控制(无私钥) |
| 地址生成 | 公钥 → Keccak256 → 取后20字节 | 创建时通过算法计算生成 |
| 能否发起交易 | 可以 | 不能直接发起交易,只能被外部账户调用后执行内部交易 |
| 代码存储 | 无代码 | 存储合约字节码 |
| 状态存储 | 仅余额 | 余额 + 合约存储(键值映射) |
| Nonce含义 | 已发送交易数 | 已创建合约数 |
合约账户的本质
- 合约账户是一段智能合约代码在链上的实例化对象,由创建交易部署时生成。
- 一旦部署,合约代码永久存储在链上,不可篡改。
- 合约账户的”所有者”是代码本身,而非某个用户。
合约账户结构
| 字段 | 说明 |
|---|---|
| 地址 | 20字节,创建时计算得出 |
| 余额 | 合约当前持有的 ETH 数量 |
| Nonce | 该合约创建其他合约的次数 |
| 合约代码 | 编译后的 EVM 字节码,存储在链上 |
| 合约存储 | 键值对映射表(storage),账户内只存整个存储树的哈希值(storageRoot) |
合约存储详解
- 合约存储是一个持久的键值映射表,每个键值对为 32字节键 → 32字节值。
- 存储数据按 slot(槽位)编号,如
0x0、0x1、0x2…,具体映射由合约代码决定。 - 账户的
storageRoot是该存储树的 Merkle Patricia Trie 根哈希,任何存储变更都会改变此哈希。
合约账户的执行
- 合约账户不能主动发起交易,只能由外部账户(EOA)或其他合约调用触发。
- 调用时,EVM 加载该合约的字节码,在沙箱环境中执行,可修改自身存储或向其他账户发送 ETH。
- 合约调用其他合约时,会产生内部交易(message call),不记录在区块交易列表中,但会消耗 Gas。
合约地址生成
- CREATE:
Keccak256(RLP(创建者地址, Nonce))取最后20字节,不可预测。 - CREATE2:
Keccak256(0xff + 创建者地址 + 盐值 + Keccak256(代码))取最后20字节,可预测。
调用流程
- 外部账户发送交易到合约地址,
To字段为合约地址,Data字段包含函数选择器和参数。 - 函数选择器 =
Keccak256(函数名+参数类型)前4字节。 - 参数按 ABI 规范编码为32字节字,前面补零。
3.4.3 驱动智能合约
- 智能合约的状态变化通过交易实现,每次运行由交易驱动。
合约调用交易
From: 外部账户地址To: 合约账户地址Value: 0(调用合约通常不转ETH)Data: 函数选择器(4字节) + 编码后的参数合约创建交易
From: 创建者地址To: 空地址(或0x)→ 以太坊识别为合约创建Data: 合约代码 + 初始化代码Gas 机制(解决停机问题)
- 智能合约是图灵完备的,可能存在死循环,而停机问题不可解。
- Gas 机制:每个 EVM 操作消耗一定 Gas,交易发起者预支付 Gas 上限。
- 执行过程逐步消耗 Gas,Gas 耗尽或执行完毕即停止,保证有限时间内终止。
- 类比:汽车燃油,燃油有限则行驶时间有上限。
EVM(以太坊虚拟机)
- 256位栈虚拟机:数据宽度为256位,执行基于栈结构,所有指令操作栈顶数据。
- 开发者使用 Solidity/Vyper 等高级语言编写,编译成 EVM 字节码后上链执行。
- 所有节点独立在 EVM 中执行合约代码,确保全网执行结果一致。
3.5 以太坊交易
3.5.1 交易内容
- 以太坊交易承载账户转账、合约创建和调用等功能,数据内容比比特币复杂。
- 交易本质上是一个签名数据包,由发送者私钥签名,全网广播。
交易字段
| 字段 | 说明 |
|---|---|
| From | 交易发送者地址,由签名推导得出,交易数据本身不存储 |
| To | 交易接收者地址;转账时为接收地址;创建合约时为 0x0(空地址);调用合约时为合约地址 |
| Value | 转账金额,单位 Wei(1 ETH = 10^18 Wei) |
| Data | 交易附带数据;创建合约时包含合约代码和构造函数;调用合约时包含函数选择器和参数 |
| Nonce | 发送者累计发出的交易数量,用于区分同一账户的不同交易及顺序 |
| GasPrice | 发送者为每个 Gas 单位支付的 ETH 价格,用于计算手续费 |
| GasLimit | 该交易允许消耗的最大 Gas,防止死循环无限消耗资源 |
| Hash | 交易内容的哈希值,作为交易 ID |
| v, r, s | ECDSA 签名参数,由发送者私钥对交易哈希签名生成,用于验证合法性 |
注意
- 交易本身不携带时间戳,智能合约通常使用区块时间戳(
block.timestamp)作为执行时的时间参考。 - 交易原始报文中不包含 Hash 和 From,因为 Hash 可从交易内容计算得出,From 可从签名推导得出。
3.5.2 交易费用
- Gas 机制不仅保证合约能停机,还对交易执行成本进行归一化计算。
- Gas 是 EVM 操作的基础资源单位,每步操作(计算、存储等)消耗一定 Gas。
Gas 核心概念
| 概念 | 说明 |
|---|---|
| Gas | 资源消耗基础单位 |
| GasLimit | 允许消耗的最大 Gas(用户预设上限) |
| GasUsed | 执行后实际消耗的 Gas(实时计算) |
| GasPrice | 每个 Gas 单位支付的 ETH 价格 |
手续费计算
手续费 = GasUsed × GasPrice- 基础交易 Gas(如转账为 21000)+ EVM 运行时消耗 Gas = GasUsed
- 若 GasUsed > GasLimit,交易执行失败,已消耗 Gas 不退还(状态回滚,但 Gas 已消耗)
- 手续费从发送者账户扣除,支付给矿工/验证者
Gas 定价争议
- EVM 操作定价由社区开发者决定,合理性常受质疑。
- Gas 机制需平衡:准确测量资源消耗 + 去中心化网络中易于达成共识。
- 以太坊社区通过 EIP 持续调整优化 Gas 定价。
3.5.3 交易的周期
以太坊交易在网络中的生命周期分为四个阶段:
graph LR
A[1. 发起] --> B[2. 广播]
B --> C[3. 打包与执行]
C --> D[4. 验证与执行]1. 发起
- 用户在钱包软件中填写:From、To、Value、Data、GasPrice 等。
- 钱包自动计算 GasLimit 和 Nonce,使用私钥签名,序列化后发送到以太坊节点。
2. 广播
- 节点收到交易后验证:签名有效性、余额是否充足、Nonce 是否正确。
- 验证通过后加入交易池(Mempool),并通过 P2P 网络广播给相邻节点。
- 交易池容量有限,按 GasPrice 排序(通常优先打包高手续费交易)。
3. 打包与执行
- 矿工/验证者从交易池中选择交易打包进候选区块。
- 按交易类型分别执行:
- 创建合约交易(To = 0x0):EVM 根据 From + Nonce 生成合约地址,执行 Data 中的代码,存储合约字节码
- 调用合约交易(To = 合约地址):EVM 加载合约字节码,执行 Data 中的函数调用
- 普通转账交易(To = EOA):直接调整 From 和 To 的余额
- 每笔交易执行后生成交易回执(Receipt),包含合约地址、GasUsed、事件日志(Log)等。
- 打包完成后,区块广播到网络。
4. 验证与执行
- 未获得记账权的节点收到区块后,独立验证并重新执行所有交易。
- 验证内容包括:签名、余额、Nonce、状态根哈希等。
- 确保全网对执行结果达成一致,维护去中心化共识。
注意
- 交易原始报文不包含 Hash 和 From,前者可计算,后者可从签名推导。
- Nonce 保证交易顺序,解决 P2P 网络乱序到达问题。
- EIP-1559 机制对 Gas 计费进行了更新,但本书不做过多叙述。
3.6 数据结构与存储
3.6.1 区块与叔块
- 以太坊区块同样分为区块头和区块体。
- 区块体包含:交易列表、收据列表(交易执行结果)、叔块列表(未入主链的合法区块)。
- 区块头增加:收据列表哈希、叔块列表哈希、状态根(stateRoot)、额外数据(≤100KB)。
世界状态(World State)
- 以太坊使用状态模型,所有账户(EOA + 合约账户)的状态汇总称为世界状态。
- 世界状态包含每个账户的:地址、余额、Nonce、合约代码(若有)、合约存储(若有)。
- 状态根(stateRoot)是世界状态的 Merkle Patricia Trie 根哈希,存储在区块头中,代表交易执行后的全局状态快照。
叔块(Uncle Block)
- 叔块是指不在主链但被主链区块引用的合法区块,因出块稍晚或网络延迟未能入主链。
- 叔块设计目的:在缩短出块时间的同时,维护区块链的安全性和矿工积极性。
- 主链区块引用叔块后,叔块获得部分区块奖励(激励矿工),引用叔块的区块也获得额外奖励。
- 引用叔块的区块在难度计算上有优势,提高矿工纳入叔块的积极性(GHOST 协议)。
收据(Receipt)
- 收据是交易执行结果的中间状态数据,包含:GasUsed、事件日志(Log)、合约地址(若为创建合约交易)等。
- 收据不包含在区块交易数据中,节点可根据交易独立重新执行生成,保存收据仅为方便查询。
- 收据也通过 MPT 组织,形成收据树,收据根哈希存储在区块头中。
3.6.2 Merkle Patricia Trie
- 以太坊使用 Merkle Patricia Trie(MPT) 作为核心数据结构,用于组织世界状态、交易列表和收据列表。
- MPT 结合了默克尔树(快速哈希证明)和压缩前缀树(高效索引)的优点。
为什么需要 MPT?
- 比特币 Merkle 树适用于交易列表(连续索引),但不适用于以太坊账户映射表(键为160位地址,空间巨大)。
- 直接计算所有账户的哈希开销巨大;MPT 允许在少量账户变更时快速重新计算根哈希。
MPT 构建过程
1. 压缩前缀树(Radix Tree)
- 以公共前缀组织数据的字典树,日常查字典类似。
- 以太坊地址为十六进制字符串(40字符),使用
0~9, a~f共16个字符作为分支单元(半字节 nibble)。 - 共同前缀组成子树,向下逐层细分,避免空节点浪费空间。
2. 添加 Merkle 哈希
- 在压缩前缀树基础上,对每个节点计算哈希值:
- 叶子节点:
H(空前缀 + 账户数据)或H(空前缀 + 存储数据) - 中间节点:
H(前缀 + 子分支哈希值列表),空分支用空值填充
- 叶子节点:
- 逐层向上计算,最终得到唯一的根哈希。
三类 MPT
| MPT 类型 | 键(Key) | 值(Value) | 说明 |
|---|---|---|---|
| 状态树(State Trie) | 账户地址(20字节) | 账户详细信息(余额、Nonce、代码哈希、存储根) | 全局状态,每个区块一个 |
| 合约存储树(Storage Trie) | 存储槽位(32字节) | 存储值(32字节) | 每个合约账户独立一棵 |
| 交易树/收据树(Transaction/Receipt Trie) | 交易/收据在区块中的索引(序号) | 交易/收据数据 | 每个区块一棵,序号连续,MPT 退化为16叉Merkle树 |
MPT 优点
- 高效索引:可根据地址快速查找账户。
- 快速重算:修改少量账户状态后,只需重新计算受影响路径的哈希,无需全量计算。
- 哈希证明:可生成 Merkle 证明,验证某账户/交易/收据是否属于某状态/区块。
3.6.3 布隆过滤器
- 布隆过滤器用于检索某值是否存在于一个集合中,以可接受的误识别率换取极高的空间效率和时间效率。
- 在以太坊中,布隆过滤器用于对收据的日志(Log)进行索引,方便轻节点快速查询特定事件。
原理
- 使用多个不同的哈希函数将键值映射到位图(Bit Array)中。
- 插入时:对键值计算多个哈希,将对应位图位置置为1。
- 查询时:对查询键值计算相同哈希,若所有对应位均为1,则可能存在(可能误判);若任一对应位为0,则必定不存在。
特点
| 特性 | 说明 |
|---|---|
| 空间效率 | 远高于普通哈希表,不存储实际数据,仅需位图 |
| 时间效率 | 插入和查询均为 O(k),k 为哈希函数数量 |
| 误识别率 | 存在假阳性(False Positive),但无假阴性(False Negative) |
| 不可删除 | 标准布隆过滤器不支持删除元素 |
以太坊中的应用
- 每个收据的日志包含主题(Topics)和数据(Data)。
- 对日志地址和主题计算布隆过滤器,结果存入收据的
bloom字段。 - 区块头中聚合所有收据的布隆过滤器,形成区块级布隆过滤器。
- 轻节点可通过区块布隆过滤器快速判断某事件是否可能存在于某区块,无需下载全部收据。
- 若布隆过滤器判断”可能存在”,再向全节点请求 Merkle 证明进行验证。
3.7 课后题
核心知识点
- EVM 是256位栈虚拟机(数据宽度256位,基于栈结构执行)
- 序列化方法:RLP(Recursive Length Prefix,递归长度前缀编码)
- Nonce:账户累计发出的交易数量,用于区分同一账户的不同交易及顺序
- 以太坊地址:20字节(40位十六进制),由公钥经 Keccak256 取最后20字节生成,几乎不可能重复
- MPT 使用16叉压缩前缀树作为地址到账户的索引
- 地址与身份无关,由公钥生成,匿名性(无需身份信息)
- 交易发出后,可通过发送相同Nonce的新交易(覆盖)实现撤销,或更高手续费加速
- 创建合约时向 空地址(0x0) 发送交易
- 以太坊记账由矿工/验证者完成(去中心化网络)
- 交易字段中用于区分同一用户不同交易的标记:Nonce
- 以太坊通过布隆过滤器对收据日志进行高效查询
- 以太坊创新:智能合约(图灵完备)
- 限制交易最大Gas消耗的参数:GasLimit
- 不在主链但被主链引用的合法区块:叔块(Uncle Block)
- 保证智能合约有限时间内终止的机制:Gas机制
- 外部账户由私钥控制
- 合约账户字段:Nonce、余额、合约代码、存储根(storageRoot)
- EVM主要作用:执行智能合约代码,保证全网执行结果一致
简答题要点
- 交易主要信息:From、To、Value、Data、Nonce、GasPrice、GasLimit、Hash、v/r/s签名
- EVM:以太坊虚拟机,256位栈虚拟机,执行智能合约字节码
- 状态根(stateRoot):世界状态的MPT根哈希,代表交易执行后的全局状态快照,用于快速校验和分叉回滚
- 三棵树:状态树(账户状态)、交易树(交易列表)、收据树(交易执行结果)
- Nonce区别:账户Nonce记录已发送交易数;区块Nonce是PoW挖矿时的随机数
- 共同点:公有链、节点对等、交易透明不可篡改、共识机制
- 不同点:UTXO vs 账户模型、图灵不完备 vs 图灵完备、PoW(SHA256) vs Ethash/Casper、有无叔块奖励
- 交易反悔:发送相同Nonce的新交易覆盖(提高GasPrice),原交易失效;已确认交易无法撤销
- 交易周期:发起 → 广播 → 打包与执行 → 验证与执行
- 叔块作用:缩短出块时间、维护矿工积极性、通过GHOST协议提高安全性
- EOA与合约账户区别:EOA由私钥控制、可发起交易、地址由公钥生成;合约账户由代码控制、无私钥、地址由创建者地址 + Nonce计算生成
第四章 区块链网络层
- 区块链网络层包含:组网方式、消息传播机制、数据验证机制。
- 通过 P2P 组网方式和特定协议,为区块链提供开放、对等的底层环境。
4.1 P2P网络
- P2P(Peer-to-Peer):节点彼此对等,同时扮演客户端和服务器的角色,直接交换资源和服务,无需经过中间实体。
- 为何区块链采用 P2P:
- 可扩展性:节点越多,系统资源和服务能力越强
- 健壮性:无单点故障,部分节点离线不影响整体运行
- 负载均衡:资源分布在多个节点上
- 去中心化:节点共同维护区块链,符合区块链设计理念
四种拓扑结构
| 拓扑类型 | 特点 | 代表 | 优缺点 |
|---|---|---|---|
| 中心化拓扑 | 中心索引服务器提供地址索引,文件传输P2P | Napster | 查询高效,但中心服务器易故障 |
| 全分布式非结构化拓扑 | 无中心,随机图组织,洪泛(Flooding)广播 | Gnutella | 快速查找,但可能广播风暴 |
| 全分布式结构化拓扑 | 基于DHT(分布式哈希表),精准定位 | Kademlia(以太坊采用) | 可扩展性好,精准查询,但维护复杂 |
| 半分布式拓扑 | 超级节点集群,簇内中心化,簇间P2P | eDonkey、BitTorrent | 易管理,但依赖超级节点 |
4.1.1 中心化拓扑
- 第一代P2P网络,由中心索引服务器 + 多个客户端节点构成。
- 中心索引服务器保存接入节点地址信息,提供地址索引服务。
- 案例:Napster 音乐共享软件
- 优点:维护简单,查询高效复杂,资源发现率高,文件传输不经过中心服务器节省带宽
- 缺点:扩展性有限,中心服务器故障导致全网瘫痪
4.1.2 全分布式非结构化拓扑
- 无中心索引服务器,节点拥有真正的对等关系。
- 采用随机图组织形式,利用 洪泛(Flooding) 进行数据广播。
- 节点将消息向邻居转发,直到所有节点收到或 TTL(Time To Live)耗尽。
- 案例:Gnutella
- 优点:快速找到源节点到目标节点的路径,快速消息传播
- 缺点:可能广播风暴,网络规模扩大时广播数据急剧增加,低带宽节点过载失效
4.1.3 全分布式结构化拓扑
- 采用 DHT(Distributed Hash Table,分布式哈希表) 实现网络寻址和存储。
- 将存储网络中所有资源信息的哈希表划分成不连续小块,分散存储在多个节点上。
- 每个节点维护部分哈希表,对象名/关键词通过哈希函数映射为128/160位哈希值。
- 案例:Kademlia(以太坊采用)、Chord、Pastry
- 优点:自适应节点加入/退出,均匀分配节点ID,精准查询,健壮性和可扩展性好
- 缺点:仅支持精准关键词匹配,不支持模糊语义查询;维护机制复杂,节点频繁变动造成网络波动
4.1.4 半分布式拓扑
- 综合中心化拓扑和非结构化拓扑的优点。
- 将性能较高的机器作为超级节点(Super Node),每个超级节点存储部分节点的文件信息,维护地址和文件索引。
- 超级节点之间形成高速转发层,与普通节点形成自治簇,簇内采用中心化拓扑。
- 案例:eDonkey、BitTorrent
- 优点:易管理,消除网络拥塞隐患,性能和可扩展性兼顾
- 缺点:对超级节点依赖较大,易受攻击,容错性受影响
4.2 比特币网络
- 比特币基于全分布式非结构化拓扑,节点对等,无特权节点和索引服务器。
- P2P协议建立在TCP之上,此外还有Stratum等扩展协议。
- 扩展比特币网络:包含P2P协议、矿池挖矿协议、Stratum协议等的完整网络结构。
4.2.1 节点类型及其功能
按数据内容划分
| 类型 | 区块链数据 | 交易验证 | 说明 |
|---|---|---|---|
| 全节点(Full Node) | 完整区块链 | 独立验证 | 矿工需运行全节点 |
| 归档节点(Archival Node) | 修剪后数据 | 独立验证 | 删除无意义区块数据,减少磁盘使用 |
| 轻节点(Lightweight Node) | 仅区块头 | 依赖SPV验证 | 启动快,可在移动设备上运行 |
按功能划分
| 节点类型 | 钱包 | 矿工 | 完整存储 | 网络路由 |
|---|---|---|---|---|
| 核心客户端(Bitcoin Core) | ✓ | ✓ | ✓ | ✓ |
| 全节点 | ✗ | ✗ | ✓ | ✓ |
| 独立矿工 | ✗ | ✓ | ✓ | ✓ |
| 轻量级钱包 | ✓ | ✗ | ✗ | ✓ |
SPV(简易支付验证)
- 轻节点仅保存区块头,通过Merkle证明验证交易是否存在。
- 流程:区块头同步 → 寻找交易所在区块 → 获取Merkle分支 → 计算并比对Merkle根 → 根据确认数判断有效性。
- 隐私风险:SPV节点选择性读取交易可能被第三方监控;通过Bloom过滤器保护隐私。
4.2.2 扩展比特币网络
- 扩展比特币网络 = P2P协议 + 矿池挖矿协议 + Stratum协议 + 其他连接组件协议。
扩展节点类型
| 节点类型 | 说明 |
|---|---|
| 矿池协议服务器 | 作为比特币网络与矿池节点的网关路由 |
| 挖矿节点 | 轻量级节点,依赖矿池服务器的全节点,运行Stratum协议 |
| 轻型Stratum钱包 | 运行Stratum协议,包含钱包功能 |
4.2.3 比特币节点通信
1. 节点发现
- DNS种子:客户端维护长期稳定运行节点(种子节点)列表,提供IP地址列表。
- -seednode命令:手动指定种子节点IP地址。
- 握手过程:节点A发送
version消息 → 节点B回复verack确认 → 建立连接。 version消息内容:协议版本、本地服务列表、当前时间、IP地址、区块高度等。
2. 地址管理
- tried列表:64个桶,每桶64个已成功连接的节点地址,保留最近连接时间戳。
- new列表:256个桶,每桶64个尚未连接的节点地址,30天未连接或多次失败则移除。
3. 全节点区块同步
- 握手时通过
version中的BestHeight判断哪方区块更多。 getblocks消息交换顶端区块哈希 →inv消息分批发送缺少区块哈希(每批500个)→getdata请求全区块数据。
4. SPV节点通信
- SPV节点使用
getheaders请求区块头(每次最多2000个)。 - 通过Bloom过滤器过滤交易集合,保护SPV节点隐私。
5. 加密和认证连接
- Tor网络(洋葱路由):多层加密+随机中继节点,保护匿名性和隐私。
- BIP-0150:P2P对等认证(公钥验证身份)。
- BIP-0151:对等体间协商加密通信。
- 认证流程:密钥交换 → 建立加密信道 → AUTHCHALLENGE → AUTHREPLY → 签名验证 → 授予访问权限。
6. 交易池
- 交易池(Transaction Pool):已发现但未确认的交易临时列表。
- 孤立交易池(Orphan Pool):父交易未知的交易暂存于此,父交易到达后移入交易池。
- UTXO池:包含所有已确认UTXO集合,初始化时已包含条目。
4.2.4 比特币中继网络
- 目的:最小化矿工间区块传播延迟,加速新区块广播。
- 原始中继网络(2015,Matt Corallo):托管在AWS上,连接大多数矿池,基于TCP。
- FIBRE(2016):替代原始网络,基于UDP + 前向纠错补偿数据包丢失,使用 紧凑块(Compact Blocks) 减少传输数据量和延迟。
- Falcon:传播区块的部分内容,节点无需等待完整区块。
- 本质:覆盖型网络,通过压缩数据、更换协议等方式提供高速块传输通道。
4.3 以太坊网络
- 以太坊采用全分布式结构化拓扑,基于 Kademlia(Kad) 分布式哈希表实现快速路由和数据定位。
- P2P网络完全加密,提供 UDP(节点发现)和 TCP(数据传输)两种连接方式。
4.3.1 Kademlia
- Kademlia(Kad):分布式哈希表技术,将所有信息作为哈希表条目分散存储在各节点上。
- 每个节点分配随机生成的160位节点ID。
- 网络表示为160层二叉树,节点位置由ID的最短唯一前缀确定。
节点距离计算
- 距离 = 两个节点ID的 异或(XOR) 结果,结果越小距离越近。
- 以太坊中:节点ID先经 SHA3 生成256位哈希码,距离为哈希码异或结果的最高位位数。
K-桶(K-Bucket)
- 每个节点维护256个K-桶,每桶存储k=16个节点信息(节点ID、endpoint、IP等)。
- 桶内按最近访问时间排序:最早访问在头部,最新访问在尾部。
- 更新规则:
- 已在桶中 → 移到尾部
- 桶未满 → 直接添加到尾部
- 桶已满 → ping头部节点,有响应则保留并忽略新节点,无响应则替换为新节点
节点查询
- 发起者从K-桶中选若干距离目标最近的节点,发送findNode异步请求。
- 收到请求的节点返回自己所知的最近节点。
- 发起者更新K-桶,向未请求过的最近节点继续查询。
- 重复直到前后两次查询结果相等(收敛)。
节点加入与退出
- 加入:获取任意已知节点信息 → 向其发送findNode → 递归构建路由表。
- 退出:无需特殊操作,节点不响应时自动从K-桶中删除。
4.3.2 节点类型与功能
- 以太坊节点同样分为全节点和轻节点(与比特币类似)。
- 以太坊2.0分片(Sharding):
- 将交易状态和历史划分为多个分片(如按地址前缀分片)。
- 每个分片存储和处理特定交易,有独立验证网络。
- 高级形式支持跨分片通信。
- 理论上提高吞吐量:每个节点只处理所在分片的交易。
4.3.3 以太坊节点通信
- 使用 discv4 协议实现节点发现,RLPx 协议实现加密通信。
- UDP 用于节点发现,TCP 用于数据传输。
discv4 节点发现
四种报文命令:
| 报文 | 说明 |
|---|---|
| ping | 探测对等节点是否在线 |
| pong | 响应ping报文 |
| findNode | 请求查询邻居节点 |
| neighbors | 回传找到的邻居节点列表 |
节点生命周期六种状态:
graph TD
A[发现状态] -->|发送ping 并收到pong| B[在线状态]
B -->|添加到K-桶| C[活跃状态]
C -->|桶满被新节点替代| D[候选状态]
D -->|发送ping 并收到pong| C
D -->|长时间无响应| E[不活跃状态]
E -->|规定时间无pong| F[死亡状态]RLPx 加密连接
- 实现完备前向安全性:每次连接使用不同密钥,现有密钥泄露不影响历史通信。
- 阶段1:密钥交换
- 每个节点生成随机密钥对
- 使用 ECDH 算法:
ECDH(A私钥, B公钥) = ECDH(B私钥, A公钥)= 共享密钥 - 随机数用于生成消息认证码,保证消息完整性
- 阶段2:身份认证与协议握手
- 交换 hello 报文(P2P版本号、端口号、节点ID等)
- 校验协议版本,版本不匹配则断开连接
区块同步流程
1. HandShake 握手连接2. 节点A发送交易信息(TxMsg)3. 节点B请求区块头(GetBlockHeadersMsg)→ 获取并存储4. 节点B依次请求区块体(GetBlockBodiesMsg)、收据(GetReceiptsMsg)、状态数据(GetNodeDataMsg)5. 新区块同步: - 被动同步:接收 NewBlockMsg 或 NewBlockHashesMsg - NewBlockMsg → 直接验证并存入本地 - NewBlockHashesMsg → 请求区块头和区块体后组装完整区块4.4 网络层安全
- 区块链的金融属性和数据公开、去中心化特性使其容易成为攻击目标。
- 信道安全是区块链网络安全的基础:若信道不安全,共识算法保障的一致性和正确性将被瓦解。
五种网络层攻击类型
| 攻击类型 | 攻击方式 | 目标 | 后果 |
|---|---|---|---|
| DDoS攻击 | 控制大批在线节点作为攻击放大平台 | 交易所、矿池、钱包 | 网络资源耗尽,竞争对手有效哈希率提升 |
| 延展性攻击 | 修改交易签名改变交易ID,广播新交易 | 交易队列 | 双重支付、浪费矿工验证时间 |
| 女巫攻击 | 广播多身份信息,非法拥有多个身份标识 | P2P网络数据冗余、投票机制 | 破坏冗余备份、不公平重复投票 |
| 路由攻击 | BGP劫持/拦截流量分割网络或延迟区块传播 | 区块链网络连通性 | 双重支付、计算能力浪费 |
| 日蚀攻击 | 侵占节点路由表,控制对外联系,隔离节点 | 单个节点 | 路由欺骗、资源搜索被劫持 |
4.4.1 分布式拒绝服务攻击
- DDoS攻击:利用客户端/服务器技术将多台计算机联合作为攻击平台,针对同一目标发动大量攻击请求。
- 传统DDoS需入侵主机建立僵尸网络;区块链DDoS只需在应用层控制大批在线节点作为放大平台。
- 主动攻击:主动向网络发送大量虚假索引信息,降低节点查找和路由性能。
- 被动攻击:修改客户端软件,被动等待查询请求,返回虚假响应。
- 案例:恶意矿工攻击竞争对手网络资源,消耗其时间和带宽,提高自己有效哈希率。
4.4.2 延展性攻击
- 利用外部虚假交易实现攻击,在不改变原交易内容的情况下阻塞交易队列。
- 交易延展性攻击:
- 攻击者侦听未确认交易 → 修改交易签名(改变交易ID)→ 广播新交易
- 原始交易方无法根据原交易ID查询确认信息
- 导致双重支付风险:攻击者可进行重复转账并蒙受损失。
4.4.3 女巫攻击
- 女巫攻击(Sybil Attack):一个攻击者节点向网络广播多个身份信息,非法拥有多个身份标识。
- 恶意行为:改变交易顺序、阻止交易确认、误导路由表、消耗连接资源。
- 破坏P2P网络数据冗余机制,使备份数据被欺诈地备份到同一节点上。
- 在投票机制中,利用伪造多个身份进行不公平重复投票,掌握网络控制权。
- 反女巫攻击:
- PoW:验证身份的计算能力,增加攻击成本
- 身份认证:新节点需经可靠第三方或所有可靠节点认证
4.4.4 路由攻击
- 网络路由不安全和ISP集中性,明文通信的区块链面临流量分析、信息窃听、丢弃、修改、注入和延迟风险。
两种类型
| 类型 | 攻击方式 | 后果 |
|---|---|---|
| 分割攻击 | BGP劫持拦截不同网络间流量,隔离区块链网络为两个子网,各子网无断网感知;合并后较短链被永久抛弃 | 区块和交易丢失、矿工收入损失 |
| 延迟攻击 | 拦截信息并简单修改,延迟区块传播速度 | 重复支付、计算能力浪费 |
4.4.5 日蚀攻击
- 日蚀攻击(Eclipse Attack):攻击者侵占节点路由表,控制节点对外联系,使其被隔离在虚假网络中。
- 已在比特币和以太坊网络中均被证实可实施。
比特币日蚀攻击
- 比特币节点最多接受117个入连接,最多向外发起8个出连接。
- 攻击者用攻击地址填充被攻击节点的tried列表,用非网络地址覆盖new列表。
- 被攻击节点重启后,所有出连接大概率连接到攻击者节点,同时攻击者占据入连接。
以太坊日蚀攻击
- 以太坊一个主机可运行多个ID节点,攻击者只需2个恶意节点即可实施。
- 独占连接攻击:节点重启时快速用入连接占满所有连接(已通过限制入连接数量修复)。
- 占有表攻击:向受害者节点重复发送findNode请求占据K-桶,使出连接指向攻击者,再用入连接占据剩余连接。
防御措施
- 监测节点状态和区块交付行为,将异常情况作为攻击早期指标触发保护措施。
- 对节点的连接数量、连接来源进行限制和验证。
4.5 课后题
核心知识点
- 删除一个区块只影响本节点,不会全网消失
- 以太坊网络节点发现采用 discv4 协议
- PBFT 不能抵御女巫攻击(PBFT解决的是拜占庭容错问题,非身份伪造)
- PoW 可防御女巫攻击(增加伪造身份的计算成本)
- 暴力破解攻击不属于网络层攻击(属于密码学攻击)
- 轻节点通过 SPV(简易支付验证) 方式验证支付
- 比特币网络基于全分布式非结构化拓扑
- 比特币中未确认交易的临时列表称为交易池(Transaction Pool)
- P2P网络四种拓扑:中心化、全分布式非结构化、全分布式结构化、半分布式
简答题要点
- 比特币与以太坊网络异同:均采用P2P、节点对等;比特币用全分布式非结构化拓扑(洪泛),以太坊用全分布式结构化拓扑(Kademlia DHT);以太坊完全加密(RLPx),比特币部分加密
- 矿池工作:矿机通过Stratum协议连接矿池服务器,矿池分配挖矿任务,矿机提交算力,矿池按贡献分配奖励
- 常见P2P拓扑:中心化(Napster)、全分布式非结构化(Gnutella/洪泛)、全分布式结构化(Kademlia/DHT)、半分布式(超级节点集群)
- 轻节点工作:仅存储区块头,通过SPV验证:同步区块头 → 获取Merkle分支 → 计算并比对Merkle根 → 根据确认数判断有效性
- 预防女巫攻击:PoW增加身份伪造成本、身份认证(可靠第三方认证新节点)
第五章 区块链共识层
- 区块链是分布式系统,每个节点有一份完整账本,天然抵抗 DDoS 攻击、解决单点故障。
- 核心难题:账本更新,即如何在去中心化、存在恶意节点的场景下维护全局一致账本。
- 区块链共识层:解决分布式一致性问题,让各节点账本在更新后保持一致的层级。
5.1 一致性问题
- 一致性问题是分布式领域最基础、最重要的问题。
- 若系统能实现”一致”,对外可呈现为一个独立的、完美的、可扩展的”虚拟节点”,被外界视为一个整体。
Rivest-Shamir-Adleman 转账例子
- Rivest 给 Shamir 转账 100 万美元(TX_RS),Shamir 给 Adleman 转账 100 万美元(TX_SA)。
- 若节点 A 先收 TX_RS 后收 TX_SA,账本为:Rivest:0 , Shamir:50 , Adleman:120 。
- 若节点 B 先收 TX_SA 后收 TX_RS,账本为:Rivest:0 , Shamir:150 , Adleman:20 。
- 两个账本不一致,说明一致性对分布式系统至关重要。
5.1.1 问题与挑战
分布式系统一致性面临四方面挑战:
| 挑战 | 说明 |
|---|---|
| 网络不可靠 | 消息延迟、乱序、出错、丢失 |
| 节点处理不可靠 | 处理时间无保障、结果可能错误、节点自身可能中断 |
| 节点恶意 | 恶意节点通过手段破坏系统一致性 |
| 同步调用代价大 | 简化设计但严重降低可扩展性,甚至退化为单点系统 |
常见方案背后的思想
- 收到交易先询问其他节点(同步调用避免冲突)→ 降低可扩展性
- 节点轮流决定交易顺序(令牌机制)→ 节点轮询
- 建立第三方机构排序 → 退化为单点系统
5.1.2 一致性要求
分布式系统达成一致性需满足:
| 要求 | 说明 | 对应性质 | 通俗表述 |
|---|---|---|---|
| 终止性(Termination) | 一致性过程在有限时间内能结束 | 活性(Liveness) | 好事总会发生 |
| 约定性(Agreement) | 不同节点最终完成决策的内容相同 | 安全性(Safety) | 坏事不会发生 |
| 合法性(Validity) | 结果必须是某个节点提出的提案 | 正确性(Correctness) | 共识结果有意义 |
重要性
- 终止性(活性):保证系统可用性,一致性过程不中断
- 约定性(安全性):算法要么不给出结果,要么任何结果必定是达成共识的,是区块链共识算法重点关注的
- 合法性(正确性):保证共识机制不会产生荒谬结果(如随意给所有账户增余额)
5.1.3 不同的一致性要求
一致性强度与性能权衡
- 越强的一致性要求往往造成越弱的处理性能和越差的可扩展性。
一致性分类
| 类型 | 要求 | 说明 |
|---|---|---|
| 线性一致性(强一致性) | 1. 任何一次读都能读到数据的最新写数据;2. 所有进程看到的操作顺序都和全局时钟下的顺序一致 | 需要准确计时设备(如原子时钟),成本高 |
| 顺序一致性 | 1. 每次读都能读到某个数据的最近一次写的数据;2. 所有进程看到的操作顺序一致且合理,无需和全局时钟顺序一致 | 较线性一致性弱,允许不同观察者视角 |
| 弱一致性(最终一致性) | 不保证任意时刻任意节点数据相同,但随时间的推移,不同节点上的同一数据总会达到一致状态 | 实现最简单,很多Web系统采用 |
最终一致性的变种
| 类型 | 说明 |
|---|---|
| 因果一致性 | 有因果依赖的操作(如进程A通知进程B)保证顺序,无依赖的可能看到旧值 |
| 读你所写一致性 | 进程自身写入后,后续读取一定能读到自己的新值(因果一致性的特例) |
| 会话一致性 | 读你所写一致性建立在某个会话中,会话终止后可能读出旧值 |
| 单调读一致性 | 进程读出某数据版本v后,后续读取不能读出比v更旧版本 |
| 单调写一致性 | 同一个进程的写操作单调递增,后续写操作在前序写操作完成后执行 |
组合使用
- 单调读和会话一致性可以组合使用
- 一致性强弱关系:线性一致性 ⊂ 顺序一致性 ⊂ 最终一致性 ⊂ 弱一致性
实际应用
- 强一致性系统实现难度大,很多场景采用最终一致性
- 谷歌Spanner采用基于原子时钟和GPS的方案,时间偏差控制在10ms以内
- 区块链共识(PoW)达成的是概率确定性共识:高度为h的区块在分叉中,但随着区块高度增长,发生变化的概率越来越小(比特币6个区块确认)
5.2 共识设计的理论限制
- 数学家喜欢先确定问题的最坏理论界限。对于共识问题,其最坏界限是:在任意情形下,分布式系统的共识问题无通用解。
- 即使网络通信可靠、设计得当,可扩展的分布式系统共识问题仍然无通用解法,这称为 FLP 不可能原理。
5.2.1 FLP 不可能原理
- FLP 不可能原理:即使在网络通信可靠的情况下,分布式系统的共识问题也无通用的解法。
- 具体表述:在网络可靠,但允许节点失效(即便只有一个)的最小化异步模型系统中,不存在一个可以解决一致性问题的确定性算法。
- 由 Fischer、Lynch、Paterson 于 1982 年证明发表。
核心含义
- 不要浪费时间设计一个在任意情形下都能实现共识的确定性算法。
- FLP 表明:在允许节点失效的情况下,纯粹的异步分布式系统无法保证一致性在有限时间内完成。
异步 vs 同步
| 传输模型 | 时钟误差 | 消息传输 | 判断消息丢失 |
|---|---|---|---|
| 同步(Synchronous) | 存在上界 | 确定时间内必到达(传输时间有上界且已知) | 容易判断 |
| 异步(Asynchronous) | 无上界,可能较大差异 | 不确定是否到达,可能丢失(传输时间无上界) | 无法判断(节点故障还是传输故障) |
通俗例子(四个投票者)
- 四个人分别在不同位置通过电话投票(同意/拒绝)。
- 某人投票后睡着了,其他人永远无法在有限时间内获知最终结果,因为不知道是对方没应答还是应答延迟。
- 重新投票后类似情形仍可能发生,共识过程永远无法完成。
FLP 的另一种表述
- 异步分布式系统不能同时保证活性和安全性:
- 活性:来自客户端的请求最终会被处理(好事总会发生)
- 安全性:处理请求后不存在不一致的状态(坏事不会发生)
- 必须在活性与安全性之间进行权衡折中。
两种折中方向
| 折中方向 | 代表算法 | 做法 | 代价 |
|---|---|---|---|
| 弱化活性 | PBFT | 将异步假设弱化为同步假设,安全性在异步网络中保证,但活性需要在同步模型中达成 | 网络变异步时可能永远不能完成请求 |
| 弱化安全性 | 比特币 PoW | 将异步假设弱化为同步假设,活性在异步网络中保证,但安全性是概率性的(可能分叉) | 会发生分叉,账本不一致;安全性依赖同步模型(10分钟内全网广播) |
Casper FFG
- 也是弱化安全性的类型,但实现的是确定性安全性而非概率性安全性。
5.2.2 CAP 原理
- CAP 原理:分布式系统不可能同时确保以下三个特性,设计中往往需要弱化对某个特性的保证:
- 一致性(Consistency):每次读操作都能得到最近写的结果或者返回错误
- 可用性(Availability):每次请求都能返回一个非错误结果,但结果不需要是最近写的结果
- 分区容忍性(Partition Tolerance):任意节点间的连接中断或大大延迟,系统仍然能够工作
核心观点
- 所有分布式系统都需要在网络分区的情况下继续工作,因此分区容忍性是必须满足的。
- 当网络分区发生时,必须在一致性和可用性之间选择:
- 侧重一致性(C+P):系统因网络分区不能保证数据最新时,返回错误或超时(如 PBFT)
- 侧重可用性(A+P):系统因网络分区不能保证数据最新时,返回查询分区最新的结果(如比特币 PoW)
常见误解
- CAP 原理不是在所有时间上都需要在三个性质中抛弃某一个。
- 如果没有发生网络分区,分布式系统正常运行,可以同时满足可用性和一致性。
区块链中的应用
| 区块链 | 侧重 | 表现 |
|---|---|---|
| 比特币(PoW) | 可用性 | 网络分区时仍能生成区块打包交易,但不同分区会出现分叉(账本不一致);分区消失后分叉收敛,一致性和可用性都能达到 |
| PBFT | 一致性 | 网络分区时若不能得到2/3投票,不能生成区块打包交易,不会出现分叉;分区消失后可用性恢复 |
5.3 区块链共识算法
- 区块链共识算法本质上是为了解决拜占庭问题(Byzantine Problem)。
- 拜占庭问题讨论的是:允许存在少数节点作恶(消息可能被伪造)场景下的一致性达成问题。
- 拜占庭容错(BFT) 算法讨论的是在拜占庭情况下系统如何达成共识。
5.3.1 拜占庭问题
1. 两将军问题
- 两将军问题(Two Generals Problem):两个将军通过信使达成进攻或撤退约定,但信使可能被拦截或迷路(信息丢失或伪造)。
- 根据 FLP 不可能定理,两将军问题无通用解。
2. 拜占庭问题
- 由 Leslie Lamport 等人于 1982 年提出。
- 拜占庭是古代东罗马帝国都城,守卫边境的多个将军(分布式系统节点)需要通过信使传递消息,对军事活动(提案)达成一致决定。
- 叛徒(恶意节点)会向不同将军传递不同消息,干扰共识达成。
- 求解条件:节点总数为 N,叛变将军数为 F,当 N ≥ 3F + 1 时,问题才有解。
- 例如:N=4, F=1;N=7, F=2
- 当 N < 3F + 1 时,拜占庭问题无解。
- 例如 N=3, F=1(3 < 3×1+1):忠诚将军无法达成一致,叛徒可发送相反消息造成混乱。
5.3.2 拜占庭容错算法
PBFT(实用拜占庭容错)
- 面向拜占庭问题的容错算法,解决在网络通信可靠但节点可能故障的情况下如何达成共识。
- 由 Leslie Lamport 等人提出,复杂度 O(N²),首次将 BFT 从指数级降至多项式级。
- 适用于联盟链,不适用于公有链的原因:
- 网络不稳定时延迟很高
- 基于投票机制,投票集合有限
- 通信复杂度 O(N²) 过高,节点数超过 100 时性能下降快
PBFT 基本概念
| 概念 | 说明 |
|---|---|
| 客户端(Client) | 发起请求的节点,在区块链中常与节点合一 |
| 主节点(Primary) | 提案发起者,负责生成新区块并广播 |
| 验证节点(Backup) | 提案投票者,验证区块并广播验证结果 |
| 视图(View) | 一个主节点 + 多个备份形成视图,不同视图主节点不同(轮换) |
| 编号(Sequence Number) | 提案的编号,在区块链中可理解为区块高度 |
| 检查点(Checkpoint) | 若编号 n 的提案收到 >2/3 确认,则称为检查点 |
PBFT 三阶段流程
| 阶段 | 说明 | 关键动作 |
|---|---|---|
| 预准备(Pre-Prepare) | 主节点收到客户端请求后构造消息并广播 | <PRE-PREPARE, v, n, d>,v=视图编号,n=序号,d=消息摘要 |
| 准备(Prepare) | 验证节点验证消息后广播 Prepare 消息 | 收到 2F+1 个 Prepare 确认后进入提交阶段 |
| 提交(Commit) | 节点收到 2F+1 个 Commit 消息后执行请求 | 执行完成后返回结果给客户端 |
日志压缩(检查点机制)
- 为避免日志无限增长,采用 检查点(Checkpoint) 机制。
- 每处理 K 个请求(如 100 个)后执行一次状态同步,广播检查点消息。
- 节点收到 2F+1 个检查点消息后,清除序号小于该检查点的日志。
视图切换(View Change)
- 当主节点失效或作恶、或超过 1/3 节点失效时,触发视图切换。
- 节点超时后广播
VIEW-CHANGE消息,新主节点收到 2F+1 个 VIEW-CHANGE 后广播NEW-VIEW,进入新视图。
PBFT 状态机
| 状态 | 说明 |
|---|---|
| 等待请求 | 所有节点初始状态,等待客户端请求 |
| 预准备 | 主节点处理请求并广播 PRE-PREPARE |
| 准备 | 验证节点验证并广播 PREPARE,等待 2F+1 确认 |
| 等待 2F+1 PREPARE | 收到后进入提交状态,否则进入视图切换 |
| 提交 | 收到 2F+1 COMMIT 后执行请求 |
| 视图切换 | 广播 VIEW-CHANGE,等待 2F+1 确认 |
关键思考
- 为什么容错性是 1/3?:N ≥ 3F+1,诚实节点数 N-F ≥ 2F+1 > F,保证少数服从多数。
- 为什么需要提交阶段?:仅两阶段会导致节点提前执行请求,视图切换时需重放,造成状态机非预期执行。
- 复杂度:O(N²),一般不超过 100 个节点。
5.3.3 比特币的工作量证明共识机制
- PoW 是解决拜占庭问题的新思路:在恶意节点算力不超过系统总算力 51% 的情况下解决拜占庭问题。
- PoW 容错阈值比 BFT 高,因为是通过争夺记账权而非合作投票解决问题。
PoW 流程
- 矿工打包区块,对区块头进行两轮 SHA256 哈希运算
- 哈希结果必须小于目标值(Target)(即区块哈希前 N 位为 0)
- 通过遍历 Nonce 寻找满足条件的哈希值
- 率先找到的矿工广播区块,其他节点验证 Nonce 是否满足难度要求
双花攻击
- 攻击者购买商品后,商家等待 y 个确认后发货。
- 攻击者同时在暗地制造分叉链(从交易所在区块高度开始),若算力足够大,分叉链长度超过主链。
- 攻击者收到货后广播分叉链,网络舍弃原主链采用分叉链,付费交易失效。
攻击成功概率
- 设诚实矿工算力比例为 p,攻击者算力比例为 q(p+q=1)。
- 攻击者在落后 z 个区块时追上的概率随确认数 y 增大呈指数级下降。
- 比特币通常取 y=6 个确认。
5.3.4 以太坊共识算法 Ethash
- 以太坊采用 PoW 共识机制,为抵抗 ASIC 矿机而设计。
- ASIC 矿机针对特定算法优化,算力远高于普通 CPU/GPU,提高参与门槛。
- Ethash 是 I/O 密集型工作量证明,要求大量内存访问,使 ASIC 矿机难以优化。
Ethash 算法要点
| 组件 | 说明 |
|---|---|
| 种子(Seed) | 根据区块高度生成,用于生成缓存 |
| 缓存(Cache) | 约 16MB,轻节点存储,用于生成数据集 |
| 数据集(Dataset) | 约 4GB(随时间增长),全节点存储,DAG 形式组织的随机数序列 |
| MixHash | 矿工从数据集抓取随机片段,通过 FNV 哈希混合 64 次得到的结果 |
| Nonce | 填充到区块头的随机值 |
挖矿流程
- 矿工根据区块高度生成种子,生成 16MB 缓存
- 全节点根据缓存生成 4GB 数据集(DAG),每 30000 区块(一个纪元)更新
- 矿工填充 Nonce → Keccak256 哈希 → 映射到数据集 → FNV 混合 64 次 → 得到 MixHash
- 用 MixHash + Nonce 再经 Keccak256 得到最终哈希,与目标值比较
- 满足条件则广播区块,其他节点用缓存验证(轻节点只需 16MB 缓存)
抗 ASIC 原理
- 需要频繁读取 4GB 数据集,内存带宽成为瓶颈
- ASIC 难以进一步优化内存带宽,成本高
5.3.5 以太坊共识算法 Casper FFG(选学)
权益证明(PoS)
- 稀缺资源为权益(持币量、币龄等),通过权益争夺记账权,无能源消耗。
- 主要挑战:长程攻击(Long-range Attack)和无利害关系(Nothing-at-Stake)
长程攻击
- 验证者退回抵押权益后,从历史某区块开始重写后续区块,因无保证金惩罚而低成本攻击。
- 早期投资人可能将私钥卖给攻击者,攻击者获得低成本历史权益。
无利害关系
- PoW 矿工只能在一个分叉上投入算力;PoS 验证者可同时在所有分叉上质押权益,无成本。
- 追求最大期望收益的矿工会在所有分叉上同时投票,导致分叉长期维持。
Casper FFG
- 拜占庭容错风格的权益证明,容错率 1/3(≥2/3 权益投票)。
- 引入 检查点(Checkpoint) 概念:每 100 个区块为一个检查点。
| 检查点状态 | 条件 | 说明 |
|---|---|---|
| 合理检查点(Justified) | ≥2/3 权益投票 c₁→c₂ | 类似于 PBFT 的 PREPARED |
| 确定检查点(Finalized) | ≥2/3 权益投票 c’→c₁(c’ 是 c₁ 的直接子检查点) | 类似于 PBFT 的 COMMITTED |
罚没条件(Slashing)
- 条件1:对同一高度的检查点投给两个不同来源(矛盾投票)
- 条件2:环绕投票(h(s₁) < h(s₂) < h(t₂) < h(t₁))
- 罚金远大于投票收益,使恶意投票者亏损,解决无利害关系。
长程攻击缓解
- 要求验证者离开验证者集合前必须经过解冻期(如 4 个月)。
- 节点首次加入或离线超过 4 个月时,需咨询受信任节点冷启动(弱主观性)。
5.3.6 EOSIO 共识算法 BFT-DPoS(选学)
委托权益证明(DPoS)
- 通过选举产生 21 个超级节点(见证人)轮流出块。
- 出块速度 3 秒,交易不可逆需 45 秒(21 个见证人各出一个块)。
BFT-DPoS 改进
- 传统 DPoS:每个见证人出块时全网广播,其他见证人需等待轮到自己出块时才能确认。
- BFT-DPoS:见证人收到新区块后立即验证并返回签名确认,无需等待出块。
- 交易确认时间从 45 秒缩短至 3 秒(等待一个区块时间)。
升级版 BFT-DPoS
- 出块速度从 3 秒缩短至 0.5 秒,但带来网络延迟问题。
- 解决:见证人商议确定出块顺序(延迟低的相邻出块);每个见证人连续生产 12 个区块(前几个有足够时间传递)。
5.3.7 Monoxide(选学)
- 利用分片思想将区块链划分为多个共识组,线性提升交易处理速度与吞吐量。
- 论文发表于 2019 年 NSDI。
核心问题与解决
| 问题 | 解决思路 |
|---|---|
| 跨共识组交易 | 拆分为两个原子交易,分别在各自共识组中共识,通过接力交易完成 |
| 算力分散导致安全性下降 | 连弩挖矿(Chu-ko-nu):矿工基于多个共识组同时进行 PoW,算力不稀释 |
连弩挖矿
- 矿工基于主区块头(包含各共识组区块头的 Merkle 根)进行 PoW。
- 相当于同时为所有共识组出块,攻击者仍需掌握全网半数以上算力才能攻击。
- 潜在问题:需要存储多个共识组信息,个体矿工倾向加入矿池,导致中心化。
5.4 课后题(易错知识点总结)
PBFT
- 需要 3 个阶段:pre-prepare → prepare → commit。
- 通信复杂度为 O(N^2)。
- 在异步网络中弱化活性(网络变异步时可能永远不能完成请求)。
CAP 理论
- 三个特性:一致性(C)、可用性(A)、分区容忍性(P)。
- 扩展性(Scalability) 不属于 CAP 理论的特性。
- 实际系统必须满足 P;当网络分区发生时,需在 C 与 A 之间权衡。
工作量证明(PoW)
- 以太坊 PoW 算法名称:Ethash。
- 与比特币 PoW 的关键区别:以太坊采用 Ethash,旨在抵抗 ASIC 矿机。
- 容错性:约 50%(或表述为 1/2)。
- 难度调整原理:统计一段时间内的出块速度,若出块过快则调高难度,过慢则调低难度。
- 每个区块的难度可以在其父区块基础上调整。
权益证明(PoS)
-
PoS 中文名称:权益证明。
-
以太坊 2.0 将采用 Casper FFG,属于 BFT 风格 PoS,容错率同样为 1/3 。
-
相对链式 PoS,BFT 风格 PoS 在网络复杂环境下的 输出与延迟更稳定 。
-
常见分片方案:交易分片、状态分片、网络分片。
-
密码分片不是常见的区块链分片方案。
矿工可调整以改变区块 Hash 的字段:
- 改变交易顺序
- 修改矿工奖励地址(coinbase)
- 改变 Nonce
以上操作均会改变区块头的 Merkle 根或 Nonce,从而改变 Hash。
拜占庭将军问题
- 解决的是一致性问题(在存在恶意节点时达成共识)。
- 经典解法要求节点总数 N ≥ 3F + 1(F 为叛变节点数)。
分布式一致性的三个特性(FLP)
-
可终止性(Termination)、一致性(Agreement/Validity)、合法性(Validity)。
-
可扩展性(Scalability) 不属于分布式一致性的核心特性。
-
保证账本的正确性与一致性(或称确定性)。
-
共识机制无法突破的理论限制:FLP 不可能定理(异步分布式系统中不可能同时保证活性与安全性)。
6.1 智能合约及其背景
- 智能合约是区块链 1.0 向 2.0 演进的重要分界:是否支持图灵完备的智能合约。
- 智能合约:能够自动执行合约条款的计算机程序,由 Nick Szabo 在 1996 年提出。
核心特性
- 事件驱动:以外部动作(如投币)作为输入触发执行。
- 价值转移:外部输入价值(如钱币),合约输出商品或服务,完成交换。
- 自动执行:履约行为完全自动,无需人工干预。
自动售货机类比
- 自动售货机可视为一种智能合约:
- 事件驱动:投币触发出货
- 价值转移:输入钱币,输出饮料/食品
- 自动执行:无需人工干预
- 中心化痛点:执行依赖中心化环境(售货机本身),环境出错则合约出错;程序被篡改后难以追溯。
区块链智能合约的优势
- 区块链是使多方达成状态一致的有效手段。
- 将智能合约应用到区块链上:
- 多个节点维护共同的区块链数据
- 通过交易进行智能合约的创建、调用、结束
- 多个节点上运行的智能合约过程和结果一致
- 相比中心化智能合约的优点:去中心化、多方验证、难以篡改
- 这些优点来自区块链,恰好解决了智能合约的中心化痛点。
注意
- 区块链智能合约是宽泛概念:比特币中的脚本也可视为智能合约,但不是图灵完备的。
- 常见的区块链智能合约一般指以太坊、Fabric 等平台中运行的图灵完备的智能合约。
6.2 Solidity语言
6.2.1 背景
以太坊智能合约运行于 EVM,难以直接编写机器码,因此需要高级语言作为开发语言。
Solidity 简介
- 用于编写智能合约的面向对象高级语言。
- 语法接近 JavaScript,开发人员能快速上手。
- 目前最为成熟、流行的智能合约语言,本书重点介绍。
其他智能合约语言
| 平台 | 语言 |
|---|---|
| Ethereum | Solidity、Vyper、Serpent |
| Hyperledger Fabric | Go、Java、Node.js |
设计特点
- 初期目标即用于编写以太坊智能合约,语法与以太坊工作原理高度耦合。
- 存在特殊类型(
address、event等)和特殊关键字(public、now等)。 - 编写时需要对变量进行存储位置(storage / memory)定义,不同存储位置涉及 Gas 计费不同。
6.2.2 入门示例
// SPDX-License-Identifier: MITpragma solidity ^0.8.7;
contract Example1 { uint public num;
function change(uint n) public { num = n; }}- 注释规则类似 Java。
- 第一行
SPDX-License-Identifier指定合约许可(如 MIT、UNLICENSED)。 pragma solidity ^0.8.7指定编译器版本范围(^表示大于等于 0.7.0 且小于 0.9.0)。本书示例统一使用^0.8.7。
6.2.3 基础语法
1. 常用类型
Solidity 是静态类型语言,每个变量必须被定义为特定类型。
| 类型 | 说明与示例 |
|---|---|
bool | 布尔类型,取值 true / false |
int / uint | 有符号 / 无符号整数;可指定位数(如 int8~int256,默认 int256) |
address | 以太坊账户地址(20 字节);成员:.balance、.transfer()、.send()、.call() |
bytesN | 定长字节数组,N 为 1~32(如 bytes1、bytes32) |
bytes / string | 变长字节数组 / 字符串 |
array | 数组,类型[];支持 .push()、.length、索引访问 |
mapping | 映射,mapping(键类型 => 值类型);键不可为映射、动态数组、合约、枚举、结构体;底层存储键的 keccak256 哈希值 |
struct | 结构体,struct 名称 { 成员... };可将多个基本类型组合 |
示例合约(类型综合)
// SPDX-License-Identifier: MITpragma solidity ^0.8.7;
contract Example2 { struct MyStruct { bool myBool; uint myUint; address myAddress; string myString; }
MyStruct[] public myArray; mapping(uint => string) public myMapping;
function test() public { MyStruct memory myElement = MyStruct(true, 1, msg.sender, "Hello"); myArray.push(myElement); myMapping[10086] = "World"; }}部署后调用 test(),再通过 myArray 和 myMapping 查看结果。
2. 函数类型
函数声明格式:
function 函数名(参数列表) [可见性] [状态可变性] [payable] [returns (返回值)]可见性
| 修饰符 | 可见范围 |
|---|---|
public | 合约内外均可见,可被外部或合约内调用 |
private | 仅合约内可见 |
internal | 当前合约及派生合约可见 |
external | 仅外部可见,只能通过合约外部调用 |
状态可变性
| 修饰符 | 说明 |
|---|---|
pure | 不读取也不写入状态 |
view / constant | 可读取状态,但不可写入状态 |
payable | 允许函数接收以太币;调用时附带以太币转账才会成功 |
3. 特殊函数
构造函数(constructor)
- 仅在合约部署时执行一次。
- 用于初始化合约状态(如将部署者地址记录为管理员)。
- 早期版本中构造函数与合约同名,易因拼写出错导致安全隐患,现已废弃该写法。
回退函数(fallback)
- 一个合约最多只能有一个。
- 声明形式:
fallback() external [payable]或fallback(bytes calldata) external [payable] returns (bytes memory) - 在发生错误调用(如函数名拼写错误)时自动执行。
- 若同时存在
receive()函数,则回退函数不会在接收以太币时触发。
接收函数(receive)
- 一个合约最多只能有一个。
- 声明形式:
receive() external payable - 在合约接收以太币转账时自动执行。
函数修改器(modifier)
- 用于限制函数执行条件,函数必须先通过修改器的检查才能继续执行。
- 常用于权限控制。
modifier onlyOwner() { require(msg.sender == owner, "Not owner"); _;}
function sendETH(address payable addr) public onlyOwner { addr.transfer(address(this).balance);}4. 特殊变量与全局函数
| 变量 / 函数 | 说明 |
|---|---|
msg.sender | 当前调用发送者地址 |
msg.value | 调用消息附带的以太币数量(单位 wei) |
msg.data | 完整调用数据 |
block.blockhash(uint n) | 指定区块号的区块哈希(近 256 个区块) |
block.coinbase | 当前区块矿工地址 |
block.difficulty | 当前区块难度 |
block.gaslimit | 当前区块 Gas 上限 |
block.number | 当前区块高度 |
block.timestamp / now | 当前区块时间戳(单位秒) |
gasleft() | 当前交易剩余可用 Gas |
tx.origin | 交易发起者地址(原始地址) |
tx.gasprice | 交易 Gas 价格 |
address(this) | 当前合约地址 |
address(this).balance | 当前合约余额 |
selfdestruct(address) | 自毁合约,将余额发送至指定地址,链上字节码被替换为 0x |
5. 事件日志
- 合约状态数据存储于状态树;事件日志(event)则用于单向输出运行过程信息,供上层应用低成本查询。
- 事件写入收据树,而非状态树,因此不可被合约读取。
- 定义事件:
event EventName(type indexed param1, type param2); - 触发事件:
emit EventName(value1, value2);
底层机制
- 事件名及参数类型被哈希编码为
topic。 - 区块头包含
logsBloom(布隆过滤器),上层应用可通过 Bloom 过滤器快速判断某区块中是否可能包含某合约的事件,降低查询成本。
event ETHReceipt(address indexed sender, uint amount);
receive() external payable { emit ETHReceipt(msg.sender, msg.value);}6. 错误处理
| 方式 | 行为 |
|---|---|
require(cond, "msg") | 条件为 false 时回滚状态,返回错误消息(推荐用于条件检查) |
revert("msg") | 立即终止并回滚状态,返回错误消息 |
assert(cond) | 条件为 false 时回滚并消耗全部剩余 Gas(用于内部不变式检查) |
try-catch | 捕获外部调用异常,不中断整个交易执行 |
// SPDX-License-Identifier: MITpragma solidity ^0.8.7;
contract Example4 { error DivByZero(string message);
function getTimes1(uint a, uint b) public pure returns (uint) { require(b > 0, "Cannot divide by zero"); return a / b; }
function getTimes2(uint a, uint b) public pure returns (uint) { if (b == 0) revert DivByZero("Cannot divide by zero"); return a / b; }
function getTimes3(uint a, uint b) public pure returns (uint) { assert(b != 0); return a / b; }
function tryCatchExample(uint a, uint b) external view returns (uint value, bool success) { try this.getTimes1(a, b) returns (uint v) { return (v, true); } catch { return (0, false); } }}补充
消息调用操作码
CALL:普通调用,会改变目标地址的存储 CALLCODE:在调用者上下文中执行目标代码,但状态保存在调用者存储中(已废弃) DELEGATECALL:在调用者上下文中执行目标代码,状态和 msg.sender 均继承自调用者 STATICCALL:只读调用,不允许修改状态 区块与交易变量
| 变量 | 说明 |
|---|---|
| block.blockhash(n) | 指定区块号的区块哈希(近 256 个区块) |
| block.coinbase | 矿工地址 |
| block.difficulty | 挖矿难度 |
| block.gaslimit | 当前区块 Gas 上限 |
| block.number | 当前区块高度 |
| block.timestamp | 当前区块时间戳(单位秒) |
| tx.gasprice | 交易 Gas 价格 |
| tx.origin | 原始交易发起者地址 |
字符串操作
拼接:string(abi.encodePacked(a, b)) 或 bytes.concat() 比较:keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b)) 或 a == b(Solidity 0.8+ 支持直接比较) 栈(Stack)
用 uint[] 数组模拟 push(x):入栈 pop():出栈(删除栈顶) top():查询栈顶,栈空时返回指定值(如 -1) 队列(Queue)
用 uint[] 数组模拟 push(x):队尾入队 pop():删除队首元素 front():查询队首,队空时返回指定值 back():查询队尾,队空时返回指定值
7.1 联盟链平台
联盟链是面向企业级应用的区块链形态,通过准入机制解决公有链在性能、隐私、监管方面的不足。
核心价值
- 解决多方协同记账与信任问题。
- 价值传输从”依赖中心化信息中介”转向”分布式可信记录”。
- 联盟链因监管可操作,在金融、供应链等领域试点广泛(如雄安新区基建融资、供应链金融)。
7.1.1 背景
区块链底层技术解决”多方协同记账”问题,本质是解决信任问题。
- 信息传输:互联网已高效解决。
- 价值传输:传统依赖银行等中心化第三方,存在单点风险、成本高、易篡改等问题。
- 公有链瓶颈:性能不足、商业秘密泄露、难以监管、去中心化与监管天然冲突。
- 联盟链方案:节点加入/退出有准入机制,保护商业秘密,提高交易效率。
7.1.2 Hyperledger Fabric
2016 年 Linux 基金会发起,IBM 等企业创建。面向企业的高度可扩展区块链平台。
核心特性
| 特性 | 说明 |
|---|---|
| 权限管理 | 通过 MSP(成员服务提供商)验证身份,基于策略授予不同权限 |
| 隐私保护 | 通道(Channel) 技术实现数据隔离,只有通道内节点可访问交易数据 |
| 高度模块化 | 可插拔的排序服务、背书/验证策略、身份与密钥管理 |
| 高效处理 | 交易执行、排序、广播分离,多角色节点并行处理,支持高吞吐 |
| 链码 | 支持 Go/JavaScript/Java 编写智能合约,运行在隔离容器中,逻辑与数据分离 |
7.1.3 企业以太坊
企业以太坊联盟(EEA):2017 年成立,成员包括摩根大通、英特尔、埃森哲等,旨在制定企业级以太坊标准。
与公有链以太坊的区别
- 更注重隐私保护、权限管理、灵活配置、处理性能。
- 长远目标:模块化平台,可动态适配公链或私有链需求。
Quorum(摩根大通)
- 引入公有交易与私有交易,支持交易和合约私有化。
- 采用基于投票的共识机制(替代 PoW),出块效率更高。
- 增加节点权限管理,控制 P2P 通信范围。
7.2 供应链金融
7.2.1 应用背景
供应链中核心企业占强势地位,上下游中小企业常被拖欠账款,导致现金流紧张。
融资痛点
- 融资成本高:中小企业业务数据难以获得银行信任,银行收取高利率或拒绝授信。
- 监管难:影子银行介入,风控授信不确定性大,政府监管困难。
7.2.2 应用案例
- 将供应链每笔交易和应收账款单据上链,引入银行、物流公司等可信机构确认信息。
- 实现物流、信息流、资金流真实上链,支持应收账款转让、融资、清算。
- 核心企业信用通过区块链可信记录传递给上下游中小企业,降低融资成本。
典型架构
- 联盟链成员:核心企业、中间供应商、金融机构。
- 核心企业确认应收账款,供应商拆分转让、发起保理融资,金融机构提供风控和贷款。
7.3 资产交易
7.3.1 应用背景
数字资产(商品、艺术品、版权、知识产权、电子仓单等)交易痛点:
- 交易所信息孤岛:跨机构流转需烦琐对账,清算成本高。
- 资产确权难:权属证明效率低,跨机构难以共识定价。
- 全过程监管难:备案制管理,信息不透明,难以实时监管。
7.3.2 应用案例
- 链下资产登记上链 → 标准化数字资产 → 交易即结算,提高效率,降低对账成本。
- 监管机构作为联盟链节点,可实时监控交易,提升监管效率。
以太坊代币标准
- ERC20:同质化代币(可分割)。
- ERC721:非同质化代币(不可分割,如 NFT)。
- 标准合约具有互操作性,可被交易所、钱包识别,提升流通性。
7.4 司法存证
7.4.1 应用背景
电子证据痛点:
- 取证成本高:依赖司法存证机构,周期长、费用高。
- 取证难校验:电子证据易篡改、难溯源,权威性依赖机构资质,难以追责。
- 监管难:人工审核成本高。
7.4.2 应用案例
- 2018 年《最高人民法院关于互联网法院审理案件若干问题的规定》明确:通过区块链等技术手段收集、固定的电子数据,能够证明真实性的,互联网法院应当确认。
- 联盟链节点:法院、公证处、司法鉴定中心、鉴定机构等。
- 实现电子证据全流程可信(生成、存储、传播、使用)。
典型案例
-
杭州互联网法院司法区块链(2018 年上线)
- 联盟方:杭州互联网法院、钱塘公证处、上海市计算机行业协会、司法鉴定中心。
- 实现时间可信、环境可信、机器可信、全流程真实可信。
-
北京互联网法院天平链(2018 年上线)
- 节点:北京市高级人民法院、北京互联网法院、公证处、司法鉴定所等 19 家单位。
- 一级共识节点包括法院、公证、鉴定机构。
- 已接入 25 家应用单位(技术服务、知识产权、金融交易等)。
7.5 物流溯源
7.5.1 应用背景
当前溯源系统问题:
- 信息存储中心化:单一数据库易篡改,冗余备份仍难防假数据。
- 多点记录对账效率低:上下游各自记录,需人工对账,错误追溯困难。
7.5.2 应用案例
- 商品物流过程记录到多参与方共同维护的区块链上,保证数据安全,提升对账效率。
- 结合物联网、防伪标签/芯片实现唯一标识。
- 参与方:品牌商、渠道商、零售商、消费者、监管部门、第三方检测机构。
- 实现精确实码的全流程正品追溯。
7.6 票据流通
7.6.1 应用背景
票据(发票、承兑汇票)痛点:
- 易篡改、伪造、复制:可靠性依赖开票机构权威性,纸质发票存在重复报销。
- 校验成本高:需投入大量人力物力核对防伪。
- 流通过程难以监管:各机构信息系统差异大,难以统一监管。
7.6.2 应用案例
- 区块链增强票据安全性与流通性,降低开票、结算成本,提升自动化水平。
- 监管机构作为节点加入,可监控所有流通环节。
区块链电子发票
- 2018 年国家税务总局授权深圳市税务局试行。
- 特性:全流程追溯、信息不可篡改、规避假发票。
- 生命周期:经营者(申领→开具→查验→入账)→ 消费者(存储→流转→报销)→ 税务局(全流程监管)。
- 实现无纸化智能税务管理。