Filecoin的Gas模型,引入了BaseFee,用来调节交易的拥堵情况。BaseFee,在区块拥堵或者区块交易不够的情况下,都会按照12.5%进行相应的调节。每笔交易的费用计算公式:(Gas Premium + Base Fee) * Gas Limit。其中BaseFee的部分会被燃烧掉,Gas Premium作为矿工的手续费。特别注意的是,GasLimit不要随意设置,多余的Gas Limit会被燃烧。
Filecoin开始Space Race了。矿工的实力都开始展现。官方的代码也有不少问题,几天时间,版本从0.5.1升级到0.5.6。好久不看go语言相关的逻辑,最近看了看Filecoin的Gas计算相关的逻辑,分享一下吧。本文分析的是0.5.6的逻辑,Lotus代码的最后一个提交信息如下:
commit 606a58bc6bc035ec0b90c6b50488e29e90f4238f
Author: Aayush Rajasekaran
Date: Sat Aug 29 00:56:24 2020 -0400
Lotus version 0.5.6
Lotus代码的CHANGELOG清晰记录了Gas费用模型的变化:从原来的limit/price,改成了limit/premium/feecap。新的Gas模型参考了EIP-1559:发送交易,交易费用不超过"feecaplimit"。矿工赚取的交易费是"premiumlimit"。简单的说,feecaplimit是Gas费用的上限,矿工能赚取的费用是premiumlimit。(feecap-premium)*limit的Gas费用会被燃烧。
feecap是如何设置的?limit是不是设置的越大越好?
Gas费用计算的相关逻辑实现在node/impl/full/gas.go中的GasEstimateMessageGas函数。接下来详细介绍Base/Limit/Premium/FeeCap。
每个区块都会设置一个baseFee。在该区块中的交易都需要燃烧相应的baseFee。注意baseFee,虽然名字看上去是fee,其实是price,具体燃烧的费用是baseFee*limit。baseFee相关的设置定义在build/params_shared_vals.go中:
const BlockGasLimit = 10_000_000_000
const BlockGasTarget = BlockGasLimit / 2
const BaseFeeMaxChangeDenom = 8 // 12.5%
const InitialBaseFee = 100e6
const MinimumBaseFee = 100
const PackingEfficiencyNum = 4
const PackingEfficiencyDenom = 5
在初始区块,baseFee设置为InitialBaseFee(10^8)。从当前的区块,生成下一个区块时,需要根据当前的区块的limit的总量确定,具体的逻辑请查看chain/store/basefee.go的ComputeBaseFee和computeNextBaseFee函数。
最小的baseFee - MinimumBaseFee (100)
区块Gas Limit - 区块中所有交易的Gas Limit的总和,在计算baseFee的时候,打了九折(PackingEfficiencyNum/PackingEfficiencyDenom)
区块Gas Limit的“超出”部分 - 每个区块存在Gas Limit的目标大小 - BlockGasTarget。超过BlockGasTarget的部分,视为超出部分。注意超出部分,可正可负。
更新的baseFee - 下一个区块的baseFee,在当前区块的baseFee的基础上增加超出部分的12.5%(BaseFeeMaxChangeDenom)。相关计算逻辑如下:
change := big.Mul(baseFee, big.NewInt(delta))
change = big.Div(change, big.NewInt(build.BlockGasTarget))
change = big.Div(change, big.NewInt(build.BaseFeeMaxChangeDenom))
简单的说,当前区块中的Gas Limit消耗超出了BlockGasTarget,则base Fee增加超出部分的12.5%。在这样的逻辑下,你会发现在交易多的情况下,base Fee会增加迅速增加和降低。
最新24小时的base Fee可以在飞狐浏览器查看(https://filfox.info/zh):
Gas Limit是指一个交易,愿意为交易执行支付的“油量”。一个交易消耗的Gas Limit几乎是固定的,计算过程请查看GasEstimateGasLimit函数。简单的说,当一个交易需要获取Gas Limit时,在目前区块高度上,“执行”该交易:
res, err := a.Stmgr.CallWithGas(ctx, &msg, priorMsgs, ts)
CallWithGas,只是为了获取执行过程消耗的Gas,并不真正改变当前的状态。
Gas Premium是指一个交易,愿意为交易执行支付的“油价”。GAS费用是油量乘以油价的结果。油量和交易本身有关,也几乎是固定的。显然的是,油价高,GAS费用高,矿工的收入就高,更愿意将交易优先打包。从交易发送者的角度,油价越低越好。Lotus代码给出一个计算Gas Premium的方法,请查看GasEstimateGasPremium函数,分为几步:
查看之前区块(4个 = 2*2)中所有交易,并按照Gas Premium从高到低排序
计算所有交易的“平均”Gas Premium。平均的意思是,找出一半油量消耗的Gas Premium:
at := build.BlockGasTarget * int64(blocks) / 2
prev1, prev2 := big.Zero(), big.Zero()
for _, price := range prices {
prev1, prev2 = price.price, prev1
at -= price.limit
if at > 0 {
continue
}
}
// mean 1, stddev 0.005 => 95% within +-1%
noise := 1 + rand.NormFloat64()*0.005
premium = types.BigMul(premium, types.NewInt(uint64(noise*(1
premium = types.BigDiv(premium, types.NewInt(1
除了Gas Premium,交易还需要支付Base Fee。也就是说,一般情况下,交易需要支付的费用是: (Gas Premium + Base Fee) * Gas Limit。问题是,Base Fee是变化的,有可能太大,交易发送者,不愿意支付。Gas Fee Cap(上限),就是设置支付费用的上限。相关的计算逻辑请看GasEstimateFeeCap函数。
parentBaseFee := ts.Blocks()[0].ParentBaseFee
increaseFactor := math.Pow(1.+1./float64(build.BaseFeeMaxChangeDenom), float64(maxqueueblks))
feeInFuture := types.BigMul(parentBaseFee, types.NewInt(uint64(increaseFactor*(1
feeInFuture = types.BigDiv(feeInFuture, types.NewInt(1
每个区块Base Fee按照12.5%的涨幅计算。
当前账户余额的百分之一,作为支付费用的上限:
maxAccepted := types.BigDiv(act.Balance, types.NewInt(MaxSpendOnFeeDenom))
上述两种情况下的最少值,作为Gas Fee Cap
众所周知,以太坊中的Gas Limit可以设置的非常大。一般情况下,多余的Gas费用会全数返还。特别注意的是,Filecoin并不完全是这样。因为Gas Limit参与了Base Fee和Gas Premium的计算,真实的Gas Limit是非常重要的。如果一个交易,设置了不合理的Gas Limit,Filecoin采取了一种惩罚机制。惩罚的Gas费用也被燃烧,计算逻辑看ComputeGasOverestimationBurn函数。
const (
gasOveruseNum = 11
gasOveruseDenom = 10
)
over := gasLimit - (gasOveruseNum*gasUsed)/gasOveruseDenom
Gas消耗的1.1倍以内认为是合理设置。
if over > gasUsed {
over = gasUsed
}
超出部分的上限是Gas的使用量。
gasToBurn := big.NewInt(gasLimit - gasUsed)
gasToBurn = big.Mul(gasToBurn, big.NewInt(over))
gasToBurn = big.Div(gasToBurn, big.NewInt(gasUsed))
简单的说,惩罚的是over/gasUsed的比例。如果over超过了gasUsed,就是所有罚光。
Filecoin的Gas模型,引入了BaseFee,用来调节交易的拥堵情况。BaseFee,在区块拥堵或者区块交易不够的情况下,都会按照12.5%进行相应的调节。每笔交易的费用计算公式:(Gas Premium + Base Fee) * Gas Limit。其中BaseFee的部分会被燃烧掉,Gas Premium作为矿工的手续费。特别注意的是,GasLimit不要随意设置,多余的Gas Limit会被燃烧。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!