Skip to content

Commit

Permalink
Introduce baseFeeChangeDenom network parameter (#1872)
Browse files Browse the repository at this point in the history
* Introduce baseFeeChangeDenom network parameter

* Fixed tests and new e2e test for `baseFeeChangeDenom` network parameter (#1901)

* fixed tests and new e2e test for baseFeeDenom

* comment fix

* fix test `TestGovernanceManager_PostEpoch`

* Fix unit tests

* Fix unit test

* fix governance e2e test

* Minor updates

---------

Co-authored-by: Stefan Negovanović <stefan@ethernal.tech>

* Update blockchain configuration when block is inserted

* Rename

* Implement latest chain config as callback

* UT fix

* Update SCs

* Additional test cases

* E2E execution timeout

* Address comment

---------

Co-authored-by: Dusan Nosovic <118283942+dusannosovic-ethernal@users.noreply.github.com>
  • Loading branch information
Stefan-Ethernal and dusannosovic-ethernal committed Sep 13, 2023
1 parent 5dd861f commit 5241598
Show file tree
Hide file tree
Showing 31 changed files with 565 additions and 186 deletions.
35 changes: 24 additions & 11 deletions blockchain/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,18 @@ import (
"sync"
"sync/atomic"

"github.com/hashicorp/go-hclog"
lru "github.com/hashicorp/golang-lru"

"github.com/0xPolygon/polygon-edge/blockchain/storage"
"github.com/0xPolygon/polygon-edge/chain"
"github.com/0xPolygon/polygon-edge/helper/common"
"github.com/0xPolygon/polygon-edge/state"
"github.com/0xPolygon/polygon-edge/types"
"github.com/0xPolygon/polygon-edge/types/buildroot"

"github.com/hashicorp/go-hclog"
lru "github.com/hashicorp/golang-lru"
)

const (
// defaultBaseFeeChangeDenom is the value to bound the amount the base fee can change between blocks.
defaultBaseFeeChangeDenom = 8

// blockGasTargetDivisor is the bound divisor of the gas limit, used in update calculations
blockGasTargetDivisor uint64 = 1024

Expand Down Expand Up @@ -92,6 +89,7 @@ type Verifier interface {
ProcessHeaders(headers []*types.Header) error
GetBlockCreator(header *types.Header) (types.Address, error)
PreCommitState(block *types.Block, txn *state.Transition) error
GetLatestChainConfig() (*chain.Params, error)
}

type Executor interface {
Expand Down Expand Up @@ -1362,7 +1360,7 @@ func (b *Blockchain) CalculateBaseFee(parent *types.Header) uint64 {
}

// Check if this is the first London hardfork block.
// Should return chain.GenesisBaseFee ins this case.
// Should return chain.GenesisBaseFee in this case.
if parent.BaseFee == 0 {
if b.config.Genesis.BaseFee > 0 {
return b.config.Genesis.BaseFee
Expand All @@ -1381,22 +1379,37 @@ func (b *Blockchain) CalculateBaseFee(parent *types.Header) uint64 {
// If the parent block used more gas than its target, the baseFee should increase.
if parent.GasUsed > parentGasTarget {
gasUsedDelta := parent.GasUsed - parentGasTarget
baseFeeDelta := calcBaseFeeDelta(gasUsedDelta, parentGasTarget, parent.BaseFee)
baseFeeDelta := b.calcBaseFeeDelta(gasUsedDelta, parentGasTarget, parent.BaseFee)

return parent.BaseFee + common.Max(baseFeeDelta, 1)
}

// Otherwise, if the parent block used less gas than its target, the baseFee should decrease.
gasUsedDelta := parentGasTarget - parent.GasUsed
baseFeeDelta := calcBaseFeeDelta(gasUsedDelta, parentGasTarget, parent.BaseFee)
baseFeeDelta := b.calcBaseFeeDelta(gasUsedDelta, parentGasTarget, parent.BaseFee)

return common.Max(parent.BaseFee-baseFeeDelta, 0)
}

func calcBaseFeeDelta(gasUsedDelta, parentGasTarget, baseFee uint64) uint64 {
func (b *Blockchain) calcBaseFeeDelta(gasUsedDelta, parentGasTarget, baseFee uint64) uint64 {
baseFeeChangeDenom := chain.BaseFeeChangeDenom

if b.Config().Forks.IsActive(chain.Governance, b.Header().Number) {
chainConfig, err := b.consensus.GetLatestChainConfig()
if err != nil {
b.logger.Error("failed to calculate base fee delta", "error", err)

return baseFeeChangeDenom
}

if chainConfig != nil {
baseFeeChangeDenom = chainConfig.BaseFeeChangeDenom
}
}

y := baseFee * gasUsedDelta / parentGasTarget

return y / defaultBaseFeeChangeDenom
return y / baseFeeChangeDenom
}

func (b *Blockchain) writeBatchAndUpdate(
Expand Down
157 changes: 140 additions & 17 deletions blockchain/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1369,19 +1369,127 @@ func TestBlockchain_CalculateBaseFee(t *testing.T) {
parentBaseFee uint64
parentGasLimit uint64
parentGasUsed uint64
expectedBaseFee uint64
elasticityMultiplier uint64
forks *chain.Forks
getLatestConfigFn getChainConfigDelegate
expectedBaseFee uint64
}{
{6, chain.GenesisBaseFee, 20000000, 10000000, chain.GenesisBaseFee, 2}, // usage == target
{6, chain.GenesisBaseFee, 20000000, 10000000, 1125000000, 4}, // usage == target
{6, chain.GenesisBaseFee, 20000000, 9000000, 987500000, 2}, // usage below target
{6, chain.GenesisBaseFee, 20000000, 9000000, 1100000000, 4}, // usage below target
{6, chain.GenesisBaseFee, 20000000, 11000000, 1012500000, 2}, // usage above target
{6, chain.GenesisBaseFee, 20000000, 11000000, 1150000000, 4}, // usage above target
{6, chain.GenesisBaseFee, 20000000, 20000000, 1125000000, 2}, // usage full
{6, chain.GenesisBaseFee, 20000000, 20000000, 1375000000, 4}, // usage full
{6, chain.GenesisBaseFee, 20000000, 0, 875000000, 2}, // usage 0
{6, chain.GenesisBaseFee, 20000000, 0, 875000000, 4}, // usage 0
{
blockNumber: 6,
parentBaseFee: chain.GenesisBaseFee,
parentGasLimit: 20000000,
parentGasUsed: 10000000,
elasticityMultiplier: 2,
expectedBaseFee: chain.GenesisBaseFee,
}, // usage == target
{
blockNumber: 6,
parentBaseFee: chain.GenesisBaseFee,
parentGasLimit: 20000000,
parentGasUsed: 10000000,
elasticityMultiplier: 4,
expectedBaseFee: 1125000000,
}, // usage == target
{
blockNumber: 6,
parentBaseFee: chain.GenesisBaseFee,
parentGasLimit: 20000000,
parentGasUsed: 9000000,
elasticityMultiplier: 2,
expectedBaseFee: 987500000,
}, // usage below target
{
blockNumber: 6,
parentBaseFee: chain.GenesisBaseFee,
parentGasLimit: 20000000,
parentGasUsed: 9000000,
elasticityMultiplier: 4,
expectedBaseFee: 1100000000,
}, // usage below target
{
blockNumber: 6,
parentBaseFee: chain.GenesisBaseFee,
parentGasLimit: 20000000,
parentGasUsed: 11000000,
elasticityMultiplier: 2,
expectedBaseFee: 1012500000,
}, // usage above target
{
blockNumber: 6,
parentBaseFee: chain.GenesisBaseFee,
parentGasLimit: 20000000,
parentGasUsed: 11000000,
elasticityMultiplier: 4,
expectedBaseFee: 1150000000,
}, // usage above target
{
blockNumber: 6,
parentBaseFee: chain.GenesisBaseFee,
parentGasLimit: 20000000,
parentGasUsed: 20000000,
elasticityMultiplier: 2,
expectedBaseFee: 1125000000,
}, // usage full
{
blockNumber: 6,
parentBaseFee: chain.GenesisBaseFee,
parentGasLimit: 20000000,
parentGasUsed: 20000000,
elasticityMultiplier: 4,
expectedBaseFee: 1375000000,
}, // usage full
{
blockNumber: 6,
parentBaseFee: chain.GenesisBaseFee,
parentGasLimit: 20000000,
parentGasUsed: 0,
elasticityMultiplier: 2,
expectedBaseFee: 875000000,
}, // usage 0
{
blockNumber: 6,
parentBaseFee: chain.GenesisBaseFee,
parentGasLimit: 20000000,
parentGasUsed: 0,
elasticityMultiplier: 4,
expectedBaseFee: 875000000,
}, // usage 0
{
blockNumber: 6,
forks: &chain.Forks{chain.London: chain.NewFork(10)},
expectedBaseFee: 0,
}, // London hard fork disabled
{
blockNumber: 6,
parentBaseFee: 0,
expectedBaseFee: 10,
},
// first block with London hard fork
// (return base fee value configured in the genesis)
{
blockNumber: 6,
parentBaseFee: chain.GenesisBaseFee,
parentGasLimit: 20000000,
parentGasUsed: 10000000,
elasticityMultiplier: 4,
forks: chain.AllForksEnabled,
getLatestConfigFn: func() (*chain.Params, error) {
return &chain.Params{BaseFeeChangeDenom: 4}, nil
},
expectedBaseFee: 1250000000,
}, // governance hard fork enabled
{
blockNumber: 6,
parentBaseFee: chain.GenesisBaseFee,
parentGasLimit: 20000000,
parentGasUsed: 10000000,
elasticityMultiplier: 4,
forks: chain.AllForksEnabled,
getLatestConfigFn: func() (*chain.Params, error) {
return nil, errors.New("failed to retrieve chain config")
},
expectedBaseFee: 1000000008,
}, // governance hard fork enabled
}

for i, test := range tests {
Expand All @@ -1390,19 +1498,34 @@ func TestBlockchain_CalculateBaseFee(t *testing.T) {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
t.Parallel()

blockchain := Blockchain{
forks := &chain.Forks{
chain.London: chain.NewFork(5),
}

if test.forks != nil {
forks = test.forks
}

blockchain := &Blockchain{
logger: hclog.NewNullLogger(),
config: &chain.Chain{
Params: &chain.Params{
Forks: &chain.Forks{
chain.London: chain.NewFork(5),
},
},
Params: &chain.Params{Forks: forks},
Genesis: &chain.Genesis{
BaseFee: 10,
BaseFeeEM: test.elasticityMultiplier,
},
},
}

blockchain.setCurrentHeader(&types.Header{
Number: test.blockNumber + 1,
GasLimit: test.parentGasLimit,
GasUsed: test.parentGasUsed,
BaseFee: test.parentBaseFee,
}, big.NewInt(1))

blockchain.SetConsensus(&MockVerifier{getChainConfigFn: test.getLatestConfigFn})

parent := &types.Header{
Number: test.blockNumber,
GasLimit: test.parentGasLimit,
Expand Down
10 changes: 10 additions & 0 deletions blockchain/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,12 +231,14 @@ type verifyHeaderDelegate func(*types.Header) error
type processHeadersDelegate func([]*types.Header) error
type getBlockCreatorDelegate func(*types.Header) (types.Address, error)
type preStateCommitDelegate func(*types.Block, *state.Transition) error
type getChainConfigDelegate func() (*chain.Params, error)

type MockVerifier struct {
verifyHeaderFn verifyHeaderDelegate
processHeadersFn processHeadersDelegate
getBlockCreatorFn getBlockCreatorDelegate
preStateCommitFn preStateCommitDelegate
getChainConfigFn getChainConfigDelegate
}

func (m *MockVerifier) VerifyHeader(header *types.Header) error {
Expand Down Expand Up @@ -271,6 +273,14 @@ func (m *MockVerifier) GetBlockCreator(header *types.Header) (types.Address, err
return types.BytesToAddress(header.Miner), nil
}

func (m *MockVerifier) GetLatestChainConfig() (*chain.Params, error) {
if m.getChainConfigFn != nil {
return m.getChainConfigFn()
}

return &chain.Params{}, nil
}

func (m *MockVerifier) HookGetBlockCreator(fn getBlockCreatorDelegate) {
m.getBlockCreatorFn = fn
}
Expand Down
3 changes: 3 additions & 0 deletions chain/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import (
)

const (
// BaseFeeChangeDenom is the value to bound the amount the base fee can change between blocks
BaseFeeChangeDenom = uint64(8)

// GenesisBaseFeeEM is the initial base fee elasticity multiplier for EIP-1559 blocks.
GenesisBaseFeeEM = 2

Expand Down
3 changes: 3 additions & 0 deletions chain/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ type Params struct {
Engine map[string]interface{} `json:"engine"`
BlockGasTarget uint64 `json:"blockGasTarget"`

// BaseFeeChangeDenom is the value to bound the amount the base fee can change between blocks
BaseFeeChangeDenom uint64 `json:"baseFeeChangeDenom,omitempty"`

// Access control configuration
AccessListsOwner *types.Address `json:"accessListsOwner,omitempty"`
ContractDeployerAllowList *AddressListConfig `json:"contractDeployerAllowList,omitempty"`
Expand Down
15 changes: 8 additions & 7 deletions command/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import (
)

const (
DefaultGenesisFileName = "genesis.json"
DefaultChainName = "polygon-edge"
DefaultChainID = 100
DefaultConsensus = server.PolyBFTConsensus
DefaultGenesisGasUsed = 458752 // 0x70000
DefaultGenesisGasLimit = 5242880 // 0x500000
DefaultGenesisBaseFeeEM = chain.GenesisBaseFeeEM
DefaultGenesisFileName = "genesis.json"
DefaultChainName = "polygon-edge"
DefaultChainID = 100
DefaultConsensus = server.PolyBFTConsensus
DefaultGenesisGasUsed = 458752 // 0x70000
DefaultGenesisGasLimit = 5242880 // 0x500000
DefaultGenesisBaseFeeEM = chain.GenesisBaseFeeEM
DefaultGenesisBaseFeeChangeDenom = chain.BaseFeeChangeDenom
)

var (
Expand Down
7 changes: 7 additions & 0 deletions command/genesis/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,13 @@ func setFlags(cmd *cobra.Command) {
defaultWithdrawalWaitPeriod,
"number of epochs after which withdrawal can be done from child chain",
)

cmd.Flags().Uint64Var(
&params.baseFeeChangeDenom,
baseFeeChangeDenomFlag,
command.DefaultGenesisBaseFeeChangeDenom,
"default base fee change denominator the value to bound the amount the base fee can change between blocks.",
)
}

// Governance
Expand Down
14 changes: 11 additions & 3 deletions command/genesis/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const (
rewardWalletFlag = "reward-wallet"
checkpointIntervalFlag = "checkpoint-interval"
withdrawalWaitPeriodFlag = "withdrawal-wait-period"
baseFeeChangeDenomFlag = "base-fee-change-denom"
voteDelayFlag = "vote-delay"
votePeriodFlag = "vote-period"
voteProposalThresholdFlag = "vote-proposal-threshold"
Expand Down Expand Up @@ -74,6 +75,7 @@ var (
errReserveAccMustBePremined = errors.New("it is mandatory to premine reserve account (0x0 address)")
errInvalidVotingPeriod = errors.New("voting period can not be zero")
errInvalidGovernorAdmin = errors.New("governor admin address must be defined")
errBaseFeeChangeDenomZero = errors.New("base fee change denominator must be greater than 0")
)

type genesisParams struct {
Expand Down Expand Up @@ -145,6 +147,7 @@ type genesisParams struct {

checkpointInterval uint64
withdrawalWaitPeriod uint64
baseFeeChangeDenom uint64

// governance
voteDelay string
Expand Down Expand Up @@ -173,6 +176,10 @@ func (p *genesisParams) validateFlags() error {
return err
}

if p.baseFeeChangeDenom == 0 {
return errBaseFeeChangeDenomZero
}

if p.isPolyBFTConsensus() {
if err := p.extractNativeTokenMetadata(); err != nil {
return err
Expand Down Expand Up @@ -429,9 +436,10 @@ func (p *genesisParams) initGenesisConfig() error {
GasUsed: command.DefaultGenesisGasUsed,
},
Params: &chain.Params{
ChainID: int64(p.chainID),
Forks: enabledForks,
Engine: p.consensusEngineConfig,
ChainID: int64(p.chainID),
Forks: enabledForks,
Engine: p.consensusEngineConfig,
BaseFeeChangeDenom: p.baseFeeChangeDenom,
},
Bootnodes: p.bootnodes,
}
Expand Down
Loading

0 comments on commit 5241598

Please sign in to comment.