Polygon POS共识
1.整体架构
2.共识层:PoS
2.1 侧链特性
-
完全独立的侧链架构
-
高性能原因:
-
预定义的生产者顺序
-
无需所有验证者竞争
-
简化的区块验证流程
3. Bor 共识机制
3.1 验证者轮换系统
Span 时期(6400块):
-
负责验证者集合的管理和更新
-
验证者集合的更替周期
Sprint 冲刺(64块):
-
负责具体的区块生产和生产者轮换
-
是区块生产的基本单位
3.2 核心机制
通过划分 span/sprint,预先指定生产者
生产者签名生产区块
其他验证者只要验证生产者没有问题,就存入数据库
每256个区块设置一个检查点,把根 hash 同步到以太坊
3.3 验证者管理
验证者集合约有100个成员
质押条件:合约配置验证者个数,通过排队按照质押量优先选择
验证者的质押/解质押在以太坊上进行
3.4 验证者筛选
每个 Sprint 周期有一组预选的验证者
其他验证者会自动验证区块,但不需要显式投票
3.5 生产者筛选
验证者按照优先级轮流生产区块
生产顺序:预定义的生产者顺序
生产者从验证者集合中轮换选出:
-
1个主生产者
-
2个备份生产者
一个区块只需要一个生产者的签名
3.6 区块验证
verifyHeader - 基本参数验证
func (c *Bor) verifyHeader(...) error {
// 1. 验证区块号
if header.Number == nil {
return errUnknownBlock
}
// 2. 验证时间戳
if header.Time > now {
return consensus.ErrFutureBlock
}
// 3. 验证Extra字段格式
if err := validateHeaderExtraField(header.Extra); err != nil {
return err
}
// 4. 验证Sprint结束时的验证者列表
isSprintEnd := IsSprintStart(number+1, c.config.CalculateSprint(number))
if isSprintEnd && signersBytes%validatorHeaderBytesLength != 0 {
return errInvalidSpanValidators
}
// 5. 验证Gas限制
if header.GasLimit > gasCap {
return fmt.Errorf("invalid gasLimit")
}
// 6. 验证难度值
if header.Difficulty == nil {
return errInvalidDifficulty
}
}
verifySeal - 签名和权限验证
func (c *Bor) verifySeal(...) error {
// 1. 获取当前快照
snap, err := c.snapshot(chain, number-1, header.ParentHash, parents)
// 2. 恢复签名者地址
signer, err := ecrecover(header, c.signatures, c.config)
// 3. 验证签名者是否在验证者集合中
if !snap.ValidatorSet.HasAddress(signer) {
return &UnauthorizedSignerError{number - 1, signer.Bytes()}
}
// 4. 获取签名者的顺序号
succession, err := snap.GetSignerSuccessionNumber(signer)
// 5. 验证区块时间是否过早
if IsBlockEarly(parent, header, number, succession, c.config) {
return &BlockTooSoonError{number, succession}
}
// 6. 验证难度值是否正确
difficulty := Difficulty(snap.ValidatorSet, signer)
if header.Difficulty.Uint64() != difficulty {
return &WrongDifficultyError{...}
}
}
3.7 分叉解决
强制回滚:
-
如果检查点未获得确认,节点必须回滚到最近的确认检查点
-
这可能导致已经写入数据库的区块被丢弃
-
用户需要等待交易重新打包
4 Heimdall 验证者集合的管理
4.1 主要功能
-
提供 gRPC 服务给 bor 调用
-
质押管理
-
检测点提交
-
跨链通讯
-
状态同步
-
惩罚机制
4.2 验证者管理
验证者的质押/解质押在以太坊上进行
Heimdall 层定期(每~256个区块)创建检查点:
检查内容:定期对一段区块进行确认,计算这些区块的默克尔树根哈希,将确认信息提交到以太坊主网
ValidateCheckpoint
func ValidateCheckpoint(
start uint64, // 起始区块高度
end uint64, // 结束区块高度
rootHash hmTypes.HeimdallHash, // 检查点的根哈希
checkpointLength uint64, // 检查点长度
contractCaller helper.IContractCaller, // 合约调用接口
confirmations uint64 // 确认数
) (bool, error) {
// 1. 检查本地是否有这些区块数据
if !contractCaller.CheckIfBlocksExist(end + confirmations) {
return false, errors.New("blocks not found locally")
}
// 2. 计算根哈希并比较
root, err := contractCaller.GetRootHash(start, end, checkpointLength)
if err != nil {
return false, err
}
// 3. 验证计算出的根哈希与提供的根哈希是否一致
if bytes.Equal(root, rootHash.Bytes()) {
return true, nil
}
return false, nil
}
检查点获得2/3验证者确认
func (app *HeimdallApp) BeginSideBlocker(ctx sdk.Context, req abci.RequestBeginSideBlock) (res abci.ResponseBeginSideBlock) {
// 1. 检查区块高度是否大于2
height := ctx.BlockHeader().Height
if height <= 2 {
return
}
// 2. 计算目标高度(当前高度-2)
targetHeight := height - 2 // sidechannel takes 2 blocks to process
logger := app.Logger()
logger.Debug("[sidechannel] Processing side block", "height", height, "targetHeight", targetHeight)
// 3. 获取所有验证者
validators := app.SidechannelKeeper.GetValidators(ctx, height)
if len(validators) == 0 {
return
}
// 4. 计算总投票权重
var totalPower int64
for _, v := range validators {
totalPower = totalPower + v.Power
}
// 5. 处理每个侧链交易结果
events := sdk.EmptyEvents()
for _, sideTxResult := range req.SideTxResults {
txHash := sideTxResult.TxHash
// 获取交易数据
tx := app.SidechannelKeeper.GetTx(ctx, targetHeight, txHash)
if tx != nil {
// 移除交易避免重复执行
app.SidechannelKeeper.RemoveTx(ctx, targetHeight, txHash)
// 统计投票结果
usedValidator := make(map[int]bool)
signedPower := make(map[abci.SideTxResultType]int64)
signedPower[abci.SideTxResultType_Yes] = 0
signedPower[abci.SideTxResultType_Skip] = 0
signedPower[abci.SideTxResultType_No] = 0
// 6. 处理每个验证者的投票
for _, sigObj := range sideTxResult.Sigs {
if i := getValidatorIndexByAddress(sigObj.Address, validators); i != -1 {
if _, ok := usedValidator[i]; !ok {
signedPower[sigObj.Result] += validators[i].Power
usedValidator[i] = true
}
}
}
// 7. 根据投票结果执行交易
var result sdk.Result
if signedPower[abci.SideTxResultType_Yes] >= (totalPower*2/3 + 1) {
// 赞成票超过2/3,执行交易
result = app.runTx(ctx, tx, abci.SideTxResultType_Yes)
} else if signedPower[abci.SideTxResultType_No] >= (totalPower*2/3 + 1) {
// 反对票超过2/3,拒绝交易
result = app.runTx(ctx, tx, abci.SideTxResultType_No)
} else {
// 其他情况跳过交易
result = app.runTx(ctx, tx, abci.SideTxResultType_Skip)
}
events = events.AppendEvents(result.Events)
}
}
// 8. 处理剩余未处理的交易
txs := app.SidechannelKeeper.GetTxs(ctx, targetHeight)
for _, tx := range txs {
app.SidechannelKeeper.RemoveTx(ctx, targetHeight, tx.Hash())
result := app.runTx(ctx, tx, abci.SideTxResultType_Skip)
events = events.AppendEvents(result.Events)
}
res.Events = events.ToABCIEvents()
return res
}
4.3 跨链桥接
作为 Polygon(Matic) 和以太坊之间的桥接点
4.4 状态同步机制
同步系统合约的状态
4.5 资产管理
核心的安全性和资产管理都依赖于以太坊主网
5. 系统合约架构
-
总结
Polygon PoS 链通过其独特的架构设计实现了高性能和安全性的平衡:
双层架构:
-
Heimdall 验证层负责验证者管理和检查点提交
-
Bor 执行层负责实际的区块生产和交易执行
高效共识:
-
预定义的生产者顺序提高了效率
-
Sprint/Span 机制优化了验证者轮换
-
简化的区块验证流程提升了性能
安全保障:
-
利用以太坊主网的安全性
-
检查点机制确保最终性
-
完善的验证者质押和惩罚机制
创新特点:
-
完全兼容以太坊
-
高性能的交易处理
-
灵活的扩展性
这种设计使得 Polygon 成为一个真正的以太坊侧链解决方案,既保持了与以太坊的紧密集成,又实现了高性能的交易处理能力。

浙公网安备 33010602011771号