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") return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
} }
head := b.blockchain.CurrentHeader() 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 there's no basefee, then it must be a non-1559 execution
if call.GasPrice == nil { if call.GasPrice == nil {
call.GasPrice = new(big.Int) 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) { func (c *BoundContract) createLegacyTx(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) {
if opts.GasFeeCap != nil || opts.GasTipCap != nil { 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 // Normalize value
value := opts.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)) return NewError(ErrorJson, fmt.Errorf("failed signing transactions: %v", err))
} }
// Sanity check, to not `panic` in state_transition // Sanity check, to not `panic` in state_transition
if chainConfig.IsLondon(big.NewInt(int64(prestate.Env.Number))) { if chainConfig.IsBanach(big.NewInt(int64(prestate.Env.Number))) {
if prestate.Env.BaseFee == nil && chainConfig.Scroll.BaseFeeEnabled() { if prestate.Env.BaseFee == nil {
return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section")) 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. // signUnsignedTransactions converts the input txs to canonical transactions.
// //
// The transactions can have two forms, either // The transactions can have two forms, either
// 1. unsigned or // 1. unsigned or
// 2. signed // 2. signed
//
// For (1), r, s, v, need so be zero, and the `secretKey` needs to be set. // 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 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. // 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 { if header.GasUsed > header.GasLimit {
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", 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. // Verify BaseFee not present before EIP-1559 fork.
if header.BaseFee != nil { if header.BaseFee != nil {
return fmt.Errorf("invalid baseFee before fork: have %d, want <nil>", header.BaseFee) 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) 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. // 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. // Verify BaseFee not present before EIP-1559 fork.
if header.BaseFee != nil { if header.BaseFee != nil {
return fmt.Errorf("invalid baseFee before fork: have %d, expected 'nil'", header.BaseFee) return fmt.Errorf("invalid baseFee before fork: have %d, expected 'nil'", header.BaseFee)

View file

@ -20,90 +20,53 @@ import (
"fmt" "fmt"
"math/big" "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/core/types"
"github.com/scroll-tech/go-ethereum/params" "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, // VerifyEip1559Header verifies some header attributes which were changed in EIP-1559,
// - gas limit check // - gas limit check
// - basefee check // - basefee check
func VerifyEip1559Header(config *params.ChainConfig, parent, header *types.Header) error { func VerifyEip1559Header(config *params.ChainConfig, parent, header *types.Header) error {
// Verify that the gas limit remains within allowed bounds // Verify that the gas limit remains within allowed bounds
parentGasLimit := parent.GasLimit if err := VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil {
if !config.IsLondon(parent.Number) {
parentGasLimit = parent.GasLimit * params.ElasticityMultiplier
}
if err := VerifyGaslimit(parentGasLimit, header.GasLimit); err != nil {
return err return err
} }
// Verify the header is not malformed // Verify the header is not malformed
if header.BaseFee == nil && config.Scroll.BaseFeeEnabled() { if header.BaseFee == nil {
return fmt.Errorf("header is missing baseFee") return fmt.Errorf("header is missing baseFee")
} }
// Now BaseFee can be nil, because !config.Scroll.BaseFeeEnabled() // note: we do not verify L2 base fee, the sequencer has the
if header.BaseFee == nil { // right to set any base fee below the maximum. L2 base fee
return nil // is not subject to L2 consensus or zk verification.
} if header.BaseFee.Cmp(big.NewInt(MaximumL2BaseFee)) > 0 {
// Verify the baseFee is correct based on the parent header. return fmt.Errorf("invalid baseFee: have %s, maximum %d", header.BaseFee, MaximumL2BaseFee)
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)
} }
return nil return nil
} }
// CalcBaseFee calculates the basefee of the header. // CalcBaseFee calculates the basefee of the header.
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { func CalcBaseFee(config *params.ChainConfig, parent *types.Header, parentL1BaseFee *big.Int) *big.Int {
// If the current block is the first EIP-1559 block, return the InitialBaseFee. l2SequencerFee := big.NewInt(10000000) // 0.01 Gwei
if !config.IsLondon(parent.Number) { provingFee := big.NewInt(140000000) // 0.14 Gwei
return new(big.Int).SetUint64(params.InitialBaseFee)
// 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 ( return baseFee
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,
)
}
} }

View file

@ -20,7 +20,6 @@ import (
"math/big" "math/big"
"testing" "testing"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/params" "github.com/scroll-tech/go-ethereum/params"
) )
@ -52,7 +51,8 @@ func copyConfig(original *params.ChainConfig) *params.ChainConfig {
func config() *params.ChainConfig { func config() *params.ChainConfig {
config := copyConfig(params.TestChainConfig) config := copyConfig(params.TestChainConfig)
config.LondonBlock = big.NewInt(5) config.LondonBlock = big.NewInt(3)
config.BanachBlock = big.NewInt(5)
return config return config
} }
@ -67,13 +67,13 @@ func TestBlockGasLimits(t *testing.T) {
gasLimit uint64 gasLimit uint64
ok bool ok bool
}{ }{
// Transitions from non-london to london // Transitions from non-banach to banach
{10000000, 4, 20000000, true}, // No change {10000000, 4, 10000000, true}, // No change
{10000000, 4, 20019530, true}, // Upper limit {10000000, 4, 10009764, true}, // Upper limit
{10000000, 4, 20019531, false}, // Upper +1 {10000000, 4, 10009765, false}, // Upper +1
{10000000, 4, 19980470, true}, // Lower limit {10000000, 4, 9990236, true}, // Lower limit
{10000000, 4, 19980469, false}, // Lower limit -1 {10000000, 4, 9990235, false}, // Lower limit -1
// London to London // Banach to Banach
{20000000, 5, 20000000, true}, {20000000, 5, 20000000, true},
{20000000, 5, 20019530, true}, // Upper limit {20000000, 5, 20019530, true}, // Upper limit
{20000000, 5, 20019531, false}, // Upper limit +1 {20000000, 5, 20019531, false}, // Upper limit +1
@ -109,23 +109,18 @@ func TestBlockGasLimits(t *testing.T) {
// TestCalcBaseFee assumes all blocks are 1559-blocks // TestCalcBaseFee assumes all blocks are 1559-blocks
func TestCalcBaseFee(t *testing.T) { func TestCalcBaseFee(t *testing.T) {
tests := []struct { tests := []struct {
parentBaseFee int64 parentL1BaseFee int64
parentGasLimit uint64 expectedL2BaseFee int64
parentGasUsed uint64
expectedBaseFee int64
}{ }{
{params.InitialBaseFee, 20000000, 10000000, params.InitialBaseFee}, // usage == target {0, 150000000},
{params.InitialBaseFee, 20000000, 9000000, 987500000}, // usage below target {1000000000, 164000000},
{params.InitialBaseFee, 20000000, 11000000, 1012500000}, // usage above target {2000000000, 178000000},
{100000000000, 1550000000},
{111111111111, 1705555555},
{1000000000000, 10000000000}, // cap at max L2 base fee
} }
for i, test := range tests { for i, test := range tests {
parent := &types.Header{ if have, want := CalcBaseFee(config(), nil, big.NewInt(test.parentL1BaseFee)), big.NewInt(test.expectedL2BaseFee); have.Cmp(want) != 0 {
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 {
t.Errorf("test %d: have %d want %d, ", i, have, want) 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) headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil)
headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil) headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil)
l2BaseFeeGauge = metrics.NewRegisteredGauge("chain/fees/l2basefee", nil)
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil) accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil) accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
accountUpdateTimer = metrics.NewRegisteredTimer("chain/account/updates", nil) accountUpdateTimer = metrics.NewRegisteredTimer("chain/account/updates", nil)
@ -1246,6 +1248,13 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
return NonStatTy, errInsertionInterrupted 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 // Calculate the total difficulty of the block
ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1) ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
if ptd == nil { if ptd == nil {

View file

@ -607,7 +607,7 @@ func TestFastVsFullChains(t *testing.T) {
gendb = rawdb.NewMemoryDatabase() gendb = rawdb.NewMemoryDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey) address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000000000) funds = big.NewInt(3000000000000000)
gspec = &Genesis{ gspec = &Genesis{
Config: params.TestChainConfig, Config: params.TestChainConfig,
Alloc: GenesisAlloc{address: {Balance: funds}}, Alloc: GenesisAlloc{address: {Balance: funds}},
@ -1704,6 +1704,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
t.Fatalf("failed to create temp freezer db: %v", err) t.Fatalf("failed to create temp freezer db: %v", err)
} }
gspec := Genesis{Config: params.AllEthashProtocolChanges} gspec := Genesis{Config: params.AllEthashProtocolChanges}
gspec.BaseFee = big.NewInt(params.InitialBaseFee)
gspec.MustCommit(ancientDb) gspec.MustCommit(ancientDb)
ancientChain, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) ancientChain, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancientChain.Stop() defer ancientChain.Stop()
@ -3171,7 +3172,10 @@ func TestFeeVault(t *testing.T) {
// Ensure that the fee vault received all tx fees // Ensure that the fee vault received all tx fees
actual = state.GetBalance(*params.TestChainConfig.Scroll.FeeVaultAddress) 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 { if actual.Cmp(expected) != 0 {
t.Fatalf("fee vault balance incorrect: expected %d, got %d", expected, actual) 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/core/vm"
"github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/ethdb"
"github.com/scroll-tech/go-ethereum/params" "github.com/scroll-tech/go-ethereum/params"
"github.com/scroll-tech/go-ethereum/rollup/fees"
) )
// BlockGen creates blocks for testing. // 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), Number: new(big.Int).Add(parent.Number(), common.Big1),
Time: time, Time: time,
} }
if chain.Config().IsLondon(header.Number) { if chain.Config().IsBanach(header.Number) {
header.BaseFee = misc.CalcBaseFee(chain.Config(), parent.Header()) parentL1BaseFee := fees.GetL1BaseFee(state)
if !chain.Config().IsLondon(parent.Number()) { header.BaseFee = misc.CalcBaseFee(chain.Config(), parent.Header(), parentL1BaseFee)
parentGasLimit := parent.GasLimit() * params.ElasticityMultiplier
header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
}
} }
return header return header
} }

View file

@ -28,6 +28,7 @@ import (
"github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/common/hexutil" "github.com/scroll-tech/go-ethereum/common/hexutil"
"github.com/scroll-tech/go-ethereum/common/math" "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/rawdb"
"github.com/scroll-tech/go-ethereum/core/state" "github.com/scroll-tech/go-ethereum/core/state"
"github.com/scroll-tech/go-ethereum/core/types" "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 { if g.Difficulty == nil {
head.Difficulty = params.GenesisDifficulty 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 { if g.BaseFee != nil {
head.BaseFee = g.BaseFee head.BaseFee = g.BaseFee
} else if g.Config.Scroll.BaseFeeEnabled() {
head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee)
} else { } else {
head.BaseFee = nil head.BaseFee = misc.CalcBaseFee(g.Config, nil, big.NewInt(0))
} }
} }
statedb.Commit(false) statedb.Commit(false)

View file

@ -56,6 +56,7 @@ func TestStateProcessorErrors(t *testing.T) {
BerlinBlock: big.NewInt(0), BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ShanghaiBlock: big.NewInt(0), ShanghaiBlock: big.NewInt(0),
BanachBlock: big.NewInt(0),
Ethash: new(params.EthashConfig), Ethash: new(params.EthashConfig),
} }
signer = types.LatestSigner(config) signer = types.LatestSigner(config)
@ -332,6 +333,7 @@ func TestStateProcessorErrors(t *testing.T) {
ArrowGlacierBlock: big.NewInt(0), ArrowGlacierBlock: big.NewInt(0),
ArchimedesBlock: big.NewInt(0), ArchimedesBlock: big.NewInt(0),
ShanghaiBlock: big.NewInt(0), ShanghaiBlock: big.NewInt(0),
BanachBlock: big.NewInt(0),
}, },
Alloc: GenesisAlloc{ Alloc: GenesisAlloc{
common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{ common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{
@ -346,21 +348,22 @@ func TestStateProcessorErrors(t *testing.T) {
smallInitCode = [320]byte{} smallInitCode = [320]byte{}
) )
defer blockchain.Stop() defer blockchain.Stop()
parentL1BaseFee := big.NewInt(1000000000) // 1 gwei
for i, tt := range []struct { for i, tt := range []struct {
txs []*types.Transaction txs []*types.Transaction
want string want string
}{ }{
{ // ErrMaxInitCodeSizeExceeded { // ErrMaxInitCodeSizeExceeded
txs: []*types.Transaction{ 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 { // ErrIntrinsicGas: Not enough gas to cover init code
txs: []*types.Transaction{ 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) 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, Time: parent.Time() + 10,
UncleHash: types.EmptyUncleHash, 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 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 // 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) // 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) { if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call) // 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 { 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) st.refundGas(params.RefundQuotientEIP3529)
} }
effectiveTip := st.gasPrice effectiveTip := st.gasPrice
if rules.IsLondon {
if st.evm.Context.BaseFee != nil { // only burn the base fee if the fee vault is not enabled
effectiveTip = cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee)) if rules.IsBanach && !st.evm.ChainConfig().Scroll.FeeVaultEnabled() {
} else { effectiveTip = cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee))
effectiveTip = cmath.BigMin(st.gasTipCap, st.gasFeeCap)
}
} }
// The L2 Fee is the same as the fee that is charged in the normal geth // 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). // because of another transaction (e.g. higher gas price).
if reset != nil { if reset != nil {
pool.demoteUnexecutables() pool.demoteUnexecutables()
if reset.newHead != nil && pool.chainconfig.IsLondon(new(big.Int).Add(reset.newHead.Number, big.NewInt(1))) { if reset.newHead != nil && pool.chainconfig.IsBanach(new(big.Int).Add(reset.newHead.Number, big.NewInt(1))) {
pendingBaseFee := misc.CalcBaseFee(pool.chainconfig, reset.newHead) l1BaseFee := fees.GetL1BaseFee(pool.currentState)
pendingBaseFee := misc.CalcBaseFee(pool.chainconfig, reset.newHead, l1BaseFee)
pool.priced.SetBaseFee(pendingBaseFee) pool.priced.SetBaseFee(pendingBaseFee)
} }
// Update all accounts to the latest known pending nonce // 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)) next := new(big.Int).Add(newHead.Number, big.NewInt(1))
pool.istanbul = pool.chainconfig.IsIstanbul(next) pool.istanbul = pool.chainconfig.IsIstanbul(next)
pool.eip2718 = pool.chainconfig.Scroll.EnableEIP2718 && pool.chainconfig.IsBerlin(next) pool.eip2718 = pool.chainconfig.IsBanach(next)
pool.eip1559 = pool.chainconfig.Scroll.EnableEIP1559 && pool.chainconfig.IsLondon(next) pool.eip1559 = pool.chainconfig.IsBanach(next)
pool.shanghai = pool.chainconfig.IsShanghai(next) pool.shanghai = pool.chainconfig.IsShanghai(next)
} }

View file

@ -148,20 +148,23 @@ type StorageWrapper struct {
} }
type TransactionData struct { type TransactionData struct {
Type uint8 `json:"type"` Type uint8 `json:"type"`
Nonce uint64 `json:"nonce"` Nonce uint64 `json:"nonce"`
TxHash string `json:"txHash"` TxHash string `json:"txHash"`
Gas uint64 `json:"gas"` Gas uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"` GasPrice *hexutil.Big `json:"gasPrice"`
From common.Address `json:"from"` GasTipCap *hexutil.Big `json:"gasTipCap"`
To *common.Address `json:"to"` GasFeeCap *hexutil.Big `json:"gasFeeCap"`
ChainId *hexutil.Big `json:"chainId"` From common.Address `json:"from"`
Value *hexutil.Big `json:"value"` To *common.Address `json:"to"`
Data string `json:"data"` ChainId *hexutil.Big `json:"chainId"`
IsCreate bool `json:"isCreate"` Value *hexutil.Big `json:"value"`
V *hexutil.Big `json:"v"` Data string `json:"data"`
R *hexutil.Big `json:"r"` IsCreate bool `json:"isCreate"`
S *hexutil.Big `json:"s"` 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 // 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{ result := &TransactionData{
Type: tx.Type(), Type: tx.Type(),
TxHash: tx.Hash().String(), TxHash: tx.Hash().String(),
Nonce: nonce, Nonce: nonce,
ChainId: (*hexutil.Big)(tx.ChainId()), ChainId: (*hexutil.Big)(tx.ChainId()),
From: from, From: from,
Gas: tx.Gas(), Gas: tx.Gas(),
GasPrice: (*hexutil.Big)(tx.GasPrice()), GasPrice: (*hexutil.Big)(tx.GasPrice()),
To: tx.To(), GasTipCap: (*hexutil.Big)(tx.GasTipCap()),
Value: (*hexutil.Big)(tx.Value()), GasFeeCap: (*hexutil.Big)(tx.GasFeeCap()),
Data: hexutil.Encode(tx.Data()), To: tx.To(),
IsCreate: tx.To() == nil, Value: (*hexutil.Big)(tx.Value()),
V: (*hexutil.Big)(v), Data: hexutil.Encode(tx.Data()),
R: (*hexutil.Big)(r), IsCreate: tx.To() == nil,
S: (*hexutil.Big)(s), AccessList: tx.AccessList(),
V: (*hexutil.Big)(v),
R: (*hexutil.Big)(r),
S: (*hexutil.Big)(s),
} }
return result return result
} }

View file

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

View file

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

View file

@ -59,11 +59,20 @@ var (
berlinInstructionSet = newBerlinInstructionSet() berlinInstructionSet = newBerlinInstructionSet()
londonInstructionSet = newLondonInstructionSet() londonInstructionSet = newLondonInstructionSet()
shanghaiInstructionSet = newShanghaiInstructionSet() shanghaiInstructionSet = newShanghaiInstructionSet()
banachInstructionSet = newBanachInstructionSet()
) )
// JumpTable contains the EVM opcodes supported at a given fork. // JumpTable contains the EVM opcodes supported at a given fork.
type JumpTable [256]*operation 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, // newShanghaiInstructionSet returns the frontier, homestead, byzantium,
// contantinople, istanbul, petersburg, berlin, london and shanghai instructions. // contantinople, istanbul, petersburg, berlin, london and shanghai instructions.
func newShanghaiInstructionSet() JumpTable { 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) { 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) 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/log"
"github.com/scroll-tech/go-ethereum/node" "github.com/scroll-tech/go-ethereum/node"
chainParams "github.com/scroll-tech/go-ethereum/params" 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/rpc"
"github.com/scroll-tech/go-ethereum/trie" "github.com/scroll-tech/go-ethereum/trie"
) )
@ -141,8 +142,13 @@ func (api *consensusAPI) AssembleBlock(params assembleBlockParams) (*executableD
Extra: []byte{}, Extra: []byte{},
Time: params.Timestamp, Time: params.Timestamp,
} }
if config := api.eth.BlockChain().Config(); config.IsLondon(header.Number) { if config := api.eth.BlockChain().Config(); config.IsBanach(header.Number) {
header.BaseFee = misc.CalcBaseFee(config, parent.Header()) 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) err = api.eth.Engine().Prepare(bc, header)
if err != nil { if err != nil {
@ -245,7 +251,7 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
return txs, nil 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) txs, err := decodeTransactions(params.Transactions)
if err != nil { if err != nil {
return nil, err return nil, err
@ -267,8 +273,8 @@ func insertBlockParamsToBlock(config *chainParams.ChainConfig, parent *types.Hea
GasUsed: params.GasUsed, GasUsed: params.GasUsed,
Time: params.Timestamp, Time: params.Timestamp,
} }
if config.IsLondon(number) { if config.IsBanach(number) {
header.BaseFee = misc.CalcBaseFee(config, parent) header.BaseFee = misc.CalcBaseFee(config, parent, parentL1BaseFee)
} }
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */) block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */)
return block, nil return block, nil
@ -282,7 +288,12 @@ func (api *consensusAPI) NewBlock(params executableData) (*newBlockResponse, err
if parent == nil { if parent == nil {
return &newBlockResponse{false}, fmt.Errorf("could not find parent %x", params.ParentHash) 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 { if err != nil {
return nil, err return nil, err
} }

View file

@ -30,6 +30,7 @@ import (
"github.com/scroll-tech/go-ethereum/consensus/misc" "github.com/scroll-tech/go-ethereum/consensus/misc"
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/log" "github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/rollup/fees"
"github.com/scroll-tech/go-ethereum/rpc" "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 { if bf.results.baseFee = bf.header.BaseFee; bf.results.baseFee == nil {
bf.results.baseFee = new(big.Int) bf.results.baseFee = new(big.Int)
} }
if chainconfig.IsLondon(big.NewInt(int64(bf.blockNumber + 1))) { if chainconfig.IsBanach(big.NewInt(int64(bf.blockNumber + 1))) {
bf.results.nextBaseFee = misc.CalcBaseFee(chainconfig, bf.header) 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 { } else {
bf.results.nextBaseFee = new(big.Int) 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 // 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. // are not available or when the head has changed during processing this request.
// Three arrays are returned based on the processed blocks: // Three arrays are returned based on the processed blocks:
// - reward: the requested percentiles of effective priority fees per gas of transactions in each // - reward: the requested percentiles of effective priority fees per gas of transactions in each
// block, sorted in ascending order and weighted by gas used. // block, sorted in ascending order and weighted by gas used.
// - baseFee: base fee per gas in the given block // - baseFee: base fee per gas in the given block
// - gasUsedRatio: gasUsed/gasLimit 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 // Note: baseFee includes the next block after the newest of the returned range, because this
// value can be derived from the newest block. // 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) { 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/common"
"github.com/scroll-tech/go-ethereum/core" "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/core/types"
"github.com/scroll-tech/go-ethereum/event" "github.com/scroll-tech/go-ethereum/event"
"github.com/scroll-tech/go-ethereum/log" "github.com/scroll-tech/go-ethereum/log"
@ -58,6 +59,7 @@ type OracleBackend interface {
PendingBlockAndReceipts() (*types.Block, types.Receipts) PendingBlockAndReceipts() (*types.Block, types.Receipts)
ChainConfig() *params.ChainConfig ChainConfig() *params.ChainConfig
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
StateAt(root common.Hash) (*state.StateDB, error)
} }
// Oracle recommends gas prices based on the content of recent // 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/consensus/ethash"
"github.com/scroll-tech/go-ethereum/core" "github.com/scroll-tech/go-ethereum/core"
"github.com/scroll-tech/go-ethereum/core/rawdb" "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/types"
"github.com/scroll-tech/go-ethereum/core/vm" "github.com/scroll-tech/go-ethereum/core/vm"
"github.com/scroll-tech/go-ethereum/crypto" "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.LondonBlock = londonBlock
config.ArrowGlacierBlock = londonBlock config.ArrowGlacierBlock = londonBlock
config.ArchimedesBlock = londonBlock
config.ShanghaiBlock = londonBlock
config.BanachBlock = londonBlock
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
genesis, err := gspec.Commit(db) genesis, err := gspec.Commit(db)
@ -160,6 +164,10 @@ func (b *testBackend) GetBlockByNumber(number uint64) *types.Block {
return b.chain.GetBlockByNumber(number) return b.chain.GetBlockByNumber(number)
} }
func (b *testBackend) StateAt(root common.Hash) (*state.StateDB, error) {
return nil, nil
}
func TestSuggestTipCap(t *testing.T) { func TestSuggestTipCap(t *testing.T) {
config := Config{ config := Config{
Blocks: 3, Blocks: 3,

View file

@ -159,11 +159,20 @@ func (s *PublicTxPoolAPI) Content() map[string]map[string]map[string]*RPCTransac
} }
pending, queue := s.b.TxPoolContent() pending, queue := s.b.TxPoolContent()
curHeader := s.b.CurrentHeader() 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 // Flatten the pending transactions
for account, txs := range pending { for account, txs := range pending {
dump := make(map[string]*RPCTransaction) dump := make(map[string]*RPCTransaction)
for _, tx := range txs { 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 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 { for account, txs := range queue {
dump := make(map[string]*RPCTransaction) dump := make(map[string]*RPCTransaction)
for _, tx := range txs { 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 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) pending, queue := s.b.TxPoolContentFrom(addr)
curHeader := s.b.CurrentHeader() 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 // Build the pending transactions
dump := make(map[string]*RPCTransaction, len(pending)) dump := make(map[string]*RPCTransaction, len(pending))
for _, tx := range 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 content["pending"] = dump
// Build the queued transactions // Build the queued transactions
dump = make(map[string]*RPCTransaction, len(queue)) dump = make(map[string]*RPCTransaction, len(queue))
for _, tx := range 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 content["queued"] = dump
@ -741,10 +758,10 @@ func (s *PublicBlockChainAPI) GetHeaderByHash(ctx context.Context, hash common.H
} }
// GetBlockByNumber returns the requested canonical block. // GetBlockByNumber returns the requested canonical block.
// * When blockNr is -1 the chain head is returned. // - When blockNr is -1 the chain head is returned.
// * When blockNr is -2 the pending 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 // - When fullTx is true all transactions in the block are returned, otherwise
// only the transaction hash is returned. // only the transaction hash is returned.
func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
block, err := s.b.BlockByNumber(ctx, number) block, err := s.b.BlockByNumber(ctx, number)
if block != nil && err == nil { 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 . // 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{}{ result := map[string]interface{}{
"number": (*hexutil.Big)(head.Number), "number": (*hexutil.Big)(head.Number),
"hash": head.Hash(), "hash": head.Hash(),
@ -1207,7 +1224,7 @@ func RPCMarshalHeader(head *types.Header, enableBaseFee bool) map[string]interfa
"receiptsRoot": head.ReceiptHash, "receiptsRoot": head.ReceiptHash,
} }
if enableBaseFee && head.BaseFee != nil { if head.BaseFee != nil {
result["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee) 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 // returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
// transaction hashes. // transaction hashes.
func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *params.ChainConfig) (map[string]interface{}, error) { 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()) fields["size"] = hexutil.Uint64(block.Size())
if inclTx { 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 // rpcMarshalHeader uses the generalized output filler, then adds the total difficulty field, which requires
// a `PublicBlockchainAPI`. // a `PublicBlockchainAPI`.
func (s *PublicBlockChainAPI) rpcMarshalHeader(ctx context.Context, header *types.Header) map[string]interface{} { 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())) fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(ctx, header.Hash()))
return fields 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 // 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 var baseFee *big.Int
blockNumber := uint64(0) blockNumber := uint64(0)
if current != nil { if current != nil {
baseFee = misc.CalcBaseFee(config, current) baseFee = misc.CalcBaseFee(config, current, l1BaseFee)
blockNumber = current.Number.Uint64() blockNumber = current.Number.Uint64()
} }
return NewRPCTransaction(tx, common.Hash{}, blockNumber, 0, baseFee, config) 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 // No finalized transaction, try to retrieve it from the pool
if tx := s.b.GetPoolTransaction(hash); tx != nil { 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 // Transaction unknown, return as such
@ -1654,7 +1681,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha
"l1Fee": (*hexutil.Big)(receipt.L1Fee), "l1Fee": (*hexutil.Big)(receipt.L1Fee),
} }
// Assign the effective gas price paid // 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()) fields["effectiveGasPrice"] = hexutil.Uint64(tx.GasPrice().Uint64())
} else { } else {
header, err := s.b.HeaderByHash(ctx, blockHash) header, err := s.b.HeaderByHash(ctx, blockHash)
@ -1866,10 +1893,19 @@ func (s *PublicTransactionPoolAPI) PendingTransactions() ([]*RPCTransaction, err
} }
curHeader := s.b.CurrentHeader() curHeader := s.b.CurrentHeader()
transactions := make([]*RPCTransaction, 0, len(pending)) 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 { for _, tx := range pending {
from, _ := types.Sender(s.signer, tx) from, _ := types.Sender(s.signer, tx)
if _, exists := accounts[from]; exists { 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 return transactions, nil

View file

@ -65,6 +65,7 @@ type Backend interface {
BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error)
StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, 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) 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) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
GetTd(ctx context.Context, hash common.Hash) *big.Int 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) 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) { if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") 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() head := b.CurrentHeader()
// If user specifies both maxPriorityfee and maxFee, then we do not // 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 { if args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil {
// In this clause, user left some fields unspecified. // 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 { if args.MaxPriorityFeePerGas == nil {
tip, err := b.SuggestGasTipCap(ctx) tip, err := b.SuggestGasTipCap(ctx)
if err != nil { if err != nil {
@ -110,14 +110,14 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
} }
} else { } else {
if args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil { 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 { if args.GasPrice == nil {
price, err := b.SuggestGasTipCap(ctx) price, err := b.SuggestGasTipCap(ctx)
if err != nil { if err != nil {
return err 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 // The legacy tx gas price suggestion should not add 2x base fee
// because all fees are consumed, so it would result in a spiral // because all fees are consumed, so it would result in a spiral
// upwards. // upwards.

View file

@ -19,6 +19,7 @@ package les
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"math/big" "math/big"
"time" "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) { 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) 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/metrics"
"github.com/scroll-tech/go-ethereum/params" "github.com/scroll-tech/go-ethereum/params"
"github.com/scroll-tech/go-ethereum/rollup/circuitcapacitychecker" "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/rollup/tracing"
"github.com/scroll-tech/go-ethereum/trie" "github.com/scroll-tech/go-ethereum/trie"
) )
@ -1322,20 +1323,15 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
Extra: w.extra, Extra: w.extra,
Time: uint64(timestamp), Time: uint64(timestamp),
} }
// Set baseFee and GasLimit if we are on an EIP-1559 chain // Set baseFee if we are on an EIP-1559 chain
if w.chainConfig.IsLondon(header.Number) { if w.chainConfig.IsBanach(header.Number) {
if w.chainConfig.Scroll.BaseFeeEnabled() { state, err := w.chain.StateAt(parent.Root())
header.BaseFee = misc.CalcBaseFee(w.chainConfig, parent.Header()) if err != nil {
} else { log.Error("Failed to create mining context", "err", err)
// When disabling EIP-2718 or EIP-1559, we do not set baseFeePerGas in RPC response. return
// 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)
} }
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) // Only set the coinbase if our consensus engine is running (avoid spurious block rewards)
if w.isRunning() { if w.isRunning() {

View file

@ -289,8 +289,6 @@ var (
MaxTxPerBlock: &ScrollMaxTxPerBlock, MaxTxPerBlock: &ScrollMaxTxPerBlock,
MaxTxPayloadBytesPerBlock: &ScrollMaxTxPayloadBytesPerBlock, MaxTxPayloadBytesPerBlock: &ScrollMaxTxPayloadBytesPerBlock,
FeeVaultAddress: &rcfg.ScrollFeeVaultAddress, FeeVaultAddress: &rcfg.ScrollFeeVaultAddress,
EnableEIP2718: false,
EnableEIP1559: false,
L1Config: &L1Config{ L1Config: &L1Config{
L1ChainId: 5, L1ChainId: 5,
L1MessageQueueAddress: common.HexToAddress("0x79DB48002Aa861C8cb189cabc21c6B1468BC83BB"), L1MessageQueueAddress: common.HexToAddress("0x79DB48002Aa861C8cb189cabc21c6B1468BC83BB"),
@ -328,8 +326,6 @@ var (
MaxTxPerBlock: &ScrollMaxTxPerBlock, MaxTxPerBlock: &ScrollMaxTxPerBlock,
MaxTxPayloadBytesPerBlock: &ScrollMaxTxPayloadBytesPerBlock, MaxTxPayloadBytesPerBlock: &ScrollMaxTxPayloadBytesPerBlock,
FeeVaultAddress: &rcfg.ScrollFeeVaultAddress, FeeVaultAddress: &rcfg.ScrollFeeVaultAddress,
EnableEIP2718: false,
EnableEIP1559: false,
L1Config: &L1Config{ L1Config: &L1Config{
L1ChainId: 11155111, L1ChainId: 11155111,
L1MessageQueueAddress: common.HexToAddress("0xF0B2293F5D834eAe920c6974D50957A1732de763"), L1MessageQueueAddress: common.HexToAddress("0xF0B2293F5D834eAe920c6974D50957A1732de763"),
@ -367,8 +363,6 @@ var (
MaxTxPerBlock: &ScrollMaxTxPerBlock, MaxTxPerBlock: &ScrollMaxTxPerBlock,
MaxTxPayloadBytesPerBlock: &ScrollMaxTxPayloadBytesPerBlock, MaxTxPayloadBytesPerBlock: &ScrollMaxTxPayloadBytesPerBlock,
FeeVaultAddress: &rcfg.ScrollFeeVaultAddress, FeeVaultAddress: &rcfg.ScrollFeeVaultAddress,
EnableEIP2718: false,
EnableEIP1559: false,
L1Config: &L1Config{ L1Config: &L1Config{
L1ChainId: 1, L1ChainId: 1,
L1MessageQueueAddress: common.HexToAddress("0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B"), L1MessageQueueAddress: common.HexToAddress("0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B"),
@ -383,12 +377,10 @@ var (
// //
// This configuration is intentionally not using keyed fields to force anyone // This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields. // 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{ ScrollConfig{
UseZktrie: false, UseZktrie: false,
FeeVaultAddress: nil, FeeVaultAddress: nil,
EnableEIP2718: true,
EnableEIP1559: true,
MaxTxPerBlock: nil, MaxTxPerBlock: nil,
MaxTxPayloadBytesPerBlock: nil, MaxTxPayloadBytesPerBlock: nil,
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")}, 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 // This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields. // 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{ ScrollConfig{
UseZktrie: false, UseZktrie: false,
FeeVaultAddress: nil, FeeVaultAddress: nil,
EnableEIP2718: true,
EnableEIP1559: true,
MaxTxPerBlock: nil, MaxTxPerBlock: nil,
MaxTxPayloadBytesPerBlock: nil, MaxTxPayloadBytesPerBlock: nil,
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")}, 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{ ScrollConfig{
UseZktrie: false, UseZktrie: false,
FeeVaultAddress: &common.Address{123}, FeeVaultAddress: &common.Address{123},
EnableEIP2718: true,
EnableEIP1559: true,
MaxTxPerBlock: nil, MaxTxPerBlock: nil,
MaxTxPayloadBytesPerBlock: nil, MaxTxPayloadBytesPerBlock: nil,
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")}, L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")},
}} }}
TestRules = TestChainConfig.Rules(new(big.Int)) 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{ ScrollConfig{
UseZktrie: false, UseZktrie: false,
FeeVaultAddress: nil, FeeVaultAddress: nil,
EnableEIP2718: true,
EnableEIP1559: true,
MaxTxPerBlock: nil, MaxTxPerBlock: nil,
MaxTxPayloadBytesPerBlock: nil, MaxTxPayloadBytesPerBlock: nil,
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")}, L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")},
@ -539,12 +525,6 @@ type ScrollConfig struct {
// Transaction fee vault address [optional] // Transaction fee vault address [optional]
FeeVaultAddress *common.Address `json:"feeVaultAddress,omitempty"` 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 // L1 config
L1Config *L1Config `json:"l1Config,omitempty"` L1Config *L1Config `json:"l1Config,omitempty"`
} }
@ -566,10 +546,6 @@ func (c *L1Config) String() string {
c.L1ChainId, c.L1MessageQueueAddress.Hex(), c.NumL1MessagesPerBlock, c.ScrollChainAddress.Hex()) 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 { func (s ScrollConfig) FeeVaultEnabled() bool {
return s.FeeVaultAddress != nil return s.FeeVaultAddress != nil
} }
@ -593,8 +569,8 @@ func (s ScrollConfig) String() string {
maxTxPayloadBytesPerBlock = fmt.Sprintf("%v", *s.MaxTxPayloadBytesPerBlock) maxTxPayloadBytesPerBlock = fmt.Sprintf("%v", *s.MaxTxPayloadBytesPerBlock)
} }
return fmt.Sprintf("{useZktrie: %v, maxTxPerBlock: %v, MaxTxPayloadBytesPerBlock: %v, feeVaultAddress: %v, enableEIP2718: %v, enableEIP1559: %v, l1Config: %v}", return fmt.Sprintf("{useZktrie: %v, maxTxPerBlock: %v, MaxTxPayloadBytesPerBlock: %v, feeVaultAddress: %v, l1Config: %v}",
s.UseZktrie, maxTxPerBlock, maxTxPayloadBytesPerBlock, s.FeeVaultAddress, s.EnableEIP2718, s.EnableEIP1559, s.L1Config.String()) s.UseZktrie, maxTxPerBlock, maxTxPayloadBytesPerBlock, s.FeeVaultAddress, s.L1Config.String())
} }
// IsValidTxCount returns whether the given block's transaction count is below the limit. // IsValidTxCount returns whether the given block's transaction count is below the limit.

View file

@ -24,7 +24,7 @@ import (
const ( const (
VersionMajor = 5 // Major version component of the current release VersionMajor = 5 // Major version component of the current release
VersionMinor = 1 // Minor 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 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) l1DataFee := calculateEncodedL1DataFee(raw, overhead, l1BaseFee, scalar)
return l1DataFee, nil 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) snaps, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter)
var baseFee *big.Int var baseFee *big.Int
if config.IsLondon(new(big.Int)) { if config.IsBanach(new(big.Int)) {
baseFee = t.json.Env.BaseFee baseFee = t.json.Env.BaseFee
if baseFee == nil { if baseFee == nil {
// Retesteth uses `0x10` for genesis baseFee. Therefore, it defaults to // Retesteth uses `0x10` for genesis baseFee. Therefore, it defaults to