Skip to content

Commit

Permalink
gas: Add tests to median premium math
Browse files Browse the repository at this point in the history
  • Loading branch information
magik6k committed Sep 9, 2020
1 parent 2aba16e commit f695c0c
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 28 deletions.
61 changes: 33 additions & 28 deletions node/impl/full/gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ package full

import (
"context"
"math"
"math/rand"
"sort"

"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"math"
"math/rand"
"sort"

"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
Expand Down Expand Up @@ -50,18 +49,42 @@ func (a *GasAPI) GasEstimateFeeCap(ctx context.Context, msg *types.Message, maxq
return out, nil
}

type gasMeta struct {
price big.Int
limit int64
}

func medianGasPremium(prices []gasMeta, blocks int) abi.TokenAmount {
sort.Slice(prices, func(i, j int) bool {
// sort desc by price
return prices[i].price.GreaterThan(prices[j].price)
})

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 {
break
}
}

premium := prev1
if prev2.Sign() != 0 {
premium = big.Div(types.BigAdd(prev1, prev2), types.NewInt(2))
}

return premium
}

func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
sender address.Address, gaslimit int64, _ types.TipSetKey) (types.BigInt, error) {

if nblocksincl == 0 {
nblocksincl = 1
}

type gasMeta struct {
price big.Int
limit int64
}

var prices []gasMeta
var blocks int

Expand Down Expand Up @@ -92,25 +115,7 @@ func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
ts = pts
}

sort.Slice(prices, func(i, j int) bool {
// sort desc by price
return prices[i].price.GreaterThan(prices[j].price)
})

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 {
break
}
}

premium := prev1
if prev2.Sign() != 0 {
premium = big.Div(types.BigAdd(prev1, prev2), types.NewInt(2))
}
premium := medianGasPremium(prices, blocks)

if types.BigCmp(premium, types.NewInt(MinGasPremium)) < 0 {
switch nblocksincl {
Expand Down
40 changes: 40 additions & 0 deletions node/impl/full/gas_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package full

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/filecoin-project/go-state-types/big"

"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
)

func TestMedian(t *testing.T) {
require.Equal(t, types.NewInt(5), medianGasPremium([]gasMeta{
{big.NewInt(5), build.BlockGasTarget},
}, 1))

require.Equal(t, types.NewInt(10), medianGasPremium([]gasMeta{
{big.NewInt(5), build.BlockGasTarget},
{big.NewInt(10), build.BlockGasTarget},
}, 1))

require.Equal(t, types.NewInt(15), medianGasPremium([]gasMeta{
{big.NewInt(10), build.BlockGasTarget / 2},
{big.NewInt(20), build.BlockGasTarget / 2},
}, 1))

require.Equal(t, types.NewInt(25), medianGasPremium([]gasMeta{
{big.NewInt(10), build.BlockGasTarget / 2},
{big.NewInt(20), build.BlockGasTarget / 2},
{big.NewInt(30), build.BlockGasTarget / 2},
}, 1))

require.Equal(t, types.NewInt(15), medianGasPremium([]gasMeta{
{big.NewInt(10), build.BlockGasTarget / 2},
{big.NewInt(20), build.BlockGasTarget / 2},
{big.NewInt(30), build.BlockGasTarget / 2},
}, 2))
}

0 comments on commit f695c0c

Please sign in to comment.