学习 polygon-edge 源码和生态

前言

polygon-edge 源码版本:v0.6.3;
core-contracts 源码版本:pre-alpha

Poly Edge 的虚拟机兼容以太坊的EVM(采用与以太坊完全相同的指令集),可以完美使用以太坊的生态,尤其是solidty合约,以及以太坊生态的相关工具;Poly Edge 是基于插件体系的模块化建构,不是以fork 以太坊的方式,但实现了对以太坊链的兼容。

1. 架构概述

基于插件体系的模块化建构
1)libp2p:为 Supernets 提供网络层,是点对点的网络架构设计;
2)Bridge:由 PolyBFT 启用的内置桥接机制,允许在 Supernet 和另一个权益证明区块链之间传递消息,而无需映射;
3)Mempool:使多个验证节点能够聚合它们的签名,用来创建代表内存池中所有验证节点的单个聚合签名;
4)Consensus:PolyBFT 作为 Polygon Supernets 的共识机制,由一个共识引擎 IBFT 2.0 和一个包括 bridgestaking 和其他实用程序的共识协议组成;
5)Blockchain:协调系统中的一切,管理世界状态转换,并在新块添加到链中时负责状态更改;
6)Runtime (EVM):使用 EVM 作为执行智能合约的运行时环境;
7)TxPool:表示交易池,与系统中的其他模块紧密相连;
8)JSON-RPC:促进 dApp 开发人员与区块链之间的交互,允许开发人员向Supernets 节点发出 JSON-RPC 请求并接收响应;
9)gRPC:对于操作员交互至关重要,允许节点操作员轻松地与客户端交互,并提供无缝的用户体验。

下图说明了 Supernets 的主要组成部分。
基于插件体系的模块化建构

2. 数据结构

polygon-edge 中,区块和交易是重要的两个数据结构。

2.1 Block

type Block struct {
	Header       *Header
	Transactions []*Transaction
	Uncles       []*Header	// 叔块


	// Cache
	size atomic.Value // *uint64
}

// Header represents a block header in the Ethereum blockchain.
type Header struct {
	ParentHash   Hash
	Sha3Uncles   Hash
	Miner        []byte  // 矿工
	StateRoot    Hash
	TxRoot       Hash
	ReceiptsRoot Hash
	LogsBloom    Bloom  // 事件地址和事件 topic 的布隆滤波器
	Difficulty   uint64
	Number       uint64
	GasLimit     uint64
	GasUsed      uint64
	Timestamp    uint64
	ExtraData    []byte
	MixHash      Hash
	Nonce        Nonce
	Hash         Hash
}

polygon-edge 目前不支持以太坊最新的 EIP-1599 协议,其它部分和 ethereum 完全一致(虽然变量名称有些有区别,但数据类型完全一致,甚至映射的 json 名称也完全一致)。

2.2 Transaction

type Transaction struct {
	Nonce    uint64
	GasPrice *big.Int
	Gas      uint64
	To       *Address
	// 如果此交易用于发送和接收以太币,这里是接收账户中计算的Wei代币数量;
	// 如果此交易用于向合约发送消息调用,则这里是支付给接收此消息的智能合约的Wei金额;
	// 如果此交易用于创建合约,则此处为初始化合约时存储在账户中的Wei以太币数量。
	Value    *big.Int  	
	Input    []byte
	V        *big.Int  // V、R、S:加密签名中使用的值,可用于确定交易的发送方
	R        *big.Int
	S        *big.Int
	Hash     Hash
	From     Address


	// Cache
	size atomic.Value
}

从关键的block和transaction的数据结构来看,polygon-edge 的数据结构基本上遵循与ethereum 的数据结构一致的设计,他们稍有不同的地方,但不影响与传统ethereum链的跨链数据交换。

2.3 链结构

数据存储结构

3. 常见问题

3.1 怎么区分POS网络和Supernet网络?

  1. Polygon PoS 链只是一种短期临时的扩容解决方案,它的代价是牺牲了安全性和去中心化,母链是 EthereumSupernet 使用共识客户端 Edge 搭建多节点网络
  2. Polygon PoS 链仅使用其 EVM 合约在 PoS 链上保存带有交易数据的 Checkpoints(检查点),验证检查点的代码如下(core-contracts/contracts/root/CheckpointManager.sol:209):
    /**

     * @notice Internal function that performs checks on the checkpoint
     * @param prevId Current checkpoint ID
     * @param checkpoint The checkpoint to store
     */
    function _verifyCheckpoint(uint256 prevId, Checkpoint calldata checkpoint) private view {
        Checkpoint memory oldCheckpoint = checkpoints[prevId];
        require(
            checkpoint.epoch == oldCheckpoint.epoch || checkpoint.epoch == (oldCheckpoint.epoch + 1),
            "INVALID_EPOCH"
        );
        // 检查点的区块高度必须大于先前的区块高度
        require(checkpoint.blockNumber > oldCheckpoint.blockNumber, "EMPTY_CHECKPOINT");
    }

