- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 1. 区块链基础:哈希、默克尔树与共识
- 2. 以太坊内部机制:EVM、Gas 与状态树
- 3. 智能合约:Solidity 模式与安全
- 4. DeFi 协议:AMM、借贷与 MEV
- 5. ZK 证明:zk-SNARK、PLONK、ZK Rollup
- 6. AI + 区块链
- 7. 开发工具
- 小测验
- 结语
1. 区块链基础:哈希、默克尔树与共识
1.1 哈希函数与不可篡改性
区块链的核心是密码学哈希函数。每个区块都包含前一个区块的哈希,从而形成链条。
import hashlib
import json
def compute_block_hash(index, previous_hash, timestamp, data, nonce):
block_content = json.dumps({
"index": index,
"previous_hash": previous_hash,
"timestamp": timestamp,
"data": data,
"nonce": nonce
}, sort_keys=True)
return hashlib.sha256(block_content.encode()).hexdigest()
# SHA-256 的特性:确定性、单向性、雪崩效应
hash1 = hashlib.sha256(b"hello").hexdigest()
hash2 = hashlib.sha256(b"hellO").hexdigest()
# 仅一个字符之差就会产生完全不同的哈希
print(hash1[:16], "vs", hash2[:16])
1.2 默克尔树(Merkle Tree)
默克尔树能以 O(log n) 的证明规模验证大规模数据集的完整性。比特币和以太坊都用它来验证交易。
def build_merkle_tree(leaves):
if not leaves:
return None
layer = [hashlib.sha256(leaf.encode()).hexdigest() for leaf in leaves]
while len(layer) > 1:
if len(layer) % 2 != 0:
layer.append(layer[-1]) # 若为奇数,复制最后一个
layer = [
hashlib.sha256((layer[i] + layer[i+1]).encode()).hexdigest()
for i in range(0, len(layer), 2)
]
return layer[0] # Merkle Root
txs = ["tx_alice_to_bob", "tx_carol_to_dave", "tx_eve_to_frank", "tx_grace_to_heidi"]
root = build_merkle_tree(txs)
print("Merkle Root:", root)
1.3 共识算法对比
| 算法 | 能耗 | 吞吐量 | 去中心化程度 | 代表链 |
|---|---|---|---|---|
| PoW | 非常高 | ~7 TPS | 高 | Bitcoin |
| PoS | 低 | ~数千 TPS | 中 | Ethereum |
| DPoS | 低 | ~数万 TPS | 低 | EOS, TRON |
| PBFT | 低 | ~数千 TPS | 低 | Hyperledger |
PoS 惩罚(Slashing):在以太坊 PoS 中,若验证者双重签名(double voting),其质押 ETH 的一部分会被销毁。这一经济惩罚正是安全性的核心。
2. 以太坊内部机制:EVM、Gas 与状态树
2.1 EVM(以太坊虚拟机)
EVM 是一个 256 位基于栈的虚拟机,是所有以太坊节点上都以相同方式执行的确定性环境。
EVM 栈运算示例(PUSH1、ADD、MUL):
PUSH1 0x03 → 栈: [3]
PUSH1 0x04 → 栈: [3, 4]
ADD → 栈: [7]
PUSH1 0x02 → 栈: [7, 2]
MUL → 栈: [14]
主要的 EVM 存储区域:
- Stack(栈):最多 1024 个元素,用于临时运算
- Memory(内存):字节数组,在函数执行期间临时使用
- Storage(存储):键值型永久存储(成本最高,SSTORE = 20,000 gas)
- Calldata(调用数据):外部函数调用时传入的数据
2.2 EIP-1559 Gas 机制
在 EIP-1559 之前,Gas 采用竞价方式分配。此后基础费用(base fee)会被销毁,只有小费(priority fee)会转给验证者。
# EIP-1559 交易费用计算
base_fee = 15 # gwei(根据网络状态自动调整)
priority_fee = 2 # gwei(小费)
max_fee = 20 # gwei(允许的最大值)
actual_fee = min(base_fee + priority_fee, max_fee)
gas_used = 21000 # 简单的 ETH 转账
total_cost_gwei = actual_fee * gas_used
total_cost_eth = total_cost_gwei / 1e9
print(f"交易手续费: {total_cost_eth:.6f} ETH")
# base_fee 被销毁 → ETH 通缩效应
burned = base_fee * gas_used / 1e9
print(f"已销毁 ETH: {burned:.6f} ETH")
2.3 The Merge:从 PoW 转向 PoS
2022 年 9 月 15 日,以太坊通过 The Merge 将能耗降低了约 99.95%。
- 信标链(Beacon Chain):自 2020 年 12 月起并行运行的 PoS 链
- 执行层:负责既有的 EVM 状态与交易处理
- 共识层:负责验证者管理、认证(attestation)与最终性(finality)
- 最低质押量:每个验证者 32 ETH
3. 智能合约:Solidity 模式与安全
3.1 带 ReentrancyGuard 的 ERC-20 代币
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract SecureToken is ERC20, ReentrancyGuard, Ownable {
uint256 public constant MAX_SUPPLY = 1_000_000 * 10**18;
mapping(address => uint256) public lockTime;
event TokensLocked(address indexed user, uint256 amount, uint256 unlockTime);
event TokensUnlocked(address indexed user, uint256 amount);
constructor() ERC20("SecureToken", "STKN") Ownable(msg.sender) {
_mint(msg.sender, 100_000 * 10**18);
}
// 应用 Checks-Effects-Interactions 模式
function lockAndRelease(uint256 amount, uint256 duration)
external
nonReentrant // 防重入
{
// 1. Checks: 校验条件
require(amount > 0, "Amount must be positive");
require(balanceOf(msg.sender) >= amount, "Insufficient balance");
require(duration >= 1 days && duration <= 365 days, "Invalid duration");
// 2. Effects: 状态变更(在外部调用之前)
lockTime[msg.sender] = block.timestamp + duration;
_transfer(msg.sender, address(this), amount);
// 3. Interactions: 外部调用(在状态变更之后)
emit TokensLocked(msg.sender, amount, lockTime[msg.sender]);
}
function unlock() external nonReentrant {
// Checks
require(block.timestamp >= lockTime[msg.sender], "Still locked");
uint256 contractBalance = balanceOf(address(this));
require(contractBalance > 0, "Nothing to unlock");
// Effects
lockTime[msg.sender] = 0;
// Interactions
_transfer(address(this), msg.sender, contractBalance);
emit TokensUnlocked(msg.sender, contractBalance);
}
function mint(address to, uint256 amount) external onlyOwner {
require(totalSupply() + amount <= MAX_SUPPLY, "Exceeds max supply");
_mint(to, amount);
}
}
3.2 重入攻击原理
这一模式正是 The DAO 事件(2016 年,被盗 360 万 ETH)中被利用的攻击手法。
// 存在漏洞的合约(切勿使用)
contract VulnerableBank {
mapping(address => uint256) public balances;
function withdraw() external {
uint256 amount = balances[msg.sender];
// 状态变更前先发起外部调用 → 可能被重入!
(bool success,) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
balances[msg.sender] = 0; // 太晚了
}
}
// 攻击合约
contract Attacker {
VulnerableBank public target;
receive() external payable {
if (address(target).balance >= 1 ether) {
target.withdraw(); // 递归调用反复提款
}
}
}
3.3 Hardhat 测试
const { expect } = require('chai')
const { ethers } = require('hardhat')
describe('SecureToken', function () {
let token, owner, alice, bob
beforeEach(async function () {
;[owner, alice, bob] = await ethers.getSigners()
const SecureToken = await ethers.getContractFactory('SecureToken')
token = await SecureToken.deploy()
await token.waitForDeployment()
})
it('재진입 공격을 방어해야 한다', async function () {
// 向 alice 转账代币
await token.transfer(alice.address, ethers.parseEther('1000'))
expect(await token.balanceOf(alice.address)).to.equal(ethers.parseEther('1000'))
})
it('잠금 기간 전에는 언락 불가', async function () {
await token.transfer(alice.address, ethers.parseEther('100'))
await token.connect(alice).lockAndRelease(
ethers.parseEther('100'),
86400 // 1 天
)
await expect(token.connect(alice).unlock()).to.be.revertedWith('Still locked')
})
it('Foundry 스타일 퍼즈 테스트 시뮬레이션', async function () {
const amounts = [1, 100, 1000].map((n) => ethers.parseEther(n.toString()))
for (const amount of amounts) {
await token.mint(alice.address, amount)
}
const total = amounts.reduce((a, b) => a + b, 0n)
expect(await token.balanceOf(alice.address)).to.equal(total)
})
})
3.4 Foundry forge 测试
// test/SecureToken.t.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "../src/SecureToken.sol";
contract SecureTokenTest is Test {
SecureToken public token;
address public alice = makeAddr("alice");
function setUp() public {
token = new SecureToken();
token.transfer(alice, 1000 ether);
}
function testLockRequiresDuration() public {
vm.startPrank(alice);
vm.expectRevert("Invalid duration");
token.lockAndRelease(100 ether, 12 hours); // 不足 1 天
vm.stopPrank();
}
// 模糊测试:用任意金额反复验证
function testFuzz_LockAmount(uint256 amount) public {
amount = bound(amount, 1 ether, 1000 ether);
vm.startPrank(alice);
token.lockAndRelease(amount, 1 days);
assertEq(token.balanceOf(address(token)), amount);
vm.stopPrank();
}
}
4. DeFi 协议:AMM、借贷与 MEV
4.1 Uniswap v3 集中流动性
v2 的 x*y=k 公式将流动性均匀分散在整个价格区间。v3 允许 LP 将流动性集中到特定价格区间,把资本效率最多提升 4000 倍。
import math
# Uniswap v3 价格计算(基于 tick)
# tick = log(sqrt(price)) / log(sqrt(1.0001))
def tick_to_price(tick):
return 1.0001 ** tick
def price_to_tick(price):
return math.floor(math.log(price) / math.log(1.0001))
def calculate_liquidity_v3(amount0, amount1, price_current, price_lower, price_upper):
"""计算集中流动性头寸的 L(流动性)"""
sqrt_p = math.sqrt(price_current)
sqrt_pa = math.sqrt(price_lower)
sqrt_pb = math.sqrt(price_upper)
if price_current <= price_lower:
# 全部为 token0
L = amount0 * (sqrt_pa * sqrt_pb) / (sqrt_pb - sqrt_pa)
elif price_current >= price_upper:
# 全部为 token1
L = amount1 / (sqrt_pb - sqrt_pa)
else:
# 混合
L0 = amount0 * (sqrt_p * sqrt_pb) / (sqrt_pb - sqrt_p)
L1 = amount1 / (sqrt_p - sqrt_pa)
L = min(L0, L1)
return L
# ETH/USDC 池示例
# 当前价格: 3000 USDC/ETH,区间: 2500 ~ 3500
L = calculate_liquidity_v3(
amount0=1.0, # 1 ETH
amount1=3000.0, # 3000 USDC
price_current=3000,
price_lower=2500,
price_upper=3500
)
print(f"流动性 L: {L:.4f}")
4.2 MEV(可提取的最大价值)
MEV 是区块生产者通过操纵交易顺序所能提取的最大价值。
主要 MEV 类型:
- 三明治攻击(Sandwich Attack):在大额兑换前后分别买入/卖出,从滑点中获利
- 套利(Arbitrage):捕捉去中心化交易所之间的价格差
- 清算(Liquidation):通过清算抵押不足的仓位获得奖励
Flashbots:为 MEV 民主化而生的基础设施
- mev-boost:连接以太坊验证者与区块构建者(block builder)
- 通过公开竞价提升 MEV 分配的透明度
- 缓解暗网(dark forest,即内存池攻击)问题
5. ZK 证明:zk-SNARK、PLONK、ZK Rollup
5.1 zk-SNARK 原理
zk-SNARK(Zero-Knowledge Succinct Non-interactive ARguments of Knowledge)让证明者能在不公开秘密信息(witness)的情况下,向验证者证明某个命题为真。
核心性质:
- 完备性(Completeness):真命题总能被证明
- 可靠性(Soundness):假命题无法被证明
- 零知识性(Zero-knowledge):证明过程中不泄露秘密
// 使用 snarkjs 的简单 ZK 证明示例
// 电路: a * b = c(在不公开 a、b 的情况下证明乘法关系)
const snarkjs = require('snarkjs')
const fs = require('fs')
async function generateAndVerifyProof() {
// 1. 计算 witness(非公开输入)
const input = {
a: 3, // 秘密
b: 11, // 秘密
c: 33, // 公开: a * b = c
}
// 2. 生成证明(需要 proving key)
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
input,
'multiply.wasm',
'multiply_final.zkey'
)
console.log('公开信号:', publicSignals) // [33]
console.log('证明大小:', JSON.stringify(proof).length, 'bytes')
// 3. 验证(只需要 verification key)
const vKey = JSON.parse(fs.readFileSync('verification_key.json'))
const isValid = await snarkjs.groth16.verify(vKey, publicSignals, proof)
console.log('证明是否有效:', isValid) // true
// 若没有证明,a=3、b=11 这一事实无法被推知
}
generateAndVerifyProof()
5.2 ZK Rollup 架构
ZK Rollup 在 L2 上处理数千笔交易,只将有效性证明(validity proof)发布到 L1。
L2 交易批处理:
[tx1, tx2, ..., tx1000]
↓ 证明者(prover)
ZK Proof(数百字节)
↓ L1 验证者
以太坊主网(节省 99%+ Gas)
zkSync Era vs StarkNet:
- zkSync Era:兼容 EVM(Boojum 证明系统,基于 PLONK)
- StarkNet:使用 Cairo 语言,STARK 证明(抗量子计算)
- Polygon zkEVM:Type 2 EVM 等价性
6. AI + 区块链
6.1 去中心化 AI 计算
Gensyn:让分布式 GPU 集群上的 AI 模型训练变得可验证的协议。
- 将训练任务拆分为更小的子任务
- 为每个子任务生成可验证的证明
- 家用 GPU 也能参与网络
Bittensor(TAO):AI 模型之间的去中心化市场
- 按子网划分的专用 AI 任务
- 由验证者(validator)评估矿工(miner)的输出
- 按贡献度发放 TAO 代币奖励
6.2 链上 AI 验证
# FHE(全同态加密)概念示例
# 在加密状态下执行运算
# 实际实现: Microsoft SEAL、OpenFHE
# 概念示例:
def fhe_inference_concept(encrypted_input, model_weights):
"""
使用 FHE,可以在不解密输入数据的情况下
以加密状态执行 AI 推理
- 医疗数据: 在不暴露患者信息的情况下完成诊断
- 金融数据: 在保护隐私的同时进行信用评估
"""
# 同态运算(加法、乘法均可在加密状态下进行)
encrypted_result = homomorphic_matrix_multiply(
encrypted_input,
model_weights # 模型是公开的,只有输入被加密
)
return encrypted_result
7. 开发工具
7.1 用 web3.py 与合约交互
from web3 import Web3
import json
# Alchemy/Infura RPC 连接
w3 = Web3(Web3.HTTPProvider("https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY"))
print("连接状态:", w3.is_connected())
print("最新区块:", w3.eth.block_number)
# ERC-20 余额查询
ERC20_ABI = [
{"inputs": [{"name": "account", "type": "address"}],
"name": "balanceOf",
"outputs": [{"name": "", "type": "uint256"}],
"type": "function"},
{"inputs": [],
"name": "symbol",
"outputs": [{"name": "", "type": "string"}],
"type": "function"}
]
USDC_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
usdc = w3.eth.contract(
address=Web3.to_checksum_address(USDC_ADDRESS),
abi=ERC20_ABI
)
address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" # vitalik.eth
balance = usdc.functions.balanceOf(address).call()
symbol = usdc.functions.symbol().call()
print(f"{symbol} 余额: {balance / 10**6:.2f}")
# 发送交易(含签名)
def send_erc20(private_key, to_address, amount_wei):
account = w3.eth.account.from_key(private_key)
nonce = w3.eth.get_transaction_count(account.address)
tx = usdc.functions.transfer(to_address, amount_wei).build_transaction({
"from": account.address,
"nonce": nonce,
"gas": 100000,
"maxFeePerGas": w3.to_wei(20, "gwei"),
"maxPriorityFeePerGas": w3.to_wei(2, "gwei"),
})
signed = w3.eth.account.sign_transaction(tx, private_key)
tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
return tx_hash.hex()
7.2 ethers.js v6
import { ethers } from 'ethers'
// 配置 provider
const provider = new ethers.JsonRpcProvider('https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY')
// 解析 ENS 名称
const address = await provider.resolveName('vitalik.eth')
console.log('vitalik.eth →', address)
// 订阅事件(实时监听 Transfer)
const ERC20_FILTER_ABI = ['event Transfer(address indexed from, address indexed to, uint256 value)']
const usdc = new ethers.Contract(
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
ERC20_FILTER_ABI,
provider
)
usdc.on('Transfer', (from, to, value, event) => {
const amount = ethers.formatUnits(value, 6)
if (parseFloat(amount) > 100000) {
console.log(`大额 USDC 转账: ${amount} USDC`)
console.log(`from: ${from} → to: ${to}`)
console.log(`tx: ${event.log.transactionHash}`)
}
})
小测验
Q1. 以太坊 PoS 相比 PoW 更节能、同时又能维持安全性,靠的是什么经济机制?
答案:通过惩罚机制(Slashing)实现的经济性处罚
解释:PoW 依靠消耗物理能源(电力)来构筑攻击成本,而 PoS 则要求验证者锁定 32 ETH 作为担保。一旦出现双重签名、环绕投票(surround voting)等恶意行为,其质押 ETH 的一部分(至少 1/32)会被自动销毁。若全网超过三分之一的验证者合谋发起攻击,最高会触发 100% 惩罚,让攻击者蒙受巨大损失。它无需消耗能源,就实现了与 PoW 相同的威慑力——只是用经济损失取代了能源消耗。
Q2. 重入攻击在智能合约中发生的模式,以及防御方法是什么?
答案:Checks-Effects-Interactions 模式 + ReentrancyGuard
解释:重入攻击是指外部合约通过回调(receive/fallback)反复调用原始函数的攻击方式。存在漏洞的模式会在把余额清零之前就发送 ETH。防御方法有三种:(1) Checks-Effects-Interactions——在任何外部调用之前完成所有状态变更;(2) OpenZeppelin 的 ReentrancyGuard——用 nonReentrant 修饰符阻止对同一函数的重入;(3) Pull Payment 模式——不是由合约主动推送资金,而是由用户自行提取。
Q3. Uniswap v3 的集中流动性为什么比 v2 的资本效率更高?
答案:LP 将流动性集中到特定价格区间,从而最大化活跃资本的占比
解释:v2 的 x*y=k 公式会把流动性从 0 到无穷大均匀分布在整个价格区间上。而实际交易大多发生在狭窄的价格区间内,导致大部分资本处于闲置状态。在 v3 中,LP 只需将资本部署在预期的价格区间内(例如 2500~3500 USDC/ETH)。用同样的资本,在该区间内可以提供最多 4000 倍更深的流动性,手续费收入也因此更集中。缺点是一旦价格超出该区间,就不再产生手续费收入。
Q4. zk-SNARK 中,证明者是如何在不暴露知识本身的情况下说服验证者的?
答案:多项式约定(Polynomial Commitment)与基于配对(pairing)的密码学
解释:zk-SNARK 把计算转换为多项式方程(R1CS → QAP)。证明者不会直接公开秘密 witness,而是提交编码在椭圆曲线上的点(Elliptic Curve Point)形式的多项式求值结果。验证者通过双线性配对(bilinear pairing)运算来确认多项式关系是否成立。由于离散对数问题的难解性,无法从中反推出真正的 witness。证明大小只有数百字节,验证耗时以毫秒计。
Q5. MEV 对区块链生态系统有哪些影响?Flashbots 又扮演了什么角色?
答案:MEV 具有两面性,Flashbots 通过透明竞价缓解其负面效应
解释:MEV 的积极一面在于通过套利实现价格效率,以及通过及时清算维持 DeFi 的稳定性。消极一面则包括三明治攻击给普通用户带来的损失、内存池拥堵与 Gas 大战、以及诱发链重组(reorg)的激励问题。Flashbots 通过 mev-boost 将区块构建者与验证者分离,建立起透明的公开竞价市场。用户可以通过打包交易(bundle transaction)来防止抢先交易(front-running),MEV 收益也能更公平地分配给验证者。
结语
区块链工程是密码学、分布式系统与经济学交叉融合的复杂领域。以太坊生态正随着 EVM 优化、ZK 技术的成熟、以及与 AI 的融合而快速演进。智能合约安全与代码编写本身同等重要——Hardhat/Foundry 测试与正式审计都是不可或缺的环节。ZK Rollup 与 AI+区块链的结合,将定义 Web3 的下一个阶段。