18 KiB
18 KiB
Web3基础知识
问题
- 什么是Web3?Web1、Web2、Web3的区别是什么?
- 区块链的核心原理是什么?区块结构是怎样的?
- 什么是共识机制?PoW、PoS、DPoS的区别?
- 什么是智能合约?它有什么特点?
- 公链、私链、联盟链的区别?
- 什么是Gas费?为什么需要Gas费?
- 什么是预言机(Oracle)?它解决了什么问题?
- 什么是代币标准?ERC-20、ERC-721、ERC-1155的区别?
- 什么是哈希函数?它在区块链中的作用?
- 什么是默克尔树(Merkle Tree)?它有什么作用?
标准答案
1. Web1、Web2、Web3的区别
Web1(1990-2005):只读时代
特点:
- 静态网页
- 用户只能阅读内容
- 单向信息传递
- 门户网站主导
代表:新浪、搜狐、Yahoo
Web2(2005-至今):读写时代
特点:
- 动态网页、交互式
- 用户可以创建内容
- 平台主导、中心化
- 数据存储在中心化服务器
代表:Facebook、Twitter、抖音
问题:
- 数据归平台所有
- 平台可以删除账号
- 隐私泄露
- 平台垄断
Web3(未来):读写拥有时代
特点:
- 去中心化
- 用户拥有数据所有权
- 基于区块链
- 代币经济激励
- 智能合约自动执行
代表:Uniswap、OpenSea、ENS
优势:
- 数据归用户所有
- 抗审查
- 透明可信
- 价值回归用户
2. 区块链核心原理
区块结构
type Block struct {
Header *BlockHeader
Data []byte // 交易数据
}
type BlockHeader struct {
Version uint32 // 版本号
PrevBlockHash []byte // 前一个区块的哈希
MerkleRoot []byte // 默克尔树根
Timestamp uint32 // 时间戳
Bits uint32 // 难度目标
Nonce uint32 // 随机数(挖矿时调整)
}
链式结构
Genesis Block (区块0)
↓ (PrevBlockHash)
Block 1
↓ (PrevBlockHash)
Block 2
↓ (PrevBlockHash)
Block 3
↓
...
关键特性:
- 不可篡改:修改任意区块,后续所有区块的哈希都会变化
- 透明性:所有交易公开可查
- 去中心化:没有单一控制方
交易流程
1. 用户发起交易(转账、调用合约)
2. 交易广播到网络
3. 矿工/验证者打包交易到区块
4. 达成共识(PoW/PoS)
5. 区块添加到链上
6. 交易确认
3. 共识机制
PoW(Proof of Work)- 工作量证明
代表:比特币、以太坊1.0
原理:
1. 矿工收集交易
2. 计算哈希值(不断调整Nonce)
3. 第一个找到符合难度要求的哈希的矿工获得记账权
4. 其他节点验证
5. 添加区块到链上
代码示例:
func (pow *ProofOfWork) Run() (int, []byte) {
var hashInt big.Int
var hash [32]byte
nonce := 0
for nonce < maxNonce {
data := pow.prepareData(nonce)
hash = sha256.Sum256(data)
hashInt.SetBytes(hash[:])
if hashInt.Cmp(pow.target) == -1 {
break // 找到有效哈希
} else {
nonce++
}
}
return nonce, hash[:]
}
优点:
- 安全性高(51%攻击成本极高)
- 去中心化程度高
缺点:
- 能源消耗大
- TPS低(比特币7 TPS)
- 确认时间长
PoS(Proof of Stake)- 权益证明
代表:以太坊2.0、Cardano、Polkadot
原理:
1. 验证者质押代币
2. 根据质押数量和时长选择验证者
3. 验证者创建区块
4. 获得奖励
5. 作恶会被罚没质押的代币
代码示例:
type Validator struct {
Address string
Stake uint64 // 质押数量
Uptime float64 // 在线时长
Reputation uint64 // 信誉分数
}
func SelectValidator(validators []Validator) *Validator {
// 根据质押数量加权随机选择
totalStake := uint64(0)
for _, v := range validators {
totalStake += v.Stake
}
randNum := rand.Uint64() % totalStake
cumulative := uint64(0)
for _, v := range validators {
cumulative += v.Stake
if randNum < cumulative {
return &v
}
}
return nil
}
优点:
- 能源消耗低(比PoW节能99%)
- 更高的TPS
- 更快确认时间
缺点:
- 富者愈富(大户更容易被选中)
- 可能导致中心化
DPoS(Delegated Proof of Stake)- 委托权益证明
代表:EOS、TRON、BTS
原理:
1. 代币持有者投票选举超级节点
2. 超级节点轮流记账
3. 超级节点获得奖励
4. 表现不好会被投票出局
示例:
// EOS:21个超级节点
func (bp *BlockProducer) Schedule(blocks []*Block) {
// 每个超级节点轮流出块
// 每3秒一个区块
// 21个节点轮一圈 = 63秒
for i, block := range blocks {
producer := bp.producers[i % 21]
producer.ProduceBlock(block)
}
}
优点:
- TPS极高(EOS可达4000+ TPS)
- 确认快
- 能耗低
缺点:
- 中心化程度高(只有21个节点)
- 可能被大户控制
4. 智能合约
定义
智能合约是运行在区块链上的自动执行程序,当满足预设条件时自动执行。
特点
// Solidity示例(以太坊智能合约)
pragma solidity ^0.8.0;
contract SimpleVault {
mapping(address => uint256) public balances;
// 存款
function deposit() public payable {
balances[msg.sender] += msg.value;
}
// 取款
function withdraw(uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
// 自动转账,无需人工干预
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
}
}
特点:
- 自动执行:条件满足自动运行
- 不可篡改:部署后无法修改
- 透明可信:代码公开可查
- 去信任化:不需要第三方中介
应用场景
- DeFi(去中心化金融)
- NFT(数字资产)
- DAO(去中心化组织)
- 供应链溯源
- 保险理赔
5. 公链、私链、联盟链
| 特性 | 公链 | 联盟链 | 私链 |
|---|---|---|---|
| 访问权限 | 任何人 | 授权成员 | 单个组织 |
| 去中心化 | 高 | 中 | 低 |
| 性能 | 低 | 中 | 高 |
| 代表 | Bitcoin、Ethereum | Hyperledger Fabric | 企业内部链 |
| 应用场景 | 加密货币、DeFi | 银行联盟、供应链 | 企业内部 |
公链代码示例:
// 任何人都可以加入网络
func (n *PublicNetwork) Join() {
// 下载区块链数据
// 开始挖矿/验证
// 无需许可
}
联盟链代码示例:
// 只有授权成员可以加入
func (n *ConsortiumNetwork) Join(nodeID string, cert *Certificate) error {
// 验证证书
if !n.verifyCertificate(cert) {
return errors.New("unauthorized")
}
// 添加到联盟
n.members = append(n.members, nodeID)
return nil
}
6. Gas费
为什么需要Gas费?
1. 防止DDoS攻击
- 如果交易免费,攻击者可以发送大量垃圾交易
- Gas费让攻击成本极高
2. 激励矿工/验证者
- 矿工打包交易需要消耗资源
- Gas费作为报酬
3. 优先级机制
- Gas费越高,越快被打包
Gas费计算
交易费用 = Gas Used × Gas Price
例如:
- 转账消耗:21,000 Gas
- Gas Price:20 Gwei
- 总费用 = 21,000 × 20 Gwei = 0.00042 ETH
代码示例:
type Transaction struct {
To *common.Address
Value *big.Int
GasLimit uint64 // 最大Gas消耗
GasPrice *big.Int // Gas价格
Data []byte
}
func (tx *Transaction) Cost() *big.Int {
// 总成本 = 转账金额 + Gas费用
gasFee := new(big.Int).Mul(
new(big.Int).SetUint64(tx.GasLimit),
tx.GasPrice,
)
return new(big.Int).Add(tx.Value, gasFee)
}
EIP-1559(伦敦升级)
旧模式:
- 用户设置Gas Price
- 全部给矿工
新模式(EIP-1559):
- Base Fee:网络自动计算(销毁)
- Priority Fee:给矿工的小费
- 总费用 = Base Fee + Priority Fee
7. 预言机(Oracle)
问题:区块链无法访问外部数据
智能合约无法直接访问:
- 股票价格
- 天气数据
- 体育比赛结果
- 法币汇率
解决方案:预言机
// 使用Chainlink预言机
pragma solidity ^0.8.0;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract PriceConsumer {
AggregatorV3Interface internal priceFeed;
constructor() {
// ETH/USD 价格预言机
priceFeed = AggregatorV3Interface(
0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419
);
}
function getLatestPrice() public view returns (int) {
(
uint80 roundID,
int price,
uint startedAt,
uint timeStamp,
uint80 answeredInRound
) = priceFeed.latestRoundData();
return price;
}
}
预言机的工作流程
1. 智能合约请求数据
2. 预言机监听事件
3. 预言机从外部API获取数据
4. 预言机将数据提交到链上
5. 智能合约使用数据
去中心化预言机
Chainlink:
- 多个节点提供数据
- 聚合结果
- 防止单点故障
- 惩罚作恶节点
8. 代币标准
ERC-20(同质化代币)
pragma solidity ^0.8.0;
contract MyToken {
string public name = "My Token";
string public symbol = "MTK";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(uint256 _initialSupply) {
totalSupply = _initialSupply * 10 ** uint256(decimals);
balanceOf[msg.sender] = totalSupply;
}
function transfer(address _to, uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value, "Insufficient balance");
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
}
应用:
- USDT、USDC(稳定币)
- UNI、AAVE(治理代币)
ERC-721(NFT,非同质化代币)
pragma solidity ^0.8.0;
contract MyNFT {
string public name = "My NFT";
string public symbol = "MNFT";
mapping(uint256 => address) public ownerOf;
mapping(address => uint256) public balanceOf;
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
function mint(address _to, uint256 _tokenId) public {
require(ownerOf[_tokenId] == address(0), "Token already exists");
ownerOf[_tokenId] = _to;
balanceOf[_to]++;
emit Transfer(address(0), _to, _tokenId);
}
function transferFrom(address _from, address _to, uint256 _tokenId) public {
require(ownerOf[_tokenId] == _from, "Not owner");
ownerOf[_tokenId] = _to;
balanceOf[_from]--;
balanceOf[_to]++;
emit Transfer(_from, _to, _tokenId);
}
}
应用:
- CryptoKitties(加密猫)
- Bored Ape Yacht Club
- OpenSea(NFT市场)
ERC-1155(多代币标准)
pragma solidity ^0.8.0;
contract MultiToken {
// 同时支持FT和NFT
mapping(uint256 => mapping(address => uint256)) public balanceOf;
function safeTransferFrom(
address _from,
address _to,
uint256 _id,
uint256 _amount,
bytes memory _data
) public {
require(balanceOf[_id][_from] >= _amount, "Insufficient balance");
balanceOf[_id][_from] -= _amount;
balanceOf[_id][_to] += _amount;
}
// 批量转账
function safeBatchTransferFrom(
address _from,
address _to,
uint256[] memory _ids,
uint256[] memory _amounts,
bytes memory _data
) public {
for (uint256 i = 0; i < _ids.length; i++) {
balanceOf[_ids[i]][_from] -= _amounts[i];
balanceOf[_ids[i]][_to] += _amounts[i];
}
}
}
优势:
- 一次交易可转账多种代币
- 节省Gas费
- 游戏道具(有些是FT,有些是NFT)
9. 哈希函数
特性
1. 确定性:相同输入总是产生相同输出
2. 快速计算:易于验证
3. 不可逆:无法从哈希值反推输入
4. 雪崩效应:输入微小变化,输出完全不同
5. 抗碰撞:很难找到两个不同输入产生相同输出
SHA-256示例
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
)
func main() {
data := "Hello, Blockchain!"
hash := sha256.Sum256([]byte(data))
fmt.Printf("原始数据: %s\n", data)
fmt.Printf("哈希值: %s\n", hex.EncodeToString(hash[:]))
// 修改一个字符
data2 := "Hello, Blockchain?"
hash2 := sha256.Sum256([]byte(data2))
fmt.Printf("\n修改后数据: %s\n", data2)
fmt.Printf("哈希值: %s\n", hex.EncodeToString(hash2[:]))
}
// 输出:
// 原始数据: Hello, Blockchain!
// 哈希值: a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146
//
// 修改后数据: Hello, Blockchain?
// 哈希值: 7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d906
在区块链中的应用
1. 区块哈希
- 标识区块
- 链式结构
2. 交易哈希
- 标识交易
- 防篡改
3. 默克尔树根
- 快速验证交易
- 轻节点验证
4. 地址生成
- 公钥 → 哈希 → 地址
5. 挖矿
- 寻找符合难度要求的哈希
10. 默克尔树(Merkle Tree)
结构
Merkle Root
/ \
Hash01 Hash23
/ \ / \
Hash0 Hash1 Hash2 Hash3
| | | |
Tx0 Tx1 Tx2 Tx3
代码实现
type MerkleTree struct {
RootNode *MerkleNode
}
type MerkleNode struct {
Left *MerkleNode
Right *MerkleNode
Data []byte
}
func NewMerkleNode(left, right *MerkleNode, data []byte) *MerkleNode {
node := &MerkleNode{}
if left == nil && right == nil {
// 叶子节点
hash := sha256.Sum256(data)
node.Data = hash[:]
} else {
// 非叶子节点
prevHash := append(left.Data, right.Data...)
hash := sha256.Sum256(prevHash)
node.Data = hash[:]
}
node.Left = left
node.Right = right
return node
}
func NewMerkleTree(data [][]byte) *MerkleTree {
var nodes []MerkleNode
// 创建叶子节点
for _, datum := range data {
node := NewMerkleNode(nil, nil, datum)
nodes = append(nodes, *node)
}
// 构建树
for len(nodes) > 1 {
var newLevel []MerkleNode
for i := 0; i < len(nodes); i += 2 {
left := &nodes[i]
right := &nodes[i+1]
parent := NewMerkleNode(left, right, nil)
newLevel = append(newLevel, *parent)
}
nodes = newLevel
}
return &MerkleTree{RootNode: &nodes[0]}
}
作用
1. 快速验证交易
- 只需要 log(n) 个哈希值
- 不需要下载整个区块
2. 轻节点(SPV)
- 只存储区块头(包含Merkle Root)
- 通过Merkle Proof验证交易
3. 防篡改
- 任何一个交易被修改
- Merkle Root都会变化
Merkle Proof示例
// 证明Tx2在区块中
func VerifyMerkleProof(tx []byte, proof [][]byte, root []byte) bool {
hash := sha256.Sum256(tx)
current := hash[:]
for _, p := range proof {
if isLeftNode {
combined := append(current, p...)
hash := sha256.Sum256(combined)
current = hash[:]
} else {
combined := append(p, current...)
hash := sha256.Sum256(combined)
current = hash[:]
}
}
return bytes.Equal(current, root)
}
结合简历的面试题
1. 从Web2到Web3的迁移经验
面试官会问:
"你在字节跳动做过高并发系统(50k+ QPS),这些经验如何应用到Web3?"
参考回答:
Web2经验:
- 50k+ QPS消费券系统
- 双机房容灾
- 监控告警
Web3应用:
1. 高并发经验
- 交易所撮合引擎
- NFT抢购(Gas优化)
- 预言机高频更新
2. 容灾经验
- 跨链桥多节点验证
- 智能合约多签钱包
- DEX多流动性池
3. 监控经验
- 链上数据监控
- 交易池监控
- 智能合约事件监听
2. Golang在区块链中的应用
面试官会问:
"你精通Golang,在区块链领域Golang有哪些应用?"
参考回答:
1. 公链开发
- Geth(以太坊客户端)
- Cosmos SDK
- Polkadot Substrate
2. 基础设施
- 区块浏览器
- 预言机节点
- 跨链桥
3. 性能优势
- 并发处理交易
- 高性能RPC节点
- 链下计算
示例:
- 使用Goroutine并发处理交易验证
- 使用Channel做交易池管理
- 使用Go的高性能网络库做P2P通信
3. 分布式系统与区块链
面试官会问:
"你有分布式系统经验,区块链的共识机制和传统分布式系统有什么区别?"
参考回答:
传统分布式系统(如Raft、Paxos):
- 节点身份已知
- 需要容许节点故障
- 强一致性
- 性能高
区块链(PoW/PoS):
- 节点身份未知(无许可)
- 需要容许恶意节点(拜占庭容错)
- 最终一致性
- 性能低
关键差异:
1. 信任模型
- 传统:信任节点
- 区块链:不信任任何节点
2. 激励机制
- 传统:无
- 区块链:代币激励
3. 数据不可篡改
- 传统:可以修改
- 区块链:不可篡改
Web3面试加分项
1. 实际经验
- 有智能合约开发经验(Solidity、Rust)
- 参与过DeFi项目
- 熟悉Web3工具(Hardhat、Foundry、Ethers.js)
- 了解主流公链(Ethereum、Solana、BSC)
2. 技术深度
- 理解EVM原理
- 了解零知识证明
- 熟悉跨链技术
- 了解Layer2扩容方案
3. 安全意识
- 智能合约安全审计
- 常见攻击手法(重入攻击、闪电贷攻击)
- 防御措施
4. 行业理解
- DeFi协议(Uniswap、Aave、Compound)
- NFT生态
- DAO治理
- 监管趋势