While over-estimation fees and miner tips are still paid, gas is no longer burnt for direct, successful window PoSt messages. Usually, gas is burnt to prevent an attacker from spamming the network and to allow clients to "price" messages (using the base fee cap) based on how urgently they need them to be processed. However: 1. Window PoSt is already a "proof of work". 2. Miners need to submit WindowedPoSts on-time so all window post messages are urgent. 3. Work is already under way to move window post verification off-chain (making it effectively free). This change simply introduces the "free" part a bit earlier.
		
			
				
	
	
		
			108 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package vm
 | |
| 
 | |
| import (
 | |
| 	"github.com/filecoin-project/go-state-types/abi"
 | |
| 	"github.com/filecoin-project/go-state-types/big"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	gasOveruseNum   = 11
 | |
| 	gasOveruseDenom = 10
 | |
| )
 | |
| 
 | |
| type GasOutputs struct {
 | |
| 	BaseFeeBurn        abi.TokenAmount
 | |
| 	OverEstimationBurn abi.TokenAmount
 | |
| 
 | |
| 	MinerPenalty abi.TokenAmount
 | |
| 	MinerTip     abi.TokenAmount
 | |
| 	Refund       abi.TokenAmount
 | |
| 
 | |
| 	GasRefund int64
 | |
| 	GasBurned int64
 | |
| }
 | |
| 
 | |
| // ZeroGasOutputs returns a logically zeroed GasOutputs.
 | |
| func ZeroGasOutputs() GasOutputs {
 | |
| 	return GasOutputs{
 | |
| 		BaseFeeBurn:        big.Zero(),
 | |
| 		OverEstimationBurn: big.Zero(),
 | |
| 		MinerPenalty:       big.Zero(),
 | |
| 		MinerTip:           big.Zero(),
 | |
| 		Refund:             big.Zero(),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // ComputeGasOverestimationBurn computes amount of gas to be refunded and amount of gas to be burned
 | |
| // Result is (refund, burn)
 | |
| func ComputeGasOverestimationBurn(gasUsed, gasLimit int64) (int64, int64) {
 | |
| 	if gasUsed == 0 {
 | |
| 		return 0, gasLimit
 | |
| 	}
 | |
| 
 | |
| 	// over = gasLimit/gasUsed - 1 - 0.1
 | |
| 	// over = min(over, 1)
 | |
| 	// gasToBurn = (gasLimit - gasUsed) * over
 | |
| 
 | |
| 	// so to factor out division from `over`
 | |
| 	// over*gasUsed = min(gasLimit - (11*gasUsed)/10, gasUsed)
 | |
| 	// gasToBurn = ((gasLimit - gasUsed)*over*gasUsed) / gasUsed
 | |
| 	over := gasLimit - (gasOveruseNum*gasUsed)/gasOveruseDenom
 | |
| 	if over < 0 {
 | |
| 		return gasLimit - gasUsed, 0
 | |
| 	}
 | |
| 
 | |
| 	// if we want sharper scaling it goes here:
 | |
| 	// over *= 2
 | |
| 
 | |
| 	if over > gasUsed {
 | |
| 		over = gasUsed
 | |
| 	}
 | |
| 
 | |
| 	// needs bigint, as it overflows in pathological case gasLimit > 2^32 gasUsed = gasLimit / 2
 | |
| 	gasToBurn := big.NewInt(gasLimit - gasUsed)
 | |
| 	gasToBurn = big.Mul(gasToBurn, big.NewInt(over))
 | |
| 	gasToBurn = big.Div(gasToBurn, big.NewInt(gasUsed))
 | |
| 
 | |
| 	return gasLimit - gasUsed - gasToBurn.Int64(), gasToBurn.Int64()
 | |
| }
 | |
| 
 | |
| func ComputeGasOutputs(gasUsed, gasLimit int64, baseFee, feeCap, gasPremium abi.TokenAmount, chargeNetworkFee bool) GasOutputs {
 | |
| 	gasUsedBig := big.NewInt(gasUsed)
 | |
| 	out := ZeroGasOutputs()
 | |
| 
 | |
| 	baseFeeToPay := baseFee
 | |
| 	if baseFee.Cmp(feeCap.Int) > 0 {
 | |
| 		baseFeeToPay = feeCap
 | |
| 		out.MinerPenalty = big.Mul(big.Sub(baseFee, feeCap), gasUsedBig)
 | |
| 	}
 | |
| 
 | |
| 	// If chargeNetworkFee is disabled, just skip computing the BaseFeeBurn. However,
 | |
| 	// we charge all the other fees regardless.
 | |
| 	if chargeNetworkFee {
 | |
| 		out.BaseFeeBurn = big.Mul(baseFeeToPay, gasUsedBig)
 | |
| 	}
 | |
| 
 | |
| 	minerTip := gasPremium
 | |
| 	if big.Cmp(big.Add(baseFeeToPay, minerTip), feeCap) > 0 {
 | |
| 		minerTip = big.Sub(feeCap, baseFeeToPay)
 | |
| 	}
 | |
| 	out.MinerTip = big.Mul(minerTip, big.NewInt(gasLimit))
 | |
| 
 | |
| 	out.GasRefund, out.GasBurned = ComputeGasOverestimationBurn(gasUsed, gasLimit)
 | |
| 
 | |
| 	if out.GasBurned != 0 {
 | |
| 		gasBurnedBig := big.NewInt(out.GasBurned)
 | |
| 		out.OverEstimationBurn = big.Mul(baseFeeToPay, gasBurnedBig)
 | |
| 		minerPenalty := big.Mul(big.Sub(baseFee, baseFeeToPay), gasBurnedBig)
 | |
| 		out.MinerPenalty = big.Add(out.MinerPenalty, minerPenalty)
 | |
| 	}
 | |
| 
 | |
| 	requiredFunds := big.Mul(big.NewInt(gasLimit), feeCap)
 | |
| 	refund := big.Sub(requiredFunds, out.BaseFeeBurn)
 | |
| 	refund = big.Sub(refund, out.MinerTip)
 | |
| 	refund = big.Sub(refund, out.OverEstimationBurn)
 | |
| 	out.Refund = refund
 | |
| 	return out
 | |
| }
 |