LOADING...
LOADING...
LOADING...
当前位置: 玩币族首页 > 区块链资讯 > Kava-3 主网 bug 修复报告

Kava-3 主网 bug 修复报告

2020-10-09 Kava 来源:区块链网络

摘要:目前 Kava 主网上有一个较小的 bug,会影响 BEP3 资产供应的调整,这意味着我们暂时无法上调 Kava CDP 内的 BNB 抵押额度(目前已触顶 40,000 BNB)。不过请放心,该 bug 不会影响用户资金的安全性。


我们已将 Kava 网络设计为一个结状结构

kava-3 网络使用参数来治理区块链的状态。通过治理改变参数,Kava 可以管理主链的运行方式,并在有时效性的紧急情况下用委员会治理来快速做出应对。我们发现在其中一个参数——BEP3 的资产供应限额上存在一个较小的 bug,导致参数值的变化无法生效,这意味着当前的供应限额 40,000BNB 无法更新。

如何修复 bug?

修复其实只需要更新几行代码,设置当供应限制的参数值更新时,强制执行应用的状态也相应更新。但值得注意的是,这对系统而言是一个大的变化,所以我们不能仅仅依靠发布一个新的 v0.8 版本来修复这个问题。

修复将如何实现?

异步网络更新

我们已经编写了一个软件版本,修复了这个小 bug。在 bug 修复中,我们指定了代码生效的时间。验证者需要在指定的时间之前更新自己的节点,确保网络顺利更新,不会出现服务中断的情况。任何遗留在上一版本软件上的节点都会在代码生效时被软分叉掉。这基本上也是以太坊核心开发者在“网络升级”时的操作。

软分叉

指区块链网络系统版本或协议升级后,旧的节点并不会意识到代码发生改变,并继续接受由新节点创造的区块,新老节点始终还是在同一条链上工作。


技术代码附录

接下来我们从技术角度来分析一下 Kava 代码中的这个 bug。这个问题代码在 Kava 的bep3 模块中。在该模块的参数中,支持的抵押资产被指定如下:

type AssetParam struct {
Denom string `json:"denom" yaml:"denom"` // name of the asset
CoinID int `json:"coin_id" yaml:"coin_id"` // internationally recognized coin ID
Limit sdk.Int `json:"limit" yaml:"limit"` // asset supply limit
Active bool `json:"active" yaml:"active"` // denotes if asset is active or paused
}

?? Github 链接:https://github.com/Kava-Labs/kava/blob/v0.8.1/x/bep3/types/params.go

每个抵押资产都规定了一个限额——即在网络限制进一步的传入交换之前,该资产可以抵押的最大数量。当主网启动时,以下代码为每个资产设置了初始限额:

// Initialize supported assets
for _, asset := range gs.Params.SupportedAssets {
zeroCoin := sdk.NewCoin(asset.Denom, sdk.NewInt(0))
supply := NewAssetSupply(asset.Denom, zeroCoin, zeroCoin,
zeroCoin, sdk.NewCoin(asset.Denom, asset.Limit))
keeper.SetAssetSupply(ctx, supply, []byte(asset.Denom))
}

?? Github 链接:https://github.com/Kava-Labs/kava/blob/v0.8.1/x/bep3/genesis.go#L29

SetAssetSupply函数为应用数据库中前缀0x02处的每个资产设置了限制:

// SetAssetSupply updates an asset's current active supply


func (k Keeper) SetAssetSupply(ctx sdk.Context, supply types.AssetSupply, denom []byte) {
store := prefix.NewStore(
ctx.KVStore(k.key),
types.AssetSupplyKeyPrefix, //0x02
)
bz := k.cdc.MustMarshalBinaryLengthPrefixed(supply)
store.Set(denom, bz)
}

?? Github 链接:https://github.com/Kava-Labs/kava/blob/869189054d68d6ec3e6446156ea0a91eb45af09c/x/bep3/keeper/keeper.go#L199

https://github.com/Kava-Labs/kava/blob/869189054d68d6ec3e6446156ea0a91eb45af09c/x/bep3/types/keys.go#L31

当系统更新AssetParam.Limit的参数值时,没有相应的函数更新数据库中的值(通过调用SetAssetSupply)。因此,更新参数不会传送到应用状态。


当一个新的交换被创建时,IncrementIncomingAssetSupply函数被调用,来检查交换资产量没有超过存储在前缀0x02的资产限制量。目前因为这个值没有被更新,所以交换没有通过这个检查。

// IncrementIncomingAssetSupply increments an asset's incoming supply
func (k Keeper) IncrementIncomingAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
supply, found := k.GetAssetSupply(ctx, []byte(coin.Denom))
if !found {
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
}
// Result of (current + incoming + amount) must be under asset's
//limit
totalSupply := supply.CurrentSupply.Add(supply.IncomingSupply)

if supply.SupplyLimit.IsLT(totalSupply.Add(coin)){
return sdkerrors.Wrapf(
types.ErrExceedsSupplyLimit,
"increase %s, asset supply %s, limit %s",
coin, totalSupply, supply.SupplyLimit,
)
}

...

?? Github 链接:https://github.com/Kava-Labs/kava/blob/869189054d68d6ec3e6446156ea0a91eb45af09c/x/bep3/keeper/swap.go#L70

https://github.com/Kava-Labs/kava/blob/869189054d68d6ec3e6446156ea0a91eb45af09c/x/bep3/keeper/asset.go#L46

我们的修复方法是在bep3 begin blocker中添加一个函数,当参数中的 AssetSupply 值更新时,该函数会更新 AssetSupply 的值。

// BeginBlocker on every block expires outdated atomic swaps, removes closed
// swap from long term storage (default storage time of 1 week), and updates
// asset supply limits that may have changed via governance.
func BeginBlocker(ctx sdk.Context, k Keeper) {
k.UpdateExpiredAtomicSwaps(ctx)
k.DeleteClosedAtomicSwapsFromLongtermStorage(ctx)
k.UpdateAssetSupplies(ctx)
}

UpdateAssetSupply 函数可以调节参数和数据库里的数值之间的差异,设置数据库与参数相匹配。

// UpdateAssetSupplies applies updates to the asset limit from parameters to the asset supplies
func (k Keeper) UpdateAssetSupplies(ctx sdk.Context) error {
params := k.GetParams(ctx)
for _, supportedAsset := range params.SupportedAssets {
asset, found := k.GetAssetSupply(
ctx, []byte(supportedAsset.Denom),
)
if !found {
continue
} if asset.SupplyLimit.Amount != supportedAsset.Limit {
asset.SupplyLimit = sdk.NewCoin(
supportedAsset.Denom, supportedAsset.Limit,
)
k.SetAssetSupply(ctx, asset, []byte(supportedAsset.Denom))
}
}
return nil
}

为了将其作为异步网络分叉来实现,我们在函数中添加一个activationTime参数,该参数指定UpdateAssetSupplies应该何时运行。例如,我们指定只有在ctx.BlockTime().After(activationTime)时才运行UpdateAssetSupply,并将激活时间设置为 bugfix 发布后一周。注意,ctx.BlockTime()是验证器集同意的区块时间的值,不受时钟漂移的影响。


—-

编译者/作者:Kava

玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。

LOADING...
LOADING...