Layer2 扩容解决方案详解 🔄
1. Layer2 基础概念
1.1 什么是 Layer2?
Layer2 是建立在以太坊主网(Layer1)之上的扩容解决方案,它:
- 继承以太坊的安全性
- 提供更高的交易吞吐量
- 降低交易费用
- 保持去中心化特性
1.2 主要类型
- Rollups
- Optimistic Rollups
- ZK Rollups
- 状态通道
- Plasma
- Validium
2. Optimistic Rollups
2.1 工作原理
contract OptimisticRollup {
struct Transaction {
address from;
address to;
uint256 value;
bytes data;
}
struct Batch {
bytes32 stateRoot;
Transaction[] transactions;
uint256 timestamp;
}
mapping(uint256 => Batch) public batches;
uint256 public currentBatch;
// 挑战期
uint256 public constant CHALLENGE_PERIOD = 7 days;
function submitBatch(
bytes32 newStateRoot,
Transaction[] calldata transactions
) external {
// 提交新批次
batches[currentBatch] = Batch({
stateRoot: newStateRoot,
transactions: transactions,
timestamp: block.timestamp
});
emit BatchSubmitted(currentBatch, newStateRoot);
currentBatch++;
}
function challengeBatch(
uint256 batchId,
bytes calldata proof
) external {
require(
block.timestamp <= batches[batchId].timestamp + CHALLENGE_PERIOD,
"Challenge period expired"
);
// 验证挑战证明
require(verifyProof(proof), "Invalid fraud proof");
// 回滚状态
revertBatch(batchId);
}
}
2.2 交易提交
async function submitToOptimisticRollup(transaction) {
const rollupProvider = new ethers.providers.JsonRpcProvider(ROLLUP_RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, rollupProvider);
// 构建交易
const tx = await wallet.sendTransaction({
to: transaction.to,
value: transaction.value,
data: transaction.data
});
// 等待交易确认
await tx.wait();
// 等待状态根提交到 L1
await waitForStateCommitment(tx.hash);
}
3. ZK Rollups
3.1 基础实现
contract ZKRollup {
struct ZKProof {
uint256[2] a;
uint256[2][2] b;
uint256[2] c;
}
struct Batch {
bytes32 stateRoot;
bytes32 transactionsHash;
ZKProof proof;
}
mapping(uint256 => Batch) public batches;
function verifyAndSubmitBatch(
bytes32 newStateRoot,
bytes32 txHash,
ZKProof calldata proof
) external {
require(verifyZKProof(proof), "Invalid ZK proof");
batches[currentBatch] = Batch({
stateRoot: newStateRoot,
transactionsHash: txHash,
proof: proof
});
emit BatchVerified(currentBatch, newStateRoot);
}
}
3.2 证明生成
async function generateZKProof(transactions, state) {
// 使用 circom 和 snarkjs 生成证明
const circuit = await compileCircuit("rollup.circom");
const setup = await generateSetup(circuit);
const input = {
transactions: transactions,
oldState: state.old,
newState: state.new
};
const proof = await generateProof(circuit, input, setup);
return proof;
}
4. 状态通道
4.1 支付通道
contract PaymentChannel {
address public participant1;
address public participant2;
uint256 public expiresAt;
mapping(address => uint256) public balances;
constructor(address _participant2) payable {
participant1 = msg.sender;
participant2 = _participant2;
balances[msg.sender] = msg.value;
expiresAt = block.timestamp + 1 days;
}
function closeChannel(
uint256 amount1,
uint256 amount2,
bytes memory signature1,
bytes memory signature2
) external {
require(
verifySignature(amount1, amount2, signature1, participant1) &&
verifySignature(amount1, amount2, signature2, participant2),
"Invalid signatures"
);
balances[participant1] = amount1;
balances[participant2] = amount2;
// 分配资金
payable(participant1).transfer(amount1);
payable(participant2).transfer(amount2);
}
}
4.2 状态更新
async function updateChannelState(channel, newState) {
// 签名新状态
const signature = await wallet.signMessage(
ethers.utils.arrayify(
ethers.utils.solidityKeccak256(
["address", "uint256", "uint256"],
[channel.address, newState.amount1, newState.amount2]
)
)
);
// 交换签名
await exchangeSignatures(channel.counterparty, signature);
return {
state: newState,
signature: signature
};
}
5. Plasma
5.1 Plasma Chain
contract PlasmaChain {
struct PlasmaBlock {
bytes32 root; // Merkle root
uint256 timestamp;
address operator;
}
mapping(uint256 => PlasmaBlock) public plasmaBlocks;
uint256 public currentBlock;
function submitBlock(bytes32 root) external {
plasmaBlocks[currentBlock] = PlasmaBlock({
root: root,
timestamp: block.timestamp,
operator: msg.sender
});
emit BlockSubmitted(currentBlock, root);
currentBlock++;
}
function withdraw(
uint256 blockNum,
bytes calldata txBytes,
bytes32[] calldata proof
) external {
require(
verifyMerkleProof(
plasmaBlocks[blockNum].root,
keccak256(txBytes),
proof
),
"Invalid merkle proof"
);
// 处理提款
processWithdrawal(txBytes);
}
}
5.2 Merkle 树实现
class MerkleTree {
constructor(leaves) {
this.leaves = leaves.map(leaf => keccak256(leaf));
this.layers = [this.leaves];
this.buildTree();
}
buildTree() {
while (this.layers[this.layers.length - 1].length > 1) {
this.layers.push(
this.getNextLayer(this.layers[this.layers.length - 1])
);
}
}
getProof(index) {
let proof = [];
let currentIndex = index;
for (let i = 0; i < this.layers.length - 1; i++) {
const layer = this.layers[i];
const isRight = currentIndex % 2;
const pairIndex = isRight ? currentIndex - 1 : currentIndex + 1;
if (pairIndex < layer.length) {
proof.push(layer[pairIndex]);
}
currentIndex = Math.floor(currentIndex / 2);
}
return proof;
}
}
6. 跨 Layer 通信
6.1 消息桥接
contract MessageBridge {
mapping(bytes32 => bool) public processedMessages;
event MessageSent(
address indexed from,
address indexed to,
bytes data,
uint256 nonce
);
function sendMessage(
address to,
bytes calldata data
) external {
bytes32 messageHash = keccak256(
abi.encodePacked(
msg.sender,
to,
data,
block.number
)
);
emit MessageSent(msg.sender, to, data, block.number);
}
function receiveMessage(
address from,
address to,
bytes calldata data,
uint256 nonce,
bytes calldata proof
) external {
bytes32 messageHash = keccak256(
abi.encodePacked(from, to, data, nonce)
);
require(
!processedMessages[messageHash],
"Message already processed"
);
require(
verifyMessageProof(messageHash, proof),
"Invalid message proof"
);
processedMessages[messageHash] = true;
// 执行跨层消息
executeMessage(to, data);
}
}
6.2 资产桥接
contract TokenBridge {
mapping(address => mapping(address => uint256)) public deposits;
function deposit(address token, uint256 amount) external {
IERC20(token).transferFrom(msg.sender, address(this), amount);
deposits[token][msg.sender] += amount;
emit Deposit(msg.sender, token, amount);
}
function withdraw(
address token,
uint256 amount,
bytes calldata proof
) external {
require(
verifyWithdrawalProof(
msg.sender,
token,
amount,
proof
),
"Invalid withdrawal proof"
);
deposits[token][msg.sender] -= amount;
IERC20(token).transfer(msg.sender, amount);
emit Withdrawal(msg.sender, token, amount);
}
}
7. 性能优化
7.1 批处理优化
contract BatchProcessor {
struct Batch {
bytes32[] txHashes;
uint256 timestamp;
bytes32 merkleRoot;
}
function processBatch(Batch calldata batch) external {
require(
verifyBatchMerkleRoot(batch.txHashes, batch.merkleRoot),
"Invalid merkle root"
);
for (uint i = 0; i < batch.txHashes.length; i++) {
processTransaction(batch.txHashes[i]);
}
}
}
7.2 数据压缩
function compressTransactionData(transactions) {
// 使用 RLP 编码
const encoded = ethers.utils.RLP.encode(
transactions.map(tx => [
tx.nonce,
tx.gasPrice,
tx.gasLimit,
tx.to,
tx.value,
tx.data
])
);
// 使用 zlib 压缩
return zlib.deflateSync(encoded);
}
8. 相关资源
- Optimism 文档
- zkSync 文档
- Arbitrum 文档
- Polygon 文档
- Layer2 生态概览