feat: re-enable EIP-1559 in Banach hard fork (#634)

* feat: re-enable EIP-1559 in Banach hard fork

* enable BASEFEE opcode

* do not double gas limit on Banach fork block

* do not burn base fee

* update base fee calculation logic

* fix gas price oracle

* fix ethapi backend

* typo

* reorder worker code

* update genesis base fee

* add MaximumL2BaseFee

* add base fee metrics

* handle nil base fee

* revert state-transition change

* bump version

* remove TODO

* update test

* fix typo

* fix typo

* update traces

* fix test

* update london to banach

* handle error

* bump version

* bump version
This commit is contained in:
Péter Garamvölgyi 2024-03-11 13:57:52 +00:00 committed by GitHub
parent dab4354b62
commit ccec84ce63
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 274 additions and 231 deletions

View file

@ -590,7 +590,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
head := b.blockchain.CurrentHeader()
if !b.blockchain.Config().IsLondon(head.Number) {
if !b.blockchain.Config().IsBanach(head.Number) {
// If there's no basefee, then it must be a non-1559 execution
if call.GasPrice == nil {
call.GasPrice = new(big.Int)

View file

@ -289,7 +289,7 @@ func (c *BoundContract) createDynamicTx(opts *TransactOpts, contract *common.Add
func (c *BoundContract) createLegacyTx(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) {
if opts.GasFeeCap != nil || opts.GasTipCap != nil {
return nil, errors.New("maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet")
return nil, errors.New("maxFeePerGas or maxPriorityFeePerGas specified but banach is not active yet")
}
// Normalize value
value := opts.Value

View file

@ -247,8 +247,8 @@ func Transition(ctx *cli.Context) error {
return NewError(ErrorJson, fmt.Errorf("failed signing transactions: %v", err))
}
// Sanity check, to not `panic` in state_transition
if chainConfig.IsLondon(big.NewInt(int64(prestate.Env.Number))) {
if prestate.Env.BaseFee == nil && chainConfig.Scroll.BaseFeeEnabled() {
if chainConfig.IsBanach(big.NewInt(int64(prestate.Env.Number))) {
if prestate.Env.BaseFee == nil {
return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section"))
}
}
@ -321,8 +321,9 @@ func (t *txWithKey) UnmarshalJSON(input []byte) error {
// signUnsignedTransactions converts the input txs to canonical transactions.
//
// The transactions can have two forms, either
// 1. unsigned or
// 2. signed
// 1. unsigned or
// 2. signed
//
// For (1), r, s, v, need so be zero, and the `secretKey` needs to be set.
// If so, we sign it here and now, with the given `secretKey`
// If the condition above is not met, then it's considered a signed transaction.

View file

@ -335,7 +335,7 @@ func (c *Clique) verifyCascadingFields(chain consensus.ChainHeaderReader, header
if header.GasUsed > header.GasLimit {
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}
if !chain.Config().IsLondon(header.Number) {
if !chain.Config().IsBanach(header.Number) {
// Verify BaseFee not present before EIP-1559 fork.
if header.BaseFee != nil {
return fmt.Errorf("invalid baseFee before fork: have %d, want <nil>", header.BaseFee)

View file

@ -291,7 +291,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}
// Verify the block's gas usage and (if applicable) verify the base fee.
if !chain.Config().IsLondon(header.Number) {
if !chain.Config().IsBanach(header.Number) {
// Verify BaseFee not present before EIP-1559 fork.
if header.BaseFee != nil {
return fmt.Errorf("invalid baseFee before fork: have %d, expected 'nil'", header.BaseFee)

View file

@ -20,90 +20,53 @@ import (
"fmt"
"math/big"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/common/math"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/params"
)
// Protocol-enforced maximum L2 base fee.
// We would only go above this if L1 base fee hits 700 Gwei.
const MaximumL2BaseFee = 10000000000
// VerifyEip1559Header verifies some header attributes which were changed in EIP-1559,
// - gas limit check
// - basefee check
func VerifyEip1559Header(config *params.ChainConfig, parent, header *types.Header) error {
// Verify that the gas limit remains within allowed bounds
parentGasLimit := parent.GasLimit
if !config.IsLondon(parent.Number) {
parentGasLimit = parent.GasLimit * params.ElasticityMultiplier
}
if err := VerifyGaslimit(parentGasLimit, header.GasLimit); err != nil {
if err := VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil {
return err
}
// Verify the header is not malformed
if header.BaseFee == nil && config.Scroll.BaseFeeEnabled() {
if header.BaseFee == nil {
return fmt.Errorf("header is missing baseFee")
}
// Now BaseFee can be nil, because !config.Scroll.BaseFeeEnabled()
if header.BaseFee == nil {
return nil
}
// Verify the baseFee is correct based on the parent header.
var expectedBaseFee *big.Int
// compatible check with the logic in commitNewWork
if config.Clique == nil || config.Scroll.BaseFeeEnabled() {
expectedBaseFee = CalcBaseFee(config, parent)
} else {
expectedBaseFee = big.NewInt(0)
}
if header.BaseFee.Cmp(expectedBaseFee) != 0 {
return fmt.Errorf("invalid baseFee: have %s, want %s, parentBaseFee %s, parentGasUsed %d",
expectedBaseFee, header.BaseFee, parent.BaseFee, parent.GasUsed)
// note: we do not verify L2 base fee, the sequencer has the
// right to set any base fee below the maximum. L2 base fee
// is not subject to L2 consensus or zk verification.
if header.BaseFee.Cmp(big.NewInt(MaximumL2BaseFee)) > 0 {
return fmt.Errorf("invalid baseFee: have %s, maximum %d", header.BaseFee, MaximumL2BaseFee)
}
return nil
}
// CalcBaseFee calculates the basefee of the header.
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
if !config.IsLondon(parent.Number) {
return new(big.Int).SetUint64(params.InitialBaseFee)
func CalcBaseFee(config *params.ChainConfig, parent *types.Header, parentL1BaseFee *big.Int) *big.Int {
l2SequencerFee := big.NewInt(10000000) // 0.01 Gwei
provingFee := big.NewInt(140000000) // 0.14 Gwei
// L1_base_fee * 0.014
verificationFee := parentL1BaseFee
verificationFee = new(big.Int).Mul(verificationFee, big.NewInt(14))
verificationFee = new(big.Int).Div(verificationFee, big.NewInt(1000))
baseFee := big.NewInt(0)
baseFee.Add(baseFee, l2SequencerFee)
baseFee.Add(baseFee, provingFee)
baseFee.Add(baseFee, verificationFee)
if baseFee.Cmp(big.NewInt(MaximumL2BaseFee)) > 0 {
baseFee = big.NewInt(MaximumL2BaseFee)
}
var (
parentGasTarget = parent.GasLimit / params.ElasticityMultiplier
parentGasTargetBig = new(big.Int).SetUint64(parentGasTarget)
baseFeeChangeDenominator = new(big.Int).SetUint64(params.BaseFeeChangeDenominator)
)
if !config.Scroll.BaseFeeEnabled() {
return nil
}
// If the parent gasUsed is the same as the target, the baseFee remains unchanged.
if parent.GasUsed == parentGasTarget {
return new(big.Int).Set(parent.BaseFee)
}
if parent.GasUsed > parentGasTarget {
// If the parent block used more gas than its target, the baseFee should increase.
gasUsedDelta := new(big.Int).SetUint64(parent.GasUsed - parentGasTarget)
x := new(big.Int).Mul(parent.BaseFee, gasUsedDelta)
y := x.Div(x, parentGasTargetBig)
baseFeeDelta := math.BigMax(
x.Div(y, baseFeeChangeDenominator),
common.Big1,
)
return x.Add(parent.BaseFee, baseFeeDelta)
} else {
// Otherwise if the parent block used less gas than its target, the baseFee should decrease.
gasUsedDelta := new(big.Int).SetUint64(parentGasTarget - parent.GasUsed)
x := new(big.Int).Mul(parent.BaseFee, gasUsedDelta)
y := x.Div(x, parentGasTargetBig)
baseFeeDelta := x.Div(y, baseFeeChangeDenominator)
return math.BigMax(
x.Sub(parent.BaseFee, baseFeeDelta),
common.Big0,
)
}
return baseFee
}

View file

@ -20,7 +20,6 @@ import (
"math/big"
"testing"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/params"
)
@ -52,7 +51,8 @@ func copyConfig(original *params.ChainConfig) *params.ChainConfig {
func config() *params.ChainConfig {
config := copyConfig(params.TestChainConfig)
config.LondonBlock = big.NewInt(5)
config.LondonBlock = big.NewInt(3)
config.BanachBlock = big.NewInt(5)
return config
}
@ -67,13 +67,13 @@ func TestBlockGasLimits(t *testing.T) {
gasLimit uint64
ok bool
}{
// Transitions from non-london to london
{10000000, 4, 20000000, true}, // No change
{10000000, 4, 20019530, true}, // Upper limit
{10000000, 4, 20019531, false}, // Upper +1
{10000000, 4, 19980470, true}, // Lower limit
{10000000, 4, 19980469, false}, // Lower limit -1
// London to London
// Transitions from non-banach to banach
{10000000, 4, 10000000, true}, // No change
{10000000, 4, 10009764, true}, // Upper limit
{10000000, 4, 10009765, false}, // Upper +1
{10000000, 4, 9990236, true}, // Lower limit
{10000000, 4, 9990235, false}, // Lower limit -1
// Banach to Banach
{20000000, 5, 20000000, true},
{20000000, 5, 20019530, true}, // Upper limit
{20000000, 5, 20019531, false}, // Upper limit +1
@ -109,23 +109,18 @@ func TestBlockGasLimits(t *testing.T) {
// TestCalcBaseFee assumes all blocks are 1559-blocks
func TestCalcBaseFee(t *testing.T) {
tests := []struct {
parentBaseFee int64
parentGasLimit uint64
parentGasUsed uint64
expectedBaseFee int64
parentL1BaseFee int64
expectedL2BaseFee int64
}{
{params.InitialBaseFee, 20000000, 10000000, params.InitialBaseFee}, // usage == target
{params.InitialBaseFee, 20000000, 9000000, 987500000}, // usage below target
{params.InitialBaseFee, 20000000, 11000000, 1012500000}, // usage above target
{0, 150000000},
{1000000000, 164000000},
{2000000000, 178000000},
{100000000000, 1550000000},
{111111111111, 1705555555},
{1000000000000, 10000000000}, // cap at max L2 base fee
}
for i, test := range tests {
parent := &types.Header{
Number: common.Big32,
GasLimit: test.parentGasLimit,
GasUsed: test.parentGasUsed,
BaseFee: big.NewInt(test.parentBaseFee),
}
if have, want := CalcBaseFee(config(), parent), big.NewInt(test.expectedBaseFee); have.Cmp(want) != 0 {
if have, want := CalcBaseFee(config(), nil, big.NewInt(test.parentL1BaseFee)), big.NewInt(test.expectedL2BaseFee); have.Cmp(want) != 0 {
t.Errorf("test %d: have %d want %d, ", i, have, want)
}
}

View file

@ -54,6 +54,8 @@ var (
headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil)
headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil)
l2BaseFeeGauge = metrics.NewRegisteredGauge("chain/fees/l2basefee", nil)
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
accountUpdateTimer = metrics.NewRegisteredTimer("chain/account/updates", nil)
@ -1246,6 +1248,13 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
return NonStatTy, errInsertionInterrupted
}
// Note latest seen L2 base fee
if block.BaseFee() != nil {
l2BaseFeeGauge.Update(block.BaseFee().Int64())
} else {
l2BaseFeeGauge.Update(0)
}
// Calculate the total difficulty of the block
ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
if ptd == nil {

View file

@ -607,7 +607,7 @@ func TestFastVsFullChains(t *testing.T) {
gendb = rawdb.NewMemoryDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000000000)
funds = big.NewInt(3000000000000000)
gspec = &Genesis{
Config: params.TestChainConfig,
Alloc: GenesisAlloc{address: {Balance: funds}},
@ -1704,6 +1704,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
t.Fatalf("failed to create temp freezer db: %v", err)
}
gspec := Genesis{Config: params.AllEthashProtocolChanges}
gspec.BaseFee = big.NewInt(params.InitialBaseFee)
gspec.MustCommit(ancientDb)
ancientChain, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancientChain.Stop()
@ -3171,7 +3172,10 @@ func TestFeeVault(t *testing.T) {
// Ensure that the fee vault received all tx fees
actual = state.GetBalance(*params.TestChainConfig.Scroll.FeeVaultAddress)
expected = new(big.Int).SetUint64(block.GasUsed() * block.Transactions()[0].GasTipCap().Uint64())
effectiveGasPrice := new(big.Int).Add(block.BaseFee(), block.Transactions()[0].GasTipCap())
gasUsed := new(big.Int).SetUint64(block.GasUsed())
expected = new(big.Int).Mul(gasUsed, effectiveGasPrice)
if actual.Cmp(expected) != 0 {
t.Fatalf("fee vault balance incorrect: expected %d, got %d", expected, actual)

View file

@ -28,6 +28,7 @@ import (
"github.com/scroll-tech/go-ethereum/core/vm"
"github.com/scroll-tech/go-ethereum/ethdb"
"github.com/scroll-tech/go-ethereum/params"
"github.com/scroll-tech/go-ethereum/rollup/fees"
)
// BlockGen creates blocks for testing.
@ -275,12 +276,9 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
Number: new(big.Int).Add(parent.Number(), common.Big1),
Time: time,
}
if chain.Config().IsLondon(header.Number) {
header.BaseFee = misc.CalcBaseFee(chain.Config(), parent.Header())
if !chain.Config().IsLondon(parent.Number()) {
parentGasLimit := parent.GasLimit() * params.ElasticityMultiplier
header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
}
if chain.Config().IsBanach(header.Number) {
parentL1BaseFee := fees.GetL1BaseFee(state)
header.BaseFee = misc.CalcBaseFee(chain.Config(), parent.Header(), parentL1BaseFee)
}
return header
}

View file

@ -28,6 +28,7 @@ import (
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/common/hexutil"
"github.com/scroll-tech/go-ethereum/common/math"
"github.com/scroll-tech/go-ethereum/consensus/misc"
"github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/core/state"
"github.com/scroll-tech/go-ethereum/core/types"
@ -312,13 +313,11 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
if g.Difficulty == nil {
head.Difficulty = params.GenesisDifficulty
}
if g.Config != nil && g.Config.IsLondon(common.Big0) {
if g.Config != nil && g.Config.IsBanach(common.Big0) {
if g.BaseFee != nil {
head.BaseFee = g.BaseFee
} else if g.Config.Scroll.BaseFeeEnabled() {
head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee)
} else {
head.BaseFee = nil
head.BaseFee = misc.CalcBaseFee(g.Config, nil, big.NewInt(0))
}
}
statedb.Commit(false)

View file

@ -56,6 +56,7 @@ func TestStateProcessorErrors(t *testing.T) {
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ShanghaiBlock: big.NewInt(0),
BanachBlock: big.NewInt(0),
Ethash: new(params.EthashConfig),
}
signer = types.LatestSigner(config)
@ -332,6 +333,7 @@ func TestStateProcessorErrors(t *testing.T) {
ArrowGlacierBlock: big.NewInt(0),
ArchimedesBlock: big.NewInt(0),
ShanghaiBlock: big.NewInt(0),
BanachBlock: big.NewInt(0),
},
Alloc: GenesisAlloc{
common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{
@ -346,21 +348,22 @@ func TestStateProcessorErrors(t *testing.T) {
smallInitCode = [320]byte{}
)
defer blockchain.Stop()
parentL1BaseFee := big.NewInt(1000000000) // 1 gwei
for i, tt := range []struct {
txs []*types.Transaction
want string
}{
{ // ErrMaxInitCodeSizeExceeded
txs: []*types.Transaction{
mkDynamicCreationTx(0, 500000, common.Big0, misc.CalcBaseFee(config, genesis.Header()), tooBigInitCode[:]),
mkDynamicCreationTx(0, 500000, common.Big0, misc.CalcBaseFee(config, genesis.Header(), parentL1BaseFee), tooBigInitCode[:]),
},
want: "could not apply tx 0 [0x7b33776d375660694a23ef992c090265682f3687607e0099b14503fdb65d73e3]: max initcode size exceeded: code size 49153 limit 49152",
want: "could not apply tx 0 [0xa3d2dadf08846f3328b84b0a38240ace42f79c99ea4b9c097c8dcb345f61a84e]: max initcode size exceeded: code size 49153 limit 49152",
},
{ // ErrIntrinsicGas: Not enough gas to cover init code
txs: []*types.Transaction{
mkDynamicCreationTx(0, 54299, common.Big0, misc.CalcBaseFee(config, genesis.Header()), smallInitCode[:]),
mkDynamicCreationTx(0, 54299, common.Big0, misc.CalcBaseFee(config, genesis.Header(), parentL1BaseFee), smallInitCode[:]),
},
want: "could not apply tx 0 [0x98e54c5ecfa7986a66480d65ba32f2c6a2a6aedc3a67abb91b1e118b0717ed2d]: intrinsic gas too low: have 54299, want 54300",
want: "could not apply tx 0 [0x0880861c73bc504c01041b6d506737a119ca7c68c1fe666dc1682636b807c9db]: intrinsic gas too low: have 54299, want 54300",
},
} {
block := GenerateBadBlock(genesis, ethash.NewFaker(), tt.txs, gspec.Config)
@ -394,8 +397,10 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
Time: parent.Time() + 10,
UncleHash: types.EmptyUncleHash,
}
if config.IsLondon(header.Number) {
header.BaseFee = misc.CalcBaseFee(config, parent.Header())
if config.IsBanach(header.Number) {
parentL1BaseFee := big.NewInt(1000000000) // 1 gwei
header.BaseFee = misc.CalcBaseFee(config, parent.Header(), parentL1BaseFee)
}
var receipts []*types.Receipt
// The post-state result doesn't need to be correct (this is a bad block), but we do need something there

View file

@ -288,6 +288,7 @@ func (st *StateTransition) preCheck() error {
}
}
// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
// Note: Logically, this should be `IsBanach`, but we keep `IsLondon` to ensure backward compatibility.
if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call)
if !st.evm.Config.NoBaseFee || st.gasFeeCap.BitLen() > 0 || st.gasTipCap.BitLen() > 0 {
@ -411,12 +412,10 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
st.refundGas(params.RefundQuotientEIP3529)
}
effectiveTip := st.gasPrice
if rules.IsLondon {
if st.evm.Context.BaseFee != nil {
effectiveTip = cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee))
} else {
effectiveTip = cmath.BigMin(st.gasTipCap, st.gasFeeCap)
}
// only burn the base fee if the fee vault is not enabled
if rules.IsBanach && !st.evm.ChainConfig().Scroll.FeeVaultEnabled() {
effectiveTip = cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee))
}
// The L2 Fee is the same as the fee that is charged in the normal geth

View file

@ -1231,8 +1231,9 @@ func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirt
// because of another transaction (e.g. higher gas price).
if reset != nil {
pool.demoteUnexecutables()
if reset.newHead != nil && pool.chainconfig.IsLondon(new(big.Int).Add(reset.newHead.Number, big.NewInt(1))) {
pendingBaseFee := misc.CalcBaseFee(pool.chainconfig, reset.newHead)
if reset.newHead != nil && pool.chainconfig.IsBanach(new(big.Int).Add(reset.newHead.Number, big.NewInt(1))) {
l1BaseFee := fees.GetL1BaseFee(pool.currentState)
pendingBaseFee := misc.CalcBaseFee(pool.chainconfig, reset.newHead, l1BaseFee)
pool.priced.SetBaseFee(pendingBaseFee)
}
// Update all accounts to the latest known pending nonce
@ -1356,8 +1357,8 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
next := new(big.Int).Add(newHead.Number, big.NewInt(1))
pool.istanbul = pool.chainconfig.IsIstanbul(next)
pool.eip2718 = pool.chainconfig.Scroll.EnableEIP2718 && pool.chainconfig.IsBerlin(next)
pool.eip1559 = pool.chainconfig.Scroll.EnableEIP1559 && pool.chainconfig.IsLondon(next)
pool.eip2718 = pool.chainconfig.IsBanach(next)
pool.eip1559 = pool.chainconfig.IsBanach(next)
pool.shanghai = pool.chainconfig.IsShanghai(next)
}

View file

@ -148,20 +148,23 @@ type StorageWrapper struct {
}
type TransactionData struct {
Type uint8 `json:"type"`
Nonce uint64 `json:"nonce"`
TxHash string `json:"txHash"`
Gas uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
From common.Address `json:"from"`
To *common.Address `json:"to"`
ChainId *hexutil.Big `json:"chainId"`
Value *hexutil.Big `json:"value"`
Data string `json:"data"`
IsCreate bool `json:"isCreate"`
V *hexutil.Big `json:"v"`
R *hexutil.Big `json:"r"`
S *hexutil.Big `json:"s"`
Type uint8 `json:"type"`
Nonce uint64 `json:"nonce"`
TxHash string `json:"txHash"`
Gas uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
GasTipCap *hexutil.Big `json:"gasTipCap"`
GasFeeCap *hexutil.Big `json:"gasFeeCap"`
From common.Address `json:"from"`
To *common.Address `json:"to"`
ChainId *hexutil.Big `json:"chainId"`
Value *hexutil.Big `json:"value"`
Data string `json:"data"`
IsCreate bool `json:"isCreate"`
AccessList AccessList `json:"accessList"`
V *hexutil.Big `json:"v"`
R *hexutil.Big `json:"r"`
S *hexutil.Big `json:"s"`
}
// NewTransactionData returns a transaction that will serialize to the trace
@ -177,20 +180,23 @@ func NewTransactionData(tx *Transaction, blockNumber uint64, config *params.Chai
}
result := &TransactionData{
Type: tx.Type(),
TxHash: tx.Hash().String(),
Nonce: nonce,
ChainId: (*hexutil.Big)(tx.ChainId()),
From: from,
Gas: tx.Gas(),
GasPrice: (*hexutil.Big)(tx.GasPrice()),
To: tx.To(),
Value: (*hexutil.Big)(tx.Value()),
Data: hexutil.Encode(tx.Data()),
IsCreate: tx.To() == nil,
V: (*hexutil.Big)(v),
R: (*hexutil.Big)(r),
S: (*hexutil.Big)(s),
Type: tx.Type(),
TxHash: tx.Hash().String(),
Nonce: nonce,
ChainId: (*hexutil.Big)(tx.ChainId()),
From: from,
Gas: tx.Gas(),
GasPrice: (*hexutil.Big)(tx.GasPrice()),
GasTipCap: (*hexutil.Big)(tx.GasTipCap()),
GasFeeCap: (*hexutil.Big)(tx.GasFeeCap()),
To: tx.To(),
Value: (*hexutil.Big)(tx.Value()),
Data: hexutil.Encode(tx.Data()),
IsCreate: tx.To() == nil,
AccessList: tx.AccessList(),
V: (*hexutil.Big)(v),
R: (*hexutil.Big)(r),
S: (*hexutil.Big)(s),
}
return result
}

View file

@ -40,6 +40,8 @@ type sigCache struct {
func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
var signer Signer
switch {
case config.IsBanach(blockNumber):
signer = NewLondonSignerWithEIP4844(config.ChainID)
case config.IsLondon(blockNumber):
signer = NewLondonSignerWithEIP4844(config.ChainID)
case config.IsBerlin(blockNumber):

View file

@ -74,6 +74,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
if cfg.JumpTable[STOP] == nil {
var jt JumpTable
switch {
case evm.chainRules.IsBanach:
jt = banachInstructionSet
case evm.chainRules.IsShanghai:
jt = shanghaiInstructionSet
case evm.chainRules.IsLondon:

View file

@ -59,11 +59,20 @@ var (
berlinInstructionSet = newBerlinInstructionSet()
londonInstructionSet = newLondonInstructionSet()
shanghaiInstructionSet = newShanghaiInstructionSet()
banachInstructionSet = newBanachInstructionSet()
)
// JumpTable contains the EVM opcodes supported at a given fork.
type JumpTable [256]*operation
// newBanachInstructionSet returns the frontier, homestead, byzantium,
// contantinople, istanbul, petersburg, berlin, london, shanghai, and banach instructions.
func newBanachInstructionSet() JumpTable {
instructionSet := newShanghaiInstructionSet()
enable3198(&instructionSet) // Base fee opcode https://eips.ethereum.org/EIPS/eip-3198
return instructionSet
}
// newShanghaiInstructionSet returns the frontier, homestead, byzantium,
// contantinople, istanbul, petersburg, berlin, london and shanghai instructions.
func newShanghaiInstructionSet() JumpTable {

View file

@ -380,3 +380,7 @@ func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, re
func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) {
return b.eth.stateAtTransaction(block, txIndex, reexec)
}
func (b *EthAPIBackend) StateAt(root common.Hash) (*state.StateDB, error) {
return b.eth.BlockChain().StateAt(root)
}

View file

@ -32,6 +32,7 @@ import (
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/node"
chainParams "github.com/scroll-tech/go-ethereum/params"
"github.com/scroll-tech/go-ethereum/rollup/fees"
"github.com/scroll-tech/go-ethereum/rpc"
"github.com/scroll-tech/go-ethereum/trie"
)
@ -141,8 +142,13 @@ func (api *consensusAPI) AssembleBlock(params assembleBlockParams) (*executableD
Extra: []byte{},
Time: params.Timestamp,
}
if config := api.eth.BlockChain().Config(); config.IsLondon(header.Number) {
header.BaseFee = misc.CalcBaseFee(config, parent.Header())
if config := api.eth.BlockChain().Config(); config.IsBanach(header.Number) {
stateDb, err := api.eth.BlockChain().StateAt(parent.Root())
if err != nil {
return nil, err
}
parentL1BaseFee := fees.GetL1BaseFee(stateDb)
header.BaseFee = misc.CalcBaseFee(config, parent.Header(), parentL1BaseFee)
}
err = api.eth.Engine().Prepare(bc, header)
if err != nil {
@ -245,7 +251,7 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
return txs, nil
}
func insertBlockParamsToBlock(config *chainParams.ChainConfig, parent *types.Header, params executableData) (*types.Block, error) {
func insertBlockParamsToBlock(config *chainParams.ChainConfig, parent *types.Header, params executableData, parentL1BaseFee *big.Int) (*types.Block, error) {
txs, err := decodeTransactions(params.Transactions)
if err != nil {
return nil, err
@ -267,8 +273,8 @@ func insertBlockParamsToBlock(config *chainParams.ChainConfig, parent *types.Hea
GasUsed: params.GasUsed,
Time: params.Timestamp,
}
if config.IsLondon(number) {
header.BaseFee = misc.CalcBaseFee(config, parent)
if config.IsBanach(number) {
header.BaseFee = misc.CalcBaseFee(config, parent, parentL1BaseFee)
}
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */)
return block, nil
@ -282,7 +288,12 @@ func (api *consensusAPI) NewBlock(params executableData) (*newBlockResponse, err
if parent == nil {
return &newBlockResponse{false}, fmt.Errorf("could not find parent %x", params.ParentHash)
}
block, err := insertBlockParamsToBlock(api.eth.BlockChain().Config(), parent.Header(), params)
stateDb, err := api.eth.BlockChain().StateAt(parent.Root())
if err != nil {
return nil, err
}
parentL1BaseFee := fees.GetL1BaseFee(stateDb)
block, err := insertBlockParamsToBlock(api.eth.BlockChain().Config(), parent.Header(), params, parentL1BaseFee)
if err != nil {
return nil, err
}

View file

@ -30,6 +30,7 @@ import (
"github.com/scroll-tech/go-ethereum/consensus/misc"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/rollup/fees"
"github.com/scroll-tech/go-ethereum/rpc"
)
@ -88,8 +89,14 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
if bf.results.baseFee = bf.header.BaseFee; bf.results.baseFee == nil {
bf.results.baseFee = new(big.Int)
}
if chainconfig.IsLondon(big.NewInt(int64(bf.blockNumber + 1))) {
bf.results.nextBaseFee = misc.CalcBaseFee(chainconfig, bf.header)
if chainconfig.IsBanach(big.NewInt(int64(bf.blockNumber + 1))) {
state, err := oracle.backend.StateAt(bf.header.Root)
if err != nil || state == nil {
log.Error("State not found", "number", bf.header.Number, "hash", bf.header.Hash().Hex(), "state", state, "err", err)
return
}
l1BaseFee := fees.GetL1BaseFee(state)
bf.results.nextBaseFee = misc.CalcBaseFee(chainconfig, bf.header, l1BaseFee)
} else {
bf.results.nextBaseFee = new(big.Int)
}
@ -191,10 +198,11 @@ func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.Block
// actually processed range is returned to avoid ambiguity when parts of the requested range
// are not available or when the head has changed during processing this request.
// Three arrays are returned based on the processed blocks:
// - reward: the requested percentiles of effective priority fees per gas of transactions in each
// block, sorted in ascending order and weighted by gas used.
// - baseFee: base fee per gas in the given block
// - gasUsedRatio: gasUsed/gasLimit in the given block
// - reward: the requested percentiles of effective priority fees per gas of transactions in each
// block, sorted in ascending order and weighted by gas used.
// - baseFee: base fee per gas in the given block
// - gasUsedRatio: gasUsed/gasLimit in the given block
//
// Note: baseFee includes the next block after the newest of the returned range, because this
// value can be derived from the newest block.
func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error) {

View file

@ -26,6 +26,7 @@ import (
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core"
"github.com/scroll-tech/go-ethereum/core/state"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/event"
"github.com/scroll-tech/go-ethereum/log"
@ -58,6 +59,7 @@ type OracleBackend interface {
PendingBlockAndReceipts() (*types.Block, types.Receipts)
ChainConfig() *params.ChainConfig
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
StateAt(root common.Hash) (*state.StateDB, error)
}
// Oracle recommends gas prices based on the content of recent

View file

@ -26,6 +26,7 @@ import (
"github.com/scroll-tech/go-ethereum/consensus/ethash"
"github.com/scroll-tech/go-ethereum/core"
"github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/core/state"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/core/vm"
"github.com/scroll-tech/go-ethereum/crypto"
@ -108,6 +109,9 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke
)
config.LondonBlock = londonBlock
config.ArrowGlacierBlock = londonBlock
config.ArchimedesBlock = londonBlock
config.ShanghaiBlock = londonBlock
config.BanachBlock = londonBlock
engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase()
genesis, err := gspec.Commit(db)
@ -160,6 +164,10 @@ func (b *testBackend) GetBlockByNumber(number uint64) *types.Block {
return b.chain.GetBlockByNumber(number)
}
func (b *testBackend) StateAt(root common.Hash) (*state.StateDB, error) {
return nil, nil
}
func TestSuggestTipCap(t *testing.T) {
config := Config{
Blocks: 3,

View file

@ -159,11 +159,20 @@ func (s *PublicTxPoolAPI) Content() map[string]map[string]map[string]*RPCTransac
}
pending, queue := s.b.TxPoolContent()
curHeader := s.b.CurrentHeader()
// get latest L1 base fee
state, err := s.b.StateAt(curHeader.Root)
if err != nil || state == nil {
log.Error("State not found", "number", curHeader.Number, "hash", curHeader.Hash().Hex(), "state", state, "err", err)
return nil
}
l1BaseFee := fees.GetL1BaseFee(state)
// Flatten the pending transactions
for account, txs := range pending {
dump := make(map[string]*RPCTransaction)
for _, tx := range txs {
dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx, curHeader, s.b.ChainConfig())
dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx, curHeader, s.b.ChainConfig(), l1BaseFee)
}
content["pending"][account.Hex()] = dump
}
@ -171,7 +180,7 @@ func (s *PublicTxPoolAPI) Content() map[string]map[string]map[string]*RPCTransac
for account, txs := range queue {
dump := make(map[string]*RPCTransaction)
for _, tx := range txs {
dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx, curHeader, s.b.ChainConfig())
dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx, curHeader, s.b.ChainConfig(), l1BaseFee)
}
content["queued"][account.Hex()] = dump
}
@ -184,17 +193,25 @@ func (s *PublicTxPoolAPI) ContentFrom(addr common.Address) map[string]map[string
pending, queue := s.b.TxPoolContentFrom(addr)
curHeader := s.b.CurrentHeader()
// get latest L1 base fee
state, err := s.b.StateAt(curHeader.Root)
if err != nil || state == nil {
log.Error("State not found", "number", curHeader.Number, "hash", curHeader.Hash().Hex(), "state", state, "err", err)
return nil
}
l1BaseFee := fees.GetL1BaseFee(state)
// Build the pending transactions
dump := make(map[string]*RPCTransaction, len(pending))
for _, tx := range pending {
dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx, curHeader, s.b.ChainConfig())
dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx, curHeader, s.b.ChainConfig(), l1BaseFee)
}
content["pending"] = dump
// Build the queued transactions
dump = make(map[string]*RPCTransaction, len(queue))
for _, tx := range queue {
dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx, curHeader, s.b.ChainConfig())
dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx, curHeader, s.b.ChainConfig(), l1BaseFee)
}
content["queued"] = dump
@ -741,10 +758,10 @@ func (s *PublicBlockChainAPI) GetHeaderByHash(ctx context.Context, hash common.H
}
// GetBlockByNumber returns the requested canonical block.
// * When blockNr is -1 the chain head is returned.
// * When blockNr is -2 the pending chain head is returned.
// * When fullTx is true all transactions in the block are returned, otherwise
// only the transaction hash is returned.
// - When blockNr is -1 the chain head is returned.
// - When blockNr is -2 the pending chain head is returned.
// - When fullTx is true all transactions in the block are returned, otherwise
// only the transaction hash is returned.
func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
block, err := s.b.BlockByNumber(ctx, number)
if block != nil && err == nil {
@ -1186,7 +1203,7 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args TransactionA
}
// RPCMarshalHeader converts the given header to the RPC output .
func RPCMarshalHeader(head *types.Header, enableBaseFee bool) map[string]interface{} {
func RPCMarshalHeader(head *types.Header) map[string]interface{} {
result := map[string]interface{}{
"number": (*hexutil.Big)(head.Number),
"hash": head.Hash(),
@ -1207,7 +1224,7 @@ func RPCMarshalHeader(head *types.Header, enableBaseFee bool) map[string]interfa
"receiptsRoot": head.ReceiptHash,
}
if enableBaseFee && head.BaseFee != nil {
if head.BaseFee != nil {
result["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee)
}
@ -1218,7 +1235,7 @@ func RPCMarshalHeader(head *types.Header, enableBaseFee bool) map[string]interfa
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
// transaction hashes.
func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *params.ChainConfig) (map[string]interface{}, error) {
fields := RPCMarshalHeader(block.Header(), config.Scroll.BaseFeeEnabled())
fields := RPCMarshalHeader(block.Header())
fields["size"] = hexutil.Uint64(block.Size())
if inclTx {
@ -1253,7 +1270,7 @@ func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *param
// rpcMarshalHeader uses the generalized output filler, then adds the total difficulty field, which requires
// a `PublicBlockchainAPI`.
func (s *PublicBlockChainAPI) rpcMarshalHeader(ctx context.Context, header *types.Header) map[string]interface{} {
fields := RPCMarshalHeader(header, s.b.ChainConfig().Scroll.BaseFeeEnabled())
fields := RPCMarshalHeader(header)
fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(ctx, header.Hash()))
return fields
}
@ -1351,11 +1368,11 @@ func NewRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
}
// newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation
func newRPCPendingTransaction(tx *types.Transaction, current *types.Header, config *params.ChainConfig) *RPCTransaction {
func newRPCPendingTransaction(tx *types.Transaction, current *types.Header, config *params.ChainConfig, l1BaseFee *big.Int) *RPCTransaction {
var baseFee *big.Int
blockNumber := uint64(0)
if current != nil {
baseFee = misc.CalcBaseFee(config, current)
baseFee = misc.CalcBaseFee(config, current, l1BaseFee)
blockNumber = current.Number.Uint64()
}
return NewRPCTransaction(tx, common.Hash{}, blockNumber, 0, baseFee, config)
@ -1594,7 +1611,17 @@ func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, has
}
// No finalized transaction, try to retrieve it from the pool
if tx := s.b.GetPoolTransaction(hash); tx != nil {
return newRPCPendingTransaction(tx, s.b.CurrentHeader(), s.b.ChainConfig()), nil
curHeader := s.b.CurrentHeader()
// get latest L1 base fee
state, err := s.b.StateAt(curHeader.Root)
if err != nil || state == nil {
log.Error("State not found", "number", curHeader.Number, "hash", curHeader.Hash().Hex(), "state", state, "err", err)
return nil, fmt.Errorf("cannot get L1 base fee, state not found")
}
l1BaseFee := fees.GetL1BaseFee(state)
return newRPCPendingTransaction(tx, s.b.CurrentHeader(), s.b.ChainConfig(), l1BaseFee), nil
}
// Transaction unknown, return as such
@ -1654,7 +1681,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha
"l1Fee": (*hexutil.Big)(receipt.L1Fee),
}
// Assign the effective gas price paid
if !s.b.ChainConfig().IsLondon(bigblock) {
if !s.b.ChainConfig().IsBanach(bigblock) {
fields["effectiveGasPrice"] = hexutil.Uint64(tx.GasPrice().Uint64())
} else {
header, err := s.b.HeaderByHash(ctx, blockHash)
@ -1866,10 +1893,19 @@ func (s *PublicTransactionPoolAPI) PendingTransactions() ([]*RPCTransaction, err
}
curHeader := s.b.CurrentHeader()
transactions := make([]*RPCTransaction, 0, len(pending))
// get latest L1 base fee
state, err := s.b.StateAt(curHeader.Root)
if err != nil || state == nil {
log.Error("State not found", "number", curHeader.Number, "hash", curHeader.Hash().Hex(), "state", state, "err", err)
return nil, fmt.Errorf("cannot get L1 base fee, state not found")
}
l1BaseFee := fees.GetL1BaseFee(state)
for _, tx := range pending {
from, _ := types.Sender(s.signer, tx)
if _, exists := accounts[from]; exists {
transactions = append(transactions, newRPCPendingTransaction(tx, curHeader, s.b.ChainConfig()))
transactions = append(transactions, newRPCPendingTransaction(tx, curHeader, s.b.ChainConfig(), l1BaseFee))
}
}
return transactions, nil

View file

@ -65,6 +65,7 @@ type Backend interface {
BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error)
StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error)
StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error)
StateAt(root common.Hash) (*state.StateDB, error)
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
GetTd(ctx context.Context, hash common.Hash) *big.Int
GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error)

View file

@ -78,13 +78,13 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
// After london, default to 1559 unless gasPrice is set
// After banach, default to 1559 unless gasPrice is set
head := b.CurrentHeader()
// If user specifies both maxPriorityfee and maxFee, then we do not
// need to consult the chain for defaults. It's definitely a London tx.
// need to consult the chain for defaults. It's definitely a Banach tx.
if args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil {
// In this clause, user left some fields unspecified.
if b.ChainConfig().IsLondon(head.Number) && args.GasPrice == nil {
if b.ChainConfig().IsBanach(head.Number) && args.GasPrice == nil {
if args.MaxPriorityFeePerGas == nil {
tip, err := b.SuggestGasTipCap(ctx)
if err != nil {
@ -110,14 +110,14 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
}
} else {
if args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil {
return errors.New("maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet")
return errors.New("maxFeePerGas or maxPriorityFeePerGas specified but banach is not active yet")
}
if args.GasPrice == nil {
price, err := b.SuggestGasTipCap(ctx)
if err != nil {
return err
}
if b.ChainConfig().IsLondon(head.Number) {
if b.ChainConfig().IsBanach(head.Number) {
// The legacy tx gas price suggestion should not add 2x base fee
// because all fees are consumed, so it would result in a spiral
// upwards.

View file

@ -19,6 +19,7 @@ package les
import (
"context"
"errors"
"fmt"
"math/big"
"time"
@ -336,3 +337,6 @@ func (b *LesApiBackend) StateAtBlock(ctx context.Context, block *types.Block, re
func (b *LesApiBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) {
return b.eth.stateAtTransaction(ctx, block, txIndex, reexec)
}
func (b *LesApiBackend) StateAt(root common.Hash) (*state.StateDB, error) {
return nil, fmt.Errorf("StateAt is not supported in LES protocol")
}

View file

@ -39,6 +39,7 @@ import (
"github.com/scroll-tech/go-ethereum/metrics"
"github.com/scroll-tech/go-ethereum/params"
"github.com/scroll-tech/go-ethereum/rollup/circuitcapacitychecker"
"github.com/scroll-tech/go-ethereum/rollup/fees"
"github.com/scroll-tech/go-ethereum/rollup/tracing"
"github.com/scroll-tech/go-ethereum/trie"
)
@ -1322,20 +1323,15 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
Extra: w.extra,
Time: uint64(timestamp),
}
// Set baseFee and GasLimit if we are on an EIP-1559 chain
if w.chainConfig.IsLondon(header.Number) {
if w.chainConfig.Scroll.BaseFeeEnabled() {
header.BaseFee = misc.CalcBaseFee(w.chainConfig, parent.Header())
} else {
// When disabling EIP-2718 or EIP-1559, we do not set baseFeePerGas in RPC response.
// Setting BaseFee as nil here can help outside SDK calculates l2geth's RLP encoding,
// otherwise the l2geth's BaseFee is not known from the outside.
header.BaseFee = nil
}
if !w.chainConfig.IsLondon(parent.Number()) {
parentGasLimit := parent.GasLimit() * params.ElasticityMultiplier
header.GasLimit = core.CalcGasLimit(parentGasLimit, w.config.GasCeil)
// Set baseFee if we are on an EIP-1559 chain
if w.chainConfig.IsBanach(header.Number) {
state, err := w.chain.StateAt(parent.Root())
if err != nil {
log.Error("Failed to create mining context", "err", err)
return
}
parentL1BaseFee := fees.GetL1BaseFee(state)
header.BaseFee = misc.CalcBaseFee(w.chainConfig, parent.Header(), parentL1BaseFee)
}
// Only set the coinbase if our consensus engine is running (avoid spurious block rewards)
if w.isRunning() {

View file

@ -289,8 +289,6 @@ var (
MaxTxPerBlock: &ScrollMaxTxPerBlock,
MaxTxPayloadBytesPerBlock: &ScrollMaxTxPayloadBytesPerBlock,
FeeVaultAddress: &rcfg.ScrollFeeVaultAddress,
EnableEIP2718: false,
EnableEIP1559: false,
L1Config: &L1Config{
L1ChainId: 5,
L1MessageQueueAddress: common.HexToAddress("0x79DB48002Aa861C8cb189cabc21c6B1468BC83BB"),
@ -328,8 +326,6 @@ var (
MaxTxPerBlock: &ScrollMaxTxPerBlock,
MaxTxPayloadBytesPerBlock: &ScrollMaxTxPayloadBytesPerBlock,
FeeVaultAddress: &rcfg.ScrollFeeVaultAddress,
EnableEIP2718: false,
EnableEIP1559: false,
L1Config: &L1Config{
L1ChainId: 11155111,
L1MessageQueueAddress: common.HexToAddress("0xF0B2293F5D834eAe920c6974D50957A1732de763"),
@ -367,8 +363,6 @@ var (
MaxTxPerBlock: &ScrollMaxTxPerBlock,
MaxTxPayloadBytesPerBlock: &ScrollMaxTxPayloadBytesPerBlock,
FeeVaultAddress: &rcfg.ScrollFeeVaultAddress,
EnableEIP2718: false,
EnableEIP1559: false,
L1Config: &L1Config{
L1ChainId: 1,
L1MessageQueueAddress: common.HexToAddress("0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B"),
@ -383,12 +377,10 @@ var (
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, new(EthashConfig), nil,
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil,
ScrollConfig{
UseZktrie: false,
FeeVaultAddress: nil,
EnableEIP2718: true,
EnableEIP1559: true,
MaxTxPerBlock: nil,
MaxTxPayloadBytesPerBlock: nil,
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")},
@ -399,35 +391,29 @@ var (
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000},
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000},
ScrollConfig{
UseZktrie: false,
FeeVaultAddress: nil,
EnableEIP2718: true,
EnableEIP1559: true,
MaxTxPerBlock: nil,
MaxTxPayloadBytesPerBlock: nil,
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")},
}}
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, new(EthashConfig), nil,
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil,
ScrollConfig{
UseZktrie: false,
FeeVaultAddress: &common.Address{123},
EnableEIP2718: true,
EnableEIP1559: true,
MaxTxPerBlock: nil,
MaxTxPayloadBytesPerBlock: nil,
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")},
}}
TestRules = TestChainConfig.Rules(new(big.Int))
TestNoL1DataFeeChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, new(EthashConfig), nil,
TestNoL1DataFeeChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil,
ScrollConfig{
UseZktrie: false,
FeeVaultAddress: nil,
EnableEIP2718: true,
EnableEIP1559: true,
MaxTxPerBlock: nil,
MaxTxPayloadBytesPerBlock: nil,
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")},
@ -539,12 +525,6 @@ type ScrollConfig struct {
// Transaction fee vault address [optional]
FeeVaultAddress *common.Address `json:"feeVaultAddress,omitempty"`
// Enable EIP-2718 in tx pool [optional]
EnableEIP2718 bool `json:"enableEIP2718,omitempty"`
// Enable EIP-1559 in tx pool, EnableEIP2718 should be true too [optional]
EnableEIP1559 bool `json:"enableEIP1559,omitempty"`
// L1 config
L1Config *L1Config `json:"l1Config,omitempty"`
}
@ -566,10 +546,6 @@ func (c *L1Config) String() string {
c.L1ChainId, c.L1MessageQueueAddress.Hex(), c.NumL1MessagesPerBlock, c.ScrollChainAddress.Hex())
}
func (s ScrollConfig) BaseFeeEnabled() bool {
return s.EnableEIP2718 && s.EnableEIP1559
}
func (s ScrollConfig) FeeVaultEnabled() bool {
return s.FeeVaultAddress != nil
}
@ -593,8 +569,8 @@ func (s ScrollConfig) String() string {
maxTxPayloadBytesPerBlock = fmt.Sprintf("%v", *s.MaxTxPayloadBytesPerBlock)
}
return fmt.Sprintf("{useZktrie: %v, maxTxPerBlock: %v, MaxTxPayloadBytesPerBlock: %v, feeVaultAddress: %v, enableEIP2718: %v, enableEIP1559: %v, l1Config: %v}",
s.UseZktrie, maxTxPerBlock, maxTxPayloadBytesPerBlock, s.FeeVaultAddress, s.EnableEIP2718, s.EnableEIP1559, s.L1Config.String())
return fmt.Sprintf("{useZktrie: %v, maxTxPerBlock: %v, MaxTxPayloadBytesPerBlock: %v, feeVaultAddress: %v, l1Config: %v}",
s.UseZktrie, maxTxPerBlock, maxTxPayloadBytesPerBlock, s.FeeVaultAddress, s.L1Config.String())
}
// IsValidTxCount returns whether the given block's transaction count is below the limit.

View file

@ -24,7 +24,7 @@ import (
const (
VersionMajor = 5 // Major version component of the current release
VersionMinor = 1 // Minor version component of the current release
VersionPatch = 21 // Patch version component of the current release
VersionPatch = 22 // Patch version component of the current release
VersionMeta = "mainnet" // Version metadata to append to the version string
)

View file

@ -187,3 +187,7 @@ func CalculateL1DataFee(tx *types.Transaction, state StateDB) (*big.Int, error)
l1DataFee := calculateEncodedL1DataFee(raw, overhead, l1BaseFee, scalar)
return l1DataFee, nil
}
func GetL1BaseFee(state StateDB) *big.Int {
return state.GetState(rcfg.L1GasPriceOracleAddress, rcfg.L1BaseFeeSlot).Big()
}

View file

@ -188,7 +188,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
snaps, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter)
var baseFee *big.Int
if config.IsLondon(new(big.Int)) {
if config.IsBanach(new(big.Int)) {
baseFee = t.json.Env.BaseFee
if baseFee == nil {
// Retesteth uses `0x10` for genesis baseFee. Therefore, it defaults to