Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

Commit

Permalink
rpc, feemarket: store base fee in event (#673)
Browse files Browse the repository at this point in the history
* store base fee in event

* update changelog
  • Loading branch information
thomas-nguy authored Oct 15, 2021
1 parent b1b1294 commit cd3b0be
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Features

* (rpc, evm) [tharsis#673](https://github.com/tharsis/ethermint/pull/673) Use tendermint events to store fee market basefee.
* (rpc) [tharsis#624](https://github.com/tharsis/ethermint/pull/624) Implement new JSON-RPC endpoints from latest geth version
* (evm) [tharsis#662](https://github.com/tharsis/ethermint/pull/662) Disable basefee for non london blocks

Expand Down
18 changes: 10 additions & 8 deletions rpc/ethereum/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -826,22 +826,24 @@ func (e *EVMBackend) BaseFee(height int64) (*big.Int, error) {
return nil, nil
}

res, err := e.queryClient.FeeMarket.BaseFee(types.ContextWithHeight(height), &feemarkettypes.QueryBaseFeeRequest{})
blockRes, err := e.clientCtx.Client.BlockResults(e.ctx, &height)
if err != nil {
return nil, err
}

if res.BaseFee != nil {
return res.BaseFee.BigInt(), nil
baseFee := types.BaseFeeFromEvents(blockRes.EndBlockEvents)
if baseFee != nil {
return baseFee, nil
}

resParams, err := e.queryClient.FeeMarket.Params(types.ContextWithHeight(height), &feemarkettypes.QueryParamsRequest{})
if err != nil {
return nil, err
// If we cannot find in events, we tried to get it from the state.
// It will return feemarket.baseFee if london is activated but feemarket is not enable
res, err := e.queryClient.FeeMarket.BaseFee(types.ContextWithHeight(height), &feemarkettypes.QueryBaseFeeRequest{})
if err == nil && res.BaseFee != nil {
return res.BaseFee.BigInt(), nil
}

baseFee := big.NewInt(resParams.Params.InitialBaseFee)
return baseFee, nil
return nil, nil
}

// GetFilteredBlocks returns the block height list match the given bloom filters.
Expand Down
12 changes: 4 additions & 8 deletions rpc/ethereum/namespaces/eth/filters/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package filters
import (
"context"
"fmt"
"math/big"
"sync"
"time"

Expand All @@ -18,7 +17,6 @@ import (
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"

evmtypes "github.com/tharsis/ethermint/x/evm/types"
Expand Down Expand Up @@ -239,9 +237,6 @@ func (api *PublicFilterAPI) NewBlockFilter() rpc.ID {
return rpc.ID(fmt.Sprintf("error creating block filter: %s", err.Error()))
}

// TODO: use events to get the base fee amount
baseFee := big.NewInt(params.InitialBaseFee)

api.filters[headerSub.ID()] = &filter{typ: filters.BlocksSubscription, deadline: time.NewTimer(deadline), hashes: []common.Hash{}, s: headerSub}

go func(headersCh <-chan coretypes.ResultEvent, errCh <-chan error) {
Expand All @@ -263,6 +258,8 @@ func (api *PublicFilterAPI) NewBlockFilter() rpc.ID {
continue
}

baseFee := types.BaseFeeFromEvents(data.ResultEndBlock.Events)

header := types.EthHeaderFromTendermint(data.Header, baseFee)
api.filtersMu.Lock()
if f, found := api.filters[headerSub.ID()]; found {
Expand Down Expand Up @@ -296,9 +293,6 @@ func (api *PublicFilterAPI) NewHeads(ctx context.Context) (*rpc.Subscription, er
return &rpc.Subscription{}, err
}

// TODO: use events to get the base fee amount
baseFee := big.NewInt(params.InitialBaseFee)

go func(headersCh <-chan coretypes.ResultEvent) {
defer cancelSubs()

Expand All @@ -316,6 +310,8 @@ func (api *PublicFilterAPI) NewHeads(ctx context.Context) (*rpc.Subscription, er
continue
}

baseFee := types.BaseFeeFromEvents(data.ResultEndBlock.Events)

header := types.EthHeaderFromTendermint(data.Header, baseFee)
err = notifier.Notify(rpcSub.ID, header)
if err != nil {
Expand Down
25 changes: 25 additions & 0 deletions rpc/ethereum/types/utils.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package types

import (
"bytes"
"context"
"encoding/hex"
"fmt"
"math/big"

abci "github.com/tendermint/tendermint/abci/types"
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"

tmbytes "github.com/tendermint/tendermint/libs/bytes"
tmtypes "github.com/tendermint/tendermint/types"

Expand Down Expand Up @@ -244,3 +248,24 @@ func NewRPCTransaction(
}
return result, nil
}

// BaseFeeFromEvents parses the feemarket basefee from cosmos events
func BaseFeeFromEvents(events []abci.Event) *big.Int {
for _, event := range events {
if event.Type != feemarkettypes.EventTypeFeeMarket {
continue
}

for _, attr := range event.Attributes {
if bytes.Equal(attr.Key, []byte(feemarkettypes.AttributeKeyBaseFee)) {
result, success := new(big.Int).SetString(string(attr.Value), 10)
if success {
return result
}

return nil
}
}
}
return nil
}
12 changes: 11 additions & 1 deletion x/feemarket/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tharsis/ethermint/x/feemarket/types"

sdk "github.com/cosmos/cosmos-sdk/types"
)
Expand All @@ -13,13 +14,22 @@ import (
// an empty slice.
func (k *Keeper) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) {
baseFee := k.CalculateBaseFee(ctx)

// return immediately if base fee is nil
if baseFee == nil {
return
}

// only set base fee if the NoBaseFee param is false
k.SetBaseFee(ctx, baseFee)

// Store current base fee in event
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeFeeMarket,
sdk.NewAttribute(types.AttributeKeyBaseFee, baseFee.String()),
),
})

if ctx.BlockGasMeter() == nil {
k.Logger(ctx).Error("block gas meter is nil when setting block gas used")
return
Expand Down
7 changes: 4 additions & 3 deletions x/feemarket/keeper/eip1559.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,21 @@ import (
)

// CalculateBaseFee calculates the base fee for the current block. This is only calculated once per
// block during EndBlock. If the NoBaseFee parameter is enabled, this function returns nil.
// block during EndBlock. If the NoBaseFee parameter is enabled or below activation height, this function returns nil.
// NOTE: This code is inspired from the go-ethereum EIP1559 implementation and adapted to Cosmos SDK-based
// chains. For the canonical code refer to: https://github.com/ethereum/go-ethereum/blob/master/consensus/misc/eip1559.go
func (k Keeper) CalculateBaseFee(ctx sdk.Context) *big.Int {
params := k.GetParams(ctx)

if params.NoBaseFee {
// Ignore the calculation if not enable
if !params.IsBaseFeeEnabled(ctx.BlockHeight()) {
return nil
}

consParams := ctx.ConsensusParams()

// If the current block is the first EIP-1559 block, return the InitialBaseFee.
if ctx.BlockHeight() <= params.EnableHeight {
if ctx.BlockHeight() == params.EnableHeight {
return new(big.Int).SetInt64(params.InitialBaseFee)
}

Expand Down
4 changes: 2 additions & 2 deletions x/feemarket/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (k Keeper) SetBlockGasUsed(ctx sdk.Context, gas uint64) {
// Required by EIP1559 base fee calculation.
// ----------------------------------------------------------------------------

// GetBlockGasUsed returns the last block gas used value from the store.
// GetLastBaseFee returns the last base fee value from the store.
func (k Keeper) GetBaseFee(ctx sdk.Context) *big.Int {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.KeyPrefixBaseFee)
Expand All @@ -82,7 +82,7 @@ func (k Keeper) GetBaseFee(ctx sdk.Context) *big.Int {
return new(big.Int).SetBytes(bz)
}

// SetBlockGasUsed gets the current block gas consumed to the store.
// SetBaseFee set the last base fee value to the store.
// CONTRACT: this should be only called during EndBlock.
func (k Keeper) SetBaseFee(ctx sdk.Context, baseFee *big.Int) {
store := ctx.KVStore(k.storeKey)
Expand Down
8 changes: 8 additions & 0 deletions x/feemarket/types/events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package types

// feemarket module events
const (
EventTypeFeeMarket = "fee_market"

AttributeKeyBaseFee = "base_fee"
)
4 changes: 4 additions & 0 deletions x/feemarket/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ func (p Params) Validate() error {
return nil
}

func (p *Params) IsBaseFeeEnabled(height int64) bool {
return !p.NoBaseFee && height >= p.EnableHeight
}

func validateBool(i interface{}) error {
_, ok := i.(bool)
if !ok {
Expand Down

0 comments on commit cd3b0be

Please sign in to comment.