Skip to content

Commit

Permalink
Integration of Sonic's base-fee pricing model
Browse files Browse the repository at this point in the history
  • Loading branch information
HerbertJordan committed Nov 11, 2024
1 parent 9d825ab commit 64e7d4a
Show file tree
Hide file tree
Showing 19 changed files with 345 additions and 119 deletions.
8 changes: 5 additions & 3 deletions eventcheck/epochcheck/epoch_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,11 @@ func (v *Checker) checkGas(e inter.EventPayloadI, rules opera.Rules) error {
if e.GasPowerUsed() > rules.Economy.Gas.MaxEventGas {
return ErrTooBigGasUsed
}
if e.GasPowerUsed() != CalcGasPowerUsed(e, rules) {
return ErrWrongGasUsed
}
/*
if e.GasPowerUsed() != CalcGasPowerUsed(e, rules) {
return ErrWrongGasUsed
}
*/
return nil
}

Expand Down
2 changes: 2 additions & 0 deletions eventcheck/gaspowercheck/gas_power_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ func (v *Checker) CalcGasPower(e inter.EventI, selfParent inter.EventI) (inter.G
res.Gas[i] = calcGasPower(e, selfParent, ctx, ctx.Configs[i])
}

//fmt.Printf("Remaining gas power - short: %d, long: %d\n", res.Gas[inter.ShortTermGas], res.Gas[inter.LongTermGas])

return res, nil
}

Expand Down
30 changes: 23 additions & 7 deletions evmcore/dummy_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package evmcore

import (
"math"
"encoding/binary"
"math/big"

"github.com/ethereum/go-ethereum/common/hexutil"
Expand Down Expand Up @@ -79,6 +79,8 @@ func ToEvmHeader(block *inter.Block, index idx.Block, prevHash hash.Event, rules
baseFee := rules.Economy.MinGasPrice
if !rules.Upgrades.London {
baseFee = nil
} else if rules.Upgrades.Sonic {
baseFee = block.BaseFee
}

prevRandao := common.Hash{}
Expand All @@ -92,7 +94,8 @@ func ToEvmHeader(block *inter.Block, index idx.Block, prevHash hash.Event, rules
Root: common.Hash(block.Root),
Number: big.NewInt(int64(index)),
Time: block.Time,
GasLimit: math.MaxUint64,
Duration: block.Duration,
GasLimit: block.GasLimit,
GasUsed: block.GasUsed,
BaseFee: baseFee,
PrevRandao: prevRandao,
Expand All @@ -101,16 +104,24 @@ func ToEvmHeader(block *inter.Block, index idx.Block, prevHash hash.Event, rules

// ConvertFromEthHeader converts ETH-formatted header to Lachesis EVM header
func ConvertFromEthHeader(h *types.Header) *EvmHeader {
var time inter.Timestamp
var duration inter.Duration
if len(h.Extra) == 16 {
time = inter.Timestamp(binary.BigEndian.Uint64(h.Extra[:8]))
duration = inter.Duration(binary.BigEndian.Uint64(h.Extra[8:]))
}
// TODO: return an error otherwise!
// NOTE: incomplete conversion
return &EvmHeader{
Number: h.Number,
Coinbase: h.Coinbase,
GasLimit: math.MaxUint64,
GasLimit: h.GasLimit,
GasUsed: h.GasUsed,
Root: h.Root,
TxHash: h.TxHash,
ParentHash: h.ParentHash,
Time: inter.FromUnix(int64(h.Time)),
Time: time,
Duration: duration,
Hash: common.BytesToHash(h.Extra),
BaseFee: h.BaseFee,
PrevRandao: h.MixDigest,
Expand All @@ -122,17 +133,20 @@ func (h *EvmHeader) EthHeader() *types.Header {
if h == nil {
return nil
}
extra := make([]byte, 16)
binary.BigEndian.PutUint64(extra[:8], uint64(h.Time))
binary.BigEndian.PutUint64(extra[8:], uint64(h.Duration))
// NOTE: incomplete conversion
ethHeader := &types.Header{
Number: h.Number,
Coinbase: h.Coinbase,
GasLimit: 0xffffffffffff, // don't use h.GasLimit (too much bits) here to avoid parsing issues
GasLimit: h.GasLimit,
GasUsed: h.GasUsed,
Root: h.Root,
TxHash: h.TxHash,
ParentHash: h.ParentHash,
Time: uint64(h.Time.Unix()),
Extra: h.Hash.Bytes(),
Extra: extra,
BaseFee: h.BaseFee,

Difficulty: new(big.Int),
Expand Down Expand Up @@ -176,17 +190,19 @@ type EvmBlockJson struct {
}

func (h *EvmHeader) ToJson(receipts types.Receipts) *EvmHeaderJson {
ethHeader := h.EthHeader()
enc := &EvmHeaderJson{
Number: (*hexutil.Big)(h.Number),
Miner: h.Coinbase,
GasLimit: 0xffffffffffff, // don't use h.GasLimit (too much bits) here to avoid parsing issues
GasLimit: hexutil.Uint64(h.GasLimit),
GasUsed: hexutil.Uint64(h.GasUsed),
Root: h.Root,
TxHash: h.TxHash,
ParentHash: h.ParentHash,
UncleHash: types.EmptyUncleHash,
Time: hexutil.Uint64(h.Time.Unix()),
TimeNano: hexutil.Uint64(h.Time),
Extra: ethHeader.Extra,
BaseFee: (*hexutil.Big)(h.BaseFee),
Difficulty: new(hexutil.Big),
PrevRandao: h.PrevRandao,
Expand Down
24 changes: 20 additions & 4 deletions gossip/apply_genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import (
"fmt"
"math/big"

"github.com/Fantom-foundation/go-opera/evmcore"
"github.com/Fantom-foundation/go-opera/gossip/gasprice"
"github.com/Fantom-foundation/go-opera/inter"
"github.com/Fantom-foundation/go-opera/inter/iblockproc"
"github.com/Fantom-foundation/go-opera/inter/ibr"
"github.com/Fantom-foundation/go-opera/inter/ier"
Expand Down Expand Up @@ -49,12 +52,28 @@ func (s *Store) ApplyGenesis(g genesis.Genesis) (err error) {
s.SetBlockEpochState(topEr.BlockState, topEr.EpochState)
s.FlushBlockEpochState()

s.SetGenesisID(g.GenesisID)
s.SetGenesisBlockIndex(topEr.BlockState.LastBlock.Idx)

// write blocks
rules := s.GetRules()
gasLimit := rules.Blocks.MaxBlockGas
baseFee := prevEs.Rules.Economy.MinGasPrice
blobGasPrice := big.NewInt(1) // TODO issue #147
var lastBlock ibr.LlrIdxFullBlockRecord
g.Blocks.ForEach(func(br ibr.LlrIdxFullBlockRecord) bool {
s.WriteFullBlockRecord(baseFee, blobGasPrice, br)
var duration inter.Duration
if rules.Upgrades.Sonic {
block := s.GetBlock(br.Idx - 1)
header := &evmcore.EvmHeader{
GasUsed: block.GasUsed,
GasLimit: block.GasLimit,
BaseFee: block.BaseFee,
}
baseFee = gasprice.GetBaseFeeForNextBlock(header, rules.Economy)
duration = inter.Duration(br.Time - block.Time)
}
s.WriteFullBlockRecord(gasLimit, baseFee, blobGasPrice, duration, br)
if br.Idx > lastBlock.Idx {
lastBlock = br
}
Expand Down Expand Up @@ -110,9 +129,6 @@ func (s *Store) ApplyGenesis(g genesis.Genesis) (err error) {
s.Log.Info("StateDB imported successfully, stateRoot matches", "index", lastBlock.Idx, "root", lastBlock.Root)
}

s.SetGenesisID(g.GenesisID)
s.SetGenesisBlockIndex(topEr.BlockState.LastBlock.Idx)

return nil
}

Expand Down
2 changes: 1 addition & 1 deletion gossip/blockproc/drivermodule/driver_txs.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func InternalTxBuilder(statedb state.StateDB) func(calldata []byte, addr common.
if nonce == math.MaxUint64 {
nonce = statedb.GetNonce(common.Address{})
}
tx := types.NewTransaction(nonce, addr, common.Big0, 1e10, common.Big0, calldata)
tx := types.NewTransaction(nonce, addr, common.Big0, 1e6, common.Big0, calldata)
nonce++
return tx
}
Expand Down
17 changes: 13 additions & 4 deletions gossip/blockproc/evmmodule/evm.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package evmmodule

import (
"math"
"math/big"

"github.com/ethereum/go-ethereum/common"
Expand All @@ -11,6 +10,7 @@ import (

"github.com/Fantom-foundation/go-opera/evmcore"
"github.com/Fantom-foundation/go-opera/gossip/blockproc"
"github.com/Fantom-foundation/go-opera/gossip/gasprice"
"github.com/Fantom-foundation/go-opera/inter"
"github.com/Fantom-foundation/go-opera/inter/iblockproc"
"github.com/Fantom-foundation/go-opera/inter/state"
Expand All @@ -26,8 +26,13 @@ func New() *EVMModule {

func (p *EVMModule) Start(block iblockproc.BlockCtx, statedb state.StateDB, reader evmcore.DummyChain, onNewLog func(*types.Log), net opera.Rules, evmCfg *params.ChainConfig) blockproc.EVMProcessor {
var prevBlockHash common.Hash
if block.Idx != 0 {
prevBlockHash = reader.GetHeader(common.Hash{}, uint64(block.Idx-1)).Hash
var baseFee *big.Int
if block.Idx == 0 {
baseFee = gasprice.GetInitialBaseFee()
} else {
header := reader.GetHeader(common.Hash{}, uint64(block.Idx-1))
prevBlockHash = header.Hash
baseFee = gasprice.GetBaseFeeForNextBlock(header, net.Economy)
}

// Start block
Expand All @@ -42,6 +47,7 @@ func (p *EVMModule) Start(block iblockproc.BlockCtx, statedb state.StateDB, read
evmCfg: evmCfg,
blockIdx: utils.U64toBig(uint64(block.Idx)),
prevBlockHash: prevBlockHash,
gasBaseFee: baseFee,
}
}

Expand All @@ -55,6 +61,7 @@ type OperaEVMProcessor struct {

blockIdx *big.Int
prevBlockHash common.Hash
gasBaseFee *big.Int

gasUsed uint64

Expand All @@ -67,6 +74,8 @@ func (p *OperaEVMProcessor) evmBlockWith(txs types.Transactions) *evmcore.EvmBlo
baseFee := p.net.Economy.MinGasPrice
if !p.net.Upgrades.London {
baseFee = nil
} else if p.net.Upgrades.Sonic {
baseFee = p.gasBaseFee
}

prevRandao := common.Hash{}
Expand All @@ -80,7 +89,7 @@ func (p *OperaEVMProcessor) evmBlockWith(txs types.Transactions) *evmcore.EvmBlo
Root: common.Hash{},
Time: p.block.Time,
Coinbase: common.Address{},
GasLimit: math.MaxUint64,
GasLimit: p.net.Blocks.MaxBlockGas,
GasUsed: p.gasUsed,
BaseFee: baseFee,
PrevRandao: prevRandao,
Expand Down
19 changes: 14 additions & 5 deletions gossip/c_block_callbacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,10 @@ func consensusCallbackBeginBlockFn(

// new block
var block = &inter.Block{
Time: blockCtx.Time,
Atropos: cBlock.Atropos,
Events: hash.Events(confirmedEvents),
Time: blockCtx.Time,
Duration: inter.Duration(blockCtx.Time - bs.LastBlock.Time),
Atropos: cBlock.Atropos,
Events: hash.Events(confirmedEvents),
}
for _, tx := range append(preInternalTxs, internalTxs...) {
block.Txs = append(block.Txs, tx.Hash())
Expand All @@ -241,9 +242,12 @@ func consensusCallbackBeginBlockFn(
_ = evmProcessor.Execute(txs)

evmBlock, skippedTxs, allReceipts := evmProcessor.Finalize()
evmBlock.Duration = block.Duration
block.SkippedTxs = skippedTxs
block.Root = hash.Hash(evmBlock.Root)
block.GasLimit = es.Rules.Blocks.MaxBlockGas
block.GasUsed = evmBlock.GasUsed
block.BaseFee = evmBlock.BaseFee

// memorize event position of each tx
txPositions := make(map[common.Hash]ExtendedTxPosition)
Expand Down Expand Up @@ -334,11 +338,16 @@ func consensusCallbackBeginBlockFn(
feed.newLogs.Send(logs)
}

lastBlockTime := evmStateReader.GetHeader(common.Hash{}, uint64(blockCtx.Idx-1)).Time.Time()
thisBlockTime := block.Time.Time()
blockTime := thisBlockTime.Sub(lastBlockTime)

now := time.Now()
blockAge := now.Sub(block.Time.Time())
log.Info("New block", "index", blockCtx.Idx, "id", block.Atropos, "gas_used",
evmBlock.GasUsed, "txs", fmt.Sprintf("%d/%d", len(evmBlock.Transactions), len(block.SkippedTxs)),
"age", utils.PrettyDuration(blockAge), "t", utils.PrettyDuration(now.Sub(start)))
evmBlock.GasUsed, "base_fee", evmBlock.BaseFee.String(), "txs", fmt.Sprintf("%d/%d", len(evmBlock.Transactions), len(block.SkippedTxs)),
"age", utils.PrettyDuration(blockAge), "t", utils.PrettyDuration(now.Sub(start)),
"gas_rate", float64(evmBlock.GasUsed)/blockTime.Seconds())
blockAgeGauge.Update(int64(blockAge.Nanoseconds()))

processedTxsMeter.Mark(int64(len(evmBlock.Transactions)))
Expand Down
6 changes: 3 additions & 3 deletions gossip/c_event_callbacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package gossip

import (
"errors"
"github.com/ethereum/go-ethereum/metrics"
"math/big"
"sync/atomic"

"github.com/ethereum/go-ethereum/metrics"

"github.com/Fantom-foundation/lachesis-base/gossip/dagprocessor"
"github.com/Fantom-foundation/lachesis-base/hash"
"github.com/Fantom-foundation/lachesis-base/inter/dag"
Expand All @@ -14,7 +15,6 @@ import (
"github.com/ethereum/go-ethereum/log"

"github.com/Fantom-foundation/go-opera/eventcheck"
"github.com/Fantom-foundation/go-opera/eventcheck/epochcheck"
"github.com/Fantom-foundation/go-opera/gossip/emitter"
"github.com/Fantom-foundation/go-opera/inter"
"github.com/Fantom-foundation/go-opera/inter/iblockproc"
Expand Down Expand Up @@ -56,7 +56,7 @@ func (s *Service) buildEvent(e *inter.MutableEventPayload, onIndexed func()) err
e.SetMedianTime(s.dagIndexer.MedianTime(e.ID(), s.store.GetEpochState().EpochStart))

// calc initial GasPower
e.SetGasPowerUsed(epochcheck.CalcGasPowerUsed(e, s.store.GetRules()))
//e.SetGasPowerUsed(epochcheck.CalcGasPowerUsed(e, s.store.GetRules()))
var selfParent *inter.Event
if e.SelfParent() != nil {
selfParent = s.store.GetEvent(*e.SelfParent())
Expand Down
5 changes: 4 additions & 1 deletion gossip/c_llr_callbacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func indexRawReceipts(s *Store, receiptsForStorage []*types.ReceiptForStorage, t
}
}

func (s *Store) WriteFullBlockRecord(baseFee *big.Int, blobGasPrice *big.Int, br ibr.LlrIdxFullBlockRecord) {
func (s *Store) WriteFullBlockRecord(gasLimit uint64, baseFee *big.Int, blobGasPrice *big.Int, duration inter.Duration, br ibr.LlrIdxFullBlockRecord) {
txHashes := make([]common.Hash, 0, len(br.Txs))
for _, tx := range br.Txs {
txHashes = append(txHashes, tx.Hash())
Expand All @@ -45,12 +45,15 @@ func (s *Store) WriteFullBlockRecord(baseFee *big.Int, blobGasPrice *big.Int, br
}
s.SetBlock(br.Idx, &inter.Block{
Time: br.Time,
Duration: duration,
Atropos: br.Atropos,
Events: hash.Events{},
Txs: txHashes,
InternalTxs: []common.Hash{},
SkippedTxs: []uint32{},
GasLimit: gasLimit,
GasUsed: br.GasUsed,
BaseFee: baseFee,
Root: br.Root,
})
s.SetBlockIndex(br.Atropos, br.Idx)
Expand Down
3 changes: 3 additions & 0 deletions gossip/emitter/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ func eventMetric(orig ancestor.Metric, seq idx.Event) ancestor.Metric {

func (em *Emitter) isAllowedToEmit(e inter.EventI, eTxs bool, metric ancestor.Metric, selfParent *inter.Event) bool {
passedTime := e.CreationTime().Time().Sub(em.prevEmittedAtTime)

return passedTime > 500*time.Millisecond

if passedTime < 0 {

Check failure on line 49 in gossip/emitter/control.go

View workflow job for this annotation

GitHub Actions / check-build

unreachable code
passedTime = 0
}
Expand Down
Loading

0 comments on commit 64e7d4a

Please sign in to comment.