3.2 公链的奖励机制是怎样的?

(1)交易费用奖励:在Polygon公链上进行交易需要支付一定数量的交易费用,这些交易费用将被用于奖励验证人和参与者。验证人将获得交易费用的一部分作为奖励,以鼓励他们验证交易的合法性。同时,参与者也可以获得一定数量的交易费用作为奖励,以鼓励他们参与网络的建设和使用。验证器和参与者获得奖励的算法见 core-contracts/contracts/child/validator/RewardPool.sol:41:

    /**

     * @inheritdoc IRewardPool
     */
    function distributeRewardFor(uint256 epochId, Uptime[] calldata uptime) external onlySystemCall {
        require(paidRewardPerEpoch[epochId] == 0, "REWARD_ALREADY_DISTRIBUTED");
       	// 获取指定POS协议的回合内的区块总数
        uint256 totalBlocks = validatorSet.totalBlocks(epochId);
        require(totalBlocks != 0, "EPOCH_NOT_COMMITTED");
        uint256 epochSize = validatorSet.EPOCH_SIZE();
        // slither-disable-next-line divide-before-multiply
        // 计算基础奖励
        uint256 reward = (baseReward * totalBlocks) / epochSize;


		// 计算指定POS协议的回合内的总供应量
        uint256 totalSupply = validatorSet.totalSupplyAt(epochId);
        uint256 length = uptime.length;
        uint256 totalReward = 0;
        for (uint256 i = 0; i < length; i++) {
            Uptime memory data = uptime[i];
            require(data.signedBlocks <= totalBlocks, "SIGNED_BLOCKS_EXCEEDS_TOTAL");
            // slither-disable-next-line calls-loop
            // 获取指定回合内的验证者的余额
            uint256 balance = validatorSet.balanceOfAt(data.validator, epochId);
            // slither-disable-next-line divide-before-multiply
            // 计算签名奖励
            uint256 validatorReward = (reward * balance * data.signedBlocks) / (totalSupply * totalBlocks);
            pendingRewards[data.validator] += validatorReward;
            totalReward += validatorReward;
        }
        // 保存给定回合内的总报酬
        paidRewardPerEpoch[epochId] = totalReward;
        // 此方法可以重写
        // 转移总奖励
        _transferRewards(totalReward);
        emit RewardDistributed(epochId, totalReward);
    }

(2)质押奖励:在Polygon公链上,用户可以将自己的代币质押到网络中,以支持网络的安全性和稳定性。质押代币的用户将获得一定数量的奖励,这些奖励将从交易费用中提取出来,并按照一定比例分配给质押者。

验证者需要抵押一定数量的MATIC代币才能参与网络的验证和出块,同时也会获得相应的奖励。这些奖励会从代币总量中自动发行,因此也会释放一定的MATIC代币。

验证者抵押代币的操作步骤见 polygon 质押。下面的代码是验证者质押代币(core-contracts/contracts/root/staking/StakeManager.sol:36):

    function stakeFor(uint256 id, uint256 amount) external {
        require(id != 0 && id <= _chains.counter, "INVALID_ID");
        // slither-disable-next-line reentrancy-benign,reentrancy-events
        // 将币质押给当前合约
        matic.safeTransferFrom(msg.sender, address(this), amount);
        // calling the library directly once fixes the coverage issue
        // https://github.com/foundry-rs/foundry/issues/4854#issuecomment-1528897219
        // 增加质押量
        StakeManagerLib.addStake(_stakes, msg.sender, id, amount);
        ISupernetManager manager = managerOf(id);
        // 同步状态
        manager.onStake(msg.sender, amount);
        // slither-disable-next-line reentrancy-events
        emit StakeAdded(id, msg.sender, amount);
    }


(3)挖矿奖励:在Polygon公链上,用户还可以通过挖矿获得代币奖励。挖矿是一种参与网络的方式,它需要用户提供计算资源来验证交易和创建新的区块。挖矿奖励将从交易费用中提取出来,并按照一定比例分配给挖矿者。比例配置不是通过 config.go 设置的,而是通过合约设置的,见代码:core-contracts/contracts/interfaces/child/validator/IRewardPool.sol:23

	struct Uptime {
	    address validator;  // 挖矿者 || 验证者 || 参与者 || 质押者
	    uint256 signedBlocks; // 当前签名区块高度
	}


 	/// @notice distributes reward for the given epoch
    /// @dev transfers funds from sender to this contract
    /// @param uptime uptime data for every validator
    /// uptime 是一个数组
    function distributeRewardFor(uint256 epochId, Uptime[] calldata uptime) external;

(4)社区奖励:Polygon公链还将设立社区奖励,以鼓励社区成员参与网络的建设和推广。社区奖励将从交易费用中提取出来,并按照一定比例分配给社区成员。

3.4 如何计算允许故障的验证器数量?

polygon-edge/consensus/ibft/validators.go:10

func CalcMaxFaultyNodes(s validators.Validators) int {
	// N -> number of nodes in IBFT
	// F -> number of faulty nodes
	//
	// N = 3F + 1
	// => F = (N - 1) / 3
	//
	// IBFT tolerates 1 failure with 4 nodes
	// 4 = 3 * 1 + 1
	// To tolerate 2 failures, IBFT requires 7 nodes
	// 7 = 3 * 2 + 1
	// It should always take the floor of the result
	// (验证器数量-1)/3
	return (s.Len() - 1) / 3
}

3.5 如何计算提议节点(Proposer)?

polygon-edge/consensus/ibft/validators.go:70

func CalcProposer(
	validators validators.Validators,
	round uint64,
	lastProposer types.Address,
) validators.Validator {
	var seed uint64

	// 在最后一个提议者地址不为空的情况下
	if lastProposer == types.ZeroAddress {
		seed = round
	} else {
		offset := int64(0)


		// 取此地址在验证者集合中的位置
		if index := validators.Index(lastProposer); index != -1 {
			offset = index
		}

		// 加上当前共识轮数
		seed = uint64(offset) + round + 1
	}

	// 对验证者集合的长度求余
	pick := seed % uint64(validators.Len())

	return validators.At(pick)
}

3.6 Polygon 是如何工作?

用以太坊第一层区块链作为基础区块链,是构建分布式应用程序的基础,含共识机制和原生代币。第二层解决方案建立在第一层网络之上,在基础层上形成第二层。这些第二层扩展解决方案通常依赖基础层来实现安全性和共识,第二层网络从主梁或父链中取出批量交易,对其进行处理,然后将汇总数据返回到主链。

我猜“第二层网络从主梁或父链中取出批量交易,并对其进行处理”,这段逻辑没有写在 polygon-edge 中,而是通过 eth-event-tracker 来处理 polygon 感兴趣的区块事件,然后通过链合约把汇总数据返回到主链。

3.7 如何在 Polygon 上建立自己的DApp?

DApp是通过智能合约构建起来的,而在 polygon 上建立自己的 DApp ,就是在编写和部署智能合约。为了更容易开发 DApp ,我选择了 Truffle 中某个项目作为模块。

Truffle 是一个基于以太坊技术的开发、测试和部署框架,提供了很多项目模板,可以快速搭建一个 DApp。建议在 Truffle 项目中选择一个合适的项目模板,开发自己的 DApp

(1)安装 Truffle

$npm install -g truffle  

(2)创建一个项目
对于初学者来说,建议不要使用truffle init 初始化项目,因为该指令生成的项目是没有智能合约的裸项目,会缺乏 web 相关文件,无法更直观的看到开发效果。若要初始化 web 项目,可以使用

$truffle unbox webpack  			-- 构建一个基于webpack的项目

若要建立转移 Token 的项目,可以使用

$truffle unbox metacoin [PATH/TO/DIRECTORY]

(3)项目结构

app:项目的入口文件,里面包括了用于合约交互的 javascript,和用于显示前端的css等静态文件,只会在初始化 web 项目时生成;
contracts:合约代码的,默认会有三个合约
migrations:合约部署脚本、配置信息
test:测试应用程序和智能合约的测试文件目录
truffle.js:Truffle 项目主配置文件

(4)测试
若是基于模板初始化的项目,可以直接运行测试;若是通过 init 初始化的项目,则需要添加合适的合约和逻辑。要运行所有测试,可以使用:

$truffle test

更多关于测试信息,见文档

(5)编译合约

$truffle compile

(6)部署到网络

$truffle migrate    --默认配置是部署到本地的区块链网络

4. 生态

4.1 DApp

Polygon 生态内项目达数千个,DeFi、NFT、游戏占据主导。

Polygon 为了鼓励生态项目发展,推出了其基于 KPI 的流动性挖矿,根据每周平均用户数或 TVL 等 KPI 数据,将奖励分配给符合标准的 DApp。
在这里插入图片描述

4.2 主要产品

(1)Polygon PoS (是 Layer 1 的侧链);

(2)Polygon zkEVM(是基于 ZK Rollup 技术搭建的以太坊 Layer2 层 zkEVM 扩容方案,ZK Rollup 是利用「零知识证明」验证方式来落实 Rollup 的扩容方案。Polygon zkEVM 上线后是一个单独运行的区块网络,Polygon POS 链继续作为侧链运作。);

(3)Polygon Supernets(允许创建特定用例的专用区块链框架);

5. 参考

生态项目数逾千,一文纵览 Polygon 生态版图

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYyVMSiZ' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片