Skip to content

Commit

Permalink
get kip71config from governancedb and replace it with chainconfig in …
Browse files Browse the repository at this point in the history
…gasprice oracle
  • Loading branch information
yoomee1313 committed May 3, 2024
1 parent e5f1892 commit 10d70b1
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 66 deletions.
1 change: 1 addition & 0 deletions api/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type Backend interface {
SuggestTipCap(ctx context.Context) (*big.Int, error)
UpperBoundGasPrice(ctx context.Context) *big.Int
LowerBoundGasPrice(ctx context.Context) *big.Int
EffectiveParams(bn uint64) *params.GovParamSet
ChainDB() database.DBManager
EventMux() *event.TypeMux
AccountManager() accounts.AccountManager
Expand Down
14 changes: 14 additions & 0 deletions api/mocks/backend_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions node/cn/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,14 @@ func (b *CNAPIBackend) SuggestTipCap(ctx context.Context) (*big.Int, error) {
return b.gpo.SuggestTipCap(ctx)
}

func (b *CNAPIBackend) EffectiveParams(bn uint64) *params.GovParamSet {
pSet, err := b.cn.governance.EffectiveParams(bn)
if err != nil {
return nil
}
return pSet
}

func (b *CNAPIBackend) UpperBoundGasPrice(ctx context.Context) *big.Int {
bignum := b.CurrentBlock().Number()
pset, err := b.cn.governance.EffectiveParams(bignum.Uint64() + 1)
Expand Down
25 changes: 16 additions & 9 deletions node/cn/gasprice/feehistory.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,23 +96,30 @@ func (s sortGasAndReward) Less(i, j int) bool {
// the block field filled in, retrieves the block from the backend if not present yet and
// fills in the rest of the fields.
func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
chainconfig := oracle.backend.ChainConfig()
// TODO-Klaytn: If we implement baseFee feature like Ethereum does, we should set it from header, not constant.
var (
chainconfig = oracle.backend.ChainConfig()
isCurrBlockMagma = chainconfig.IsMagmaForkEnabled(big.NewInt(int64(bf.blockNumber)))
isNextBlockMagma = chainconfig.IsMagmaForkEnabled(big.NewInt(int64(bf.blockNumber + 1)))

currParamSet = oracle.backend.EffectiveParams(bf.blockNumber + 1)
kip71Config = chainconfig.Governance.KIP71
)
if currParamSet != nil {
kip71Config = currParamSet.ToKIP71Config()
}
if bf.results.baseFee = bf.header.BaseFee; bf.results.baseFee == nil {
bf.results.baseFee = new(big.Int).SetUint64(params.ZeroBaseFee)
}
// TODO-Klaytn: If we implement baseFee feature like Ethereum does, we should calculate nextBaseFee from parent block header.
if chainconfig.IsMagmaForkEnabled(big.NewInt(int64(bf.blockNumber + 1))) {
bf.results.nextBaseFee = misc.NextMagmaBlockBaseFee(bf.header, chainconfig.Governance.KIP71)
if isNextBlockMagma {
bf.results.nextBaseFee = misc.NextMagmaBlockBaseFee(bf.header, kip71Config)
} else {
bf.results.nextBaseFee = new(big.Int).SetUint64(params.ZeroBaseFee)
}

// Use MaxBlockGasUsedForBaseFee as gasLimit for gasUsedRatio.
if chainconfig.IsMagmaForkEnabled(big.NewInt(int64(bf.blockNumber))) {
// TODO-Klaytn: Instead of using chainConfig, we should use governance set values.
if chainconfig.Governance.KIP71.MaxBlockGasUsedForBaseFee != 0 {
bf.results.gasUsedRatio = float64(bf.header.GasUsed) / float64(chainconfig.Governance.KIP71.MaxBlockGasUsedForBaseFee)
if isCurrBlockMagma {
if kip71Config.MaxBlockGasUsedForBaseFee != 0 {
bf.results.gasUsedRatio = float64(bf.header.GasUsed) / float64(kip71Config.MaxBlockGasUsedForBaseFee)
}
}
if bf.results.gasUsedRatio == 0 {
Expand Down
89 changes: 40 additions & 49 deletions node/cn/gasprice/feehistory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ package gasprice

import (
"context"
"errors"
"fmt"
"math/big"
"testing"

"github.com/klaytn/klaytn/common"
"github.com/klaytn/klaytn/networks/rpc"
"github.com/klaytn/klaytn/params"
"github.com/stretchr/testify/assert"
)

func TestFeeHistory(t *testing.T) {
Expand All @@ -42,23 +43,25 @@ func TestFeeHistory(t *testing.T) {
}{
{1000, 1000, 10, 30, nil, 21, 10, nil},
{1000, 1000, 10, 30, []float64{0, 10}, 21, 10, nil},
{1000, 1000, 10, 30, []float64{20, 10}, 0, 0, errInvalidPercentile},
{1000, 1000, 10, 30, []float64{20, 10}, 0, 0, fmt.Errorf("%w: #%d:%f > #%d:%f", errInvalidPercentile, 0, 20.0000, 1, 10.0000)},
{1000, 1000, 1000000000, 30, nil, 0, 31, nil},
{1000, 1000, 1000000000, rpc.LatestBlockNumber, nil, 0, 33, nil},
{1000, 1000, 10, 40, nil, 0, 0, errRequestBeyondHead},
{1000, 1000, 10, 40, nil, 0, 0, fmt.Errorf("%w: requested %d, head %d", errRequestBeyondHead, 40, 32)},
{20, 2, 100, rpc.LatestBlockNumber, nil, 13, 20, nil},
{20, 2, 100, rpc.LatestBlockNumber, []float64{0, 10}, 31, 2, nil},
{20, 2, 100, 32, []float64{0, 10}, 31, 2, nil},
{1000, 1000, 1, rpc.PendingBlockNumber, nil, 0, 0, nil},
{1000, 1000, 2, rpc.PendingBlockNumber, nil, 32, 1, nil},
}
magmaBlock, dragonBlock := int64(16), int64(20)
backend := newTestBackend(t, big.NewInt(magmaBlock), big.NewInt(dragonBlock))
defer backend.teardown()
for i, c := range cases {
config := Config{
MaxHeaderHistory: c.maxHeader,
MaxBlockHistory: c.maxBlock,
MaxPrice: big.NewInt(500000000000),
}
backend := newTestBackend(t, nil, nil)
defer backend.teardown()
oracle := NewOracle(backend, config, nil)

first, reward, baseFee, ratio, err := oracle.FeeHistory(context.Background(), c.count, c.last, c.percent)
Expand All @@ -72,52 +75,40 @@ func TestFeeHistory(t *testing.T) {
expBaseFee++
}

if first.Uint64() != c.expFirst {
t.Fatalf("Test case %d: first block mismatch, want %d, got %d", i, c.expFirst, first)
}
if len(reward) != expReward {
t.Fatalf("Test case %d: reward array length mismatch, want %d, got %d", i, expReward, len(reward))
}
if len(baseFee) != expBaseFee {
t.Fatalf("Test case %d: baseFee array length mismatch, want %d, got %d", i, expBaseFee, len(baseFee))
}
if len(ratio) != c.expCount {
t.Fatalf("Test case %d: gasUsedRatio array length mismatch, want %d, got %d", i, c.expCount, len(ratio))
}
if err != c.expErr && !errors.Is(err, c.expErr) {
t.Fatalf("Test case %d: error mismatch, want %v, got %v", i, c.expErr, err)
}
assert.Equal(t, c.expFirst, first.Uint64(), "Test case %d: first block mismatch, want %d, got %d", i, c.expFirst, first.Uint64())
assert.Equal(t, expReward, len(reward), "Test case %d: reward array length mismatch, want %d, got %d", i, expReward, len(reward))
assert.Equal(t, expBaseFee, len(baseFee), "Test case %d: baseFee array length mismatch, want %d, got %d", i, expBaseFee, len(baseFee))
assert.Equal(t, c.expCount, len(ratio), "Test case %d: baseFee array length mismatch, want %d, got %d", i, c.expCount, len(ratio))
assert.Equal(t, c.expErr, err, "Test case %d: error mismatch, want %v, got %v", i, c.expErr, err)
}
}

func TestGasUsedRatioForMagma(t *testing.T) {
config := Config{
MaxHeaderHistory: 1000,
MaxBlockHistory: 1000,
}
backendNoMagma := newTestBackend(t, nil, nil)
defer backendNoMagma.teardown()
oracle := NewOracle(backendNoMagma, config, nil)
// Last check. Check the value of Reward, BaseFee and GasUsedRatio of every block.
var (
config = Config{
MaxHeaderHistory: 1000,
MaxBlockHistory: 1000,
MaxPrice: big.NewInt(500000000000),
}
oracle = NewOracle(backend, config, nil)

expectedRatio := 21000 / float64(params.UpperGasLimit)
_, _, _, ratio, _ := oracle.FeeHistory(context.Background(), 1, 30, nil)
if len(ratio) != 1 {
t.Fatalf("Wrong number of gas used ratio, want 1, got %d", len(ratio))
}
if ratio[0] != expectedRatio {
t.Fatalf("Gas used ratio mismatch, want %f, got %f", expectedRatio, ratio[0])
}
beforeMagmaExpectedBaseFee = big.NewInt(0)
atMagmaExpectedBaseFee = big.NewInt(int64(backend.EffectiveParams(16).LowerBoundBaseFee()))
afterMagmaExpectedBaseFee = big.NewInt(int64(backend.EffectiveParams(17).LowerBoundBaseFee()))

backendWithMagma := newTestBackend(t, common.Big0, nil)
defer backendWithMagma.teardown()
oracle = NewOracle(backendWithMagma, config, nil)
beforeMagmaExpectedGasUsedRatio = float64(21000) / float64(params.UpperGasLimit)
atMagmaExpectedGasUsedRatio = float64(21000) / float64(backend.EffectiveParams(16).MaxBlockGasUsedForBaseFee())
afterMagmaExpectedGasUsedRatio = float64(21000) / float64(backend.EffectiveParams(17).MaxBlockGasUsedForBaseFee())
)

expectedRatio = 21000 / float64(backendWithMagma.ChainConfig().Governance.KIP71.MaxBlockGasUsedForBaseFee)
_, _, _, ratio, _ = oracle.FeeHistory(context.Background(), 1, 30, nil)
if len(ratio) != 1 {
t.Fatalf("Wrong number of gas used ratio, want 1, got %d", len(ratio))
}
if ratio[0] != expectedRatio {
t.Fatalf("Gas used ratio mismatch, want %f, got %f", expectedRatio, ratio[0])
}
first, _, baseFee, ratio, err := oracle.FeeHistory(context.Background(), 32, rpc.LatestBlockNumber, nil)
assert.Equal(t, first, big.NewInt(1))
assert.Nil(t, err)

// magma hardfork
assert.Equal(t, []*big.Int{beforeMagmaExpectedBaseFee, atMagmaExpectedBaseFee, afterMagmaExpectedBaseFee}, baseFee[14:17])
assert.Equal(t, []float64{beforeMagmaExpectedGasUsedRatio, atMagmaExpectedGasUsedRatio, afterMagmaExpectedGasUsedRatio}, ratio[14:17])

// dragon hardfork
// check the value of reward
// assert.Equal(t, <impl>, gasTip[18:21])
}
1 change: 1 addition & 0 deletions node/cn/gasprice/gasprice.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type OracleBackend interface {
GetBlockReceipts(ctx context.Context, hash common.Hash) types.Receipts
ChainConfig() *params.ChainConfig
CurrentBlock() *types.Block
EffectiveParams(bn uint64) *params.GovParamSet
}

type TxPool interface {
Expand Down
25 changes: 17 additions & 8 deletions node/cn/gasprice/gasprice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/klaytn/klaytn/common/math"
"github.com/klaytn/klaytn/consensus/gxhash"
"github.com/klaytn/klaytn/crypto"
"github.com/klaytn/klaytn/governance"
"github.com/klaytn/klaytn/networks/rpc"
"github.com/klaytn/klaytn/params"
"github.com/klaytn/klaytn/storage/database"
Expand All @@ -39,7 +40,8 @@ import (
const testHead = 32

type testBackend struct {
chain *blockchain.BlockChain
governance governance.Engine
chain *blockchain.BlockChain
}

func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
Expand Down Expand Up @@ -74,6 +76,14 @@ func (b *testBackend) CurrentBlock() *types.Block {
return b.chain.CurrentBlock()
}

func (b *testBackend) EffectiveParams(bn uint64) *params.GovParamSet {
pSet, err := b.governance.EffectiveParams(bn + 1)
if err != nil {
return nil
}
return pSet
}

func (b *testBackend) teardown() {
b.chain.Stop()
}
Expand Down Expand Up @@ -101,18 +111,15 @@ func newTestBackend(t *testing.T, magmaBlock, dragonBlock *big.Int) *testBackend
config.ShanghaiCompatibleBlock = dragonBlock
config.CancunCompatibleBlock = dragonBlock
config.DragonCompatibleBlock = dragonBlock
if magmaBlock != nil {
config.Governance = params.GetDefaultGovernanceConfig()
config.Istanbul = params.GetDefaultIstanbulConfig()
config.Governance.KIP71.LowerBoundBaseFee = 0
}
config.Governance = params.GetDefaultGovernanceConfig()
config.Istanbul = params.GetDefaultIstanbulConfig()
blocks, _ := blockchain.GenerateChain(gspec.Config, genesis, gxhash.NewFaker(), db, testHead+1, func(i int, b *blockchain.BlockGen) {
toaddr := common.Address{}
// To test fee history, rewardbase should be different from the sender address
b.SetRewardbase(toaddr)

var txdata types.TxInternalData
if config.MagmaCompatibleBlock != nil && b.Number().Cmp(config.MagmaCompatibleBlock) >= 0 {
if config.IsMagmaForkEnabled(b.Number()) {
txdata = &types.TxInternalDataEthereumDynamicFee{
ChainID: gspec.Config.ChainID,
AccountNonce: b.TxNonce(addr),
Expand Down Expand Up @@ -142,9 +149,11 @@ func newTestBackend(t *testing.T, magmaBlock, dragonBlock *big.Int) *testBackend
if err != nil {
t.Fatalf("Failed to create local chain, %v", err)
}
gov := governance.NewMixedEngine(gspec.Config, db)
gov.SetBlockchain(chain)
chain.InsertChain(blocks)

return &testBackend{chain: chain}
return &testBackend{governance: gov, chain: chain}
}

func TestGasPrice_NewOracle(t *testing.T) {
Expand Down

0 comments on commit 10d70b1

Please sign in to comment.