From b010efe195259e7c98e0ad6fb91b0c6484ae2b80 Mon Sep 17 00:00:00 2001 From: Gavin Yu Date: Tue, 27 Aug 2024 15:13:09 +0800 Subject: [PATCH] fix(taiko-client): fix some issues about `calculateBaseFee` (#17978) Co-authored-by: David Co-authored-by: maskpp --- .../bindings/encoding/protocol_config.go | 2 +- .../driver/chain_syncer/blob/syncer.go | 2 +- .../taiko-client/pkg/config/chain_config.go | 26 ++++---- packages/taiko-client/pkg/rpc/methods.go | 66 +++++++++++++++++-- packages/taiko-client/proposer/proposer.go | 7 +- .../taiko-client/proposer/proposer_test.go | 4 +- .../proposer/transaction_builder/blob.go | 6 +- .../proposer/transaction_builder/calldata.go | 6 +- .../transaction_builder/common_test.go | 8 ++- 9 files changed, 100 insertions(+), 27 deletions(-) diff --git a/packages/taiko-client/bindings/encoding/protocol_config.go b/packages/taiko-client/bindings/encoding/protocol_config.go index e4b6601c564..22e37239440 100644 --- a/packages/taiko-client/bindings/encoding/protocol_config.go +++ b/packages/taiko-client/bindings/encoding/protocol_config.go @@ -36,7 +36,7 @@ var ( LivenessBond: livenessBond, StateRootSyncInternal: 16, MaxAnchorHeightOffset: 64, - OntakeForkHeight: 720_000, + OntakeForkHeight: 793_000, BaseFeeConfig: bindings.TaikoDataBaseFeeConfig{ AdjustmentQuotient: 8, SharingPctg: 75, diff --git a/packages/taiko-client/driver/chain_syncer/blob/syncer.go b/packages/taiko-client/driver/chain_syncer/blob/syncer.go index 97ce314fc95..212db5018e6 100644 --- a/packages/taiko-client/driver/chain_syncer/blob/syncer.go +++ b/packages/taiko-client/driver/chain_syncer/blob/syncer.go @@ -377,7 +377,7 @@ func (s *Syncer) insertNewHead( } var parentGasExcess uint64 - if newGasTarget != parentGasTarget { + if newGasTarget != parentGasTarget && parentGasTarget != 0 { oldParentGasExcess, err := s.rpc.TaikoL2.ParentGasExcess(&bind.CallOpts{ BlockNumber: parent.Number, Context: ctx, }) diff --git a/packages/taiko-client/pkg/config/chain_config.go b/packages/taiko-client/pkg/config/chain_config.go index 3647aebea60..c0a05974b2d 100644 --- a/packages/taiko-client/pkg/config/chain_config.go +++ b/packages/taiko-client/pkg/config/chain_config.go @@ -5,19 +5,21 @@ import ( "math/big" "strings" + "github.com/taikoxyz/taiko-mono/packages/taiko-client/bindings" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" ) // ChainConfig is the core config which determines the blockchain settings. type ChainConfig struct { - ChainID *big.Int `json:"chainId"` // ChainId identifies the current chain - OnTakeBlock *big.Int `json:"onTakeBlock"` // Ontake switch block (nil = no fork, 0 = already on ontake) + // Ontake switch block (nil = no fork, 0 = already on ontake) + ProtocolConfigs *bindings.TaikoDataConfig `json:"protocolConfigs"` } // NewChainConfig creates a new ChainConfig instance. -func NewChainConfig(chainID *big.Int, onTakeBlock *big.Int) *ChainConfig { - cfg := &ChainConfig{chainID, onTakeBlock} +func NewChainConfig(protocolConfigs *bindings.TaikoDataConfig) *ChainConfig { + cfg := &ChainConfig{protocolConfigs} log.Info("") log.Info(strings.Repeat("-", 153)) @@ -31,10 +33,10 @@ func NewChainConfig(chainID *big.Int, onTakeBlock *big.Int) *ChainConfig { } // NetworkNames are user friendly names to use in the chain spec banner. -var NetworkNames = map[string]string{ - params.TaikoMainnetNetworkID.String(): "Taiko Mainnet", - params.HeklaNetworkID.String(): "Taiko Hekla Testnet", - params.TaikoInternalL2ANetworkID.String(): "Taiko Internal Devnet", +var NetworkNames = map[uint64]string{ + params.TaikoMainnetNetworkID.Uint64(): "Taiko Mainnet", + params.HeklaNetworkID.Uint64(): "Taiko Hekla Testnet", + params.TaikoInternalL2ANetworkID.Uint64(): "Taiko Internal Devnet", } // Description returns a human-readable description of ChainConfig. @@ -42,15 +44,15 @@ func (c *ChainConfig) Description() string { var banner string // Create some basic network config output - network := NetworkNames[c.ChainID.String()] + network := NetworkNames[c.ProtocolConfigs.ChainId] if network == "" { network = "unknown" } - banner += fmt.Sprintf("Chain ID: %v (%s)\n", c.ChainID, network) + banner += fmt.Sprintf("Chain ID: %v (%s)\n", c.ProtocolConfigs.ChainId, network) // Create a list of forks with a short description of them. banner += "Hard forks (block based):\n" - banner += fmt.Sprintf(" - Ontake: #%-8v\n", c.OnTakeBlock) + banner += fmt.Sprintf(" - Ontake: #%-8v\n", c.ProtocolConfigs.OntakeForkHeight) banner += "\n" return banner @@ -58,7 +60,7 @@ func (c *ChainConfig) Description() string { // IsOntake returns whether num is either equal to the ontake block or greater. func (c *ChainConfig) IsOntake(num *big.Int) bool { - return isBlockForked(c.OnTakeBlock, num) + return isBlockForked(new(big.Int).SetUint64(c.ProtocolConfigs.OntakeForkHeight), num) } // isBlockForked returns whether a fork scheduled at block s is active at the diff --git a/packages/taiko-client/pkg/rpc/methods.go b/packages/taiko-client/pkg/rpc/methods.go index 37b0314ee3f..b8ba19323ac 100644 --- a/packages/taiko-client/pkg/rpc/methods.go +++ b/packages/taiko-client/pkg/rpc/methods.go @@ -7,6 +7,8 @@ import ( "math/big" "time" + "github.com/taikoxyz/taiko-mono/packages/taiko-client/pkg/config" + "github.com/cenkalti/backoff/v4" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -275,6 +277,7 @@ func (c *Client) GetPoolContent( locals []common.Address, maxTransactionsLists uint64, minTip uint64, + chainConfig *config.ChainConfig, ) ([]*miner.PreBuiltTxList, error) { ctxWithTimeout, cancel := CtxWithTimeoutOrDefault(ctx, defaultTimeout) defer cancel() @@ -289,11 +292,64 @@ func (c *Client) GetPoolContent( return nil, err } - baseFeeInfo, err := c.TaikoL2.GetBasefee( - &bind.CallOpts{Context: ctx}, - l1Head.Number.Uint64(), - uint32(l2Head.GasUsed), // #nosec G115 - ) + var baseFeeInfo struct { + Basefee *big.Int + ParentGasExcess uint64 + } + if chainConfig.IsOntake(l2Head.Number) { + newGasTarget := uint64(chainConfig.ProtocolConfigs.BaseFeeConfig.GasIssuancePerSecond) * + uint64(chainConfig.ProtocolConfigs.BaseFeeConfig.AdjustmentQuotient) + parentGasTarget, err := c.TaikoL2.ParentGasTarget(&bind.CallOpts{ + BlockNumber: l2Head.Number, Context: ctx, + }) + if err != nil { + return nil, fmt.Errorf("failed to fetch parent gas target: %w", err) + } + + var parentGasExcess uint64 + if newGasTarget != parentGasTarget && parentGasTarget != 0 { + oldParentGasExcess, err := c.TaikoL2.ParentGasExcess(&bind.CallOpts{ + BlockNumber: l2Head.Number, Context: ctx, + }) + if err != nil { + return nil, fmt.Errorf("failed to fetch old parent gas excess: %w", err) + } + if parentGasExcess, err = c.TaikoL2.AdjustExcess( + &bind.CallOpts{BlockNumber: l2Head.Number, Context: ctx}, + oldParentGasExcess, + parentGasTarget, + newGasTarget, + ); err != nil { + return nil, fmt.Errorf("failed to adjust parent gas excess: %w", err) + } + } else { + if parentGasExcess, err = c.TaikoL2.ParentGasExcess(&bind.CallOpts{ + BlockNumber: l2Head.Number, Context: ctx, + }); err != nil { + return nil, fmt.Errorf("failed to fetch parent gas excess: %w", err) + } + } + baseFeeInfo, err = c.TaikoL2.CalculateBaseFee( + &bind.CallOpts{Context: ctx}, + chainConfig.ProtocolConfigs.BaseFeeConfig, + uint64(time.Now().Unix())-l2Head.Time, + parentGasExcess, + uint32(l2Head.GasUsed), // #nosec G115 + ) + if err != nil { + return nil, err + } + } else { + baseFeeInfo, err = c.TaikoL2.GetBasefee( + &bind.CallOpts{Context: ctx}, + l1Head.Number.Uint64(), + uint32(l2Head.GasUsed), // #nosec G115 + ) + if err != nil { + return nil, err + } + } + if err != nil { return nil, err } diff --git a/packages/taiko-client/proposer/proposer.go b/packages/taiko-client/proposer/proposer.go index 43ca187040b..502807ccc82 100644 --- a/packages/taiko-client/proposer/proposer.go +++ b/packages/taiko-client/proposer/proposer.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "math/big" "math/rand" "sync" "time" @@ -48,6 +47,8 @@ type Proposer struct { // Protocol configurations protocolConfigs *bindings.TaikoDataConfig + chainConfig *config.ChainConfig + lastProposedAt time.Time totalEpochs uint64 @@ -122,7 +123,8 @@ func (p *Proposer) InitFromConfig( } } - chainConfig := config.NewChainConfig(p.rpc.L2.ChainID, new(big.Int).SetUint64(p.protocolConfigs.OntakeForkHeight)) + chainConfig := config.NewChainConfig(p.protocolConfigs) + p.chainConfig = chainConfig if cfg.BlobAllowed { p.txBuilder = builder.NewBlobTransactionBuilder( @@ -208,6 +210,7 @@ func (p *Proposer) fetchPoolContent(filterPoolContent bool) ([]types.Transaction p.LocalAddresses, p.MaxProposedTxListsPerEpoch, minTip, + p.chainConfig, ) if err != nil { return nil, fmt.Errorf("failed to fetch transaction pool content: %w", err) diff --git a/packages/taiko-client/proposer/proposer_test.go b/packages/taiko-client/proposer/proposer_test.go index 5694a17d057..a013f475c61 100644 --- a/packages/taiko-client/proposer/proposer_test.go +++ b/packages/taiko-client/proposer/proposer_test.go @@ -2,7 +2,6 @@ package proposer import ( "context" - "math/big" "os" "testing" "time" @@ -132,7 +131,7 @@ func (s *ProposerTestSuite) TestProposeTxLists() { cfg.L2SuggestedFeeRecipient, cfg.ProposeBlockTxGasLimit, cfg.ExtraData, - config.NewChainConfig(s.RPCClient.L2.ChainID, new(big.Int).SetUint64(s.p.protocolConfigs.OntakeForkHeight)), + config.NewChainConfig(s.p.protocolConfigs), ) emptyTxListBytes, err := rlp.EncodeToBytes(types.Transactions{}) @@ -193,6 +192,7 @@ func (s *ProposerTestSuite) TestProposeOpNoEmptyBlock() { p.LocalAddresses, p.MaxProposedTxListsPerEpoch, 0, + p.chainConfig, ) time.Sleep(time.Second) } diff --git a/packages/taiko-client/proposer/transaction_builder/blob.go b/packages/taiko-client/proposer/transaction_builder/blob.go index 1ca91aa4604..56d8275272b 100644 --- a/packages/taiko-client/proposer/transaction_builder/blob.go +++ b/packages/taiko-client/proposer/transaction_builder/blob.go @@ -71,7 +71,11 @@ func (b *BlobTransactionBuilder) Build( err error ) if includeParentMetaHash { - if parentMetaHash, err = getParentMetaHash(ctx, b.rpc, b.chainConfig.OnTakeBlock); err != nil { + if parentMetaHash, err = getParentMetaHash( + ctx, + b.rpc, + new(big.Int).SetUint64(b.chainConfig.ProtocolConfigs.OntakeForkHeight), + ); err != nil { return nil, err } } diff --git a/packages/taiko-client/proposer/transaction_builder/calldata.go b/packages/taiko-client/proposer/transaction_builder/calldata.go index 1ed91290154..fa22fb675f2 100644 --- a/packages/taiko-client/proposer/transaction_builder/calldata.go +++ b/packages/taiko-client/proposer/transaction_builder/calldata.go @@ -63,7 +63,11 @@ func (b *CalldataTransactionBuilder) Build( err error ) if includeParentMetaHash { - if parentMetaHash, err = getParentMetaHash(ctx, b.rpc, b.chainConfig.OnTakeBlock); err != nil { + if parentMetaHash, err = getParentMetaHash( + ctx, + b.rpc, + new(big.Int).SetUint64(b.chainConfig.ProtocolConfigs.OntakeForkHeight), + ); err != nil { return nil, err } } diff --git a/packages/taiko-client/proposer/transaction_builder/common_test.go b/packages/taiko-client/proposer/transaction_builder/common_test.go index 6049d3e0244..a65e0a7c40d 100644 --- a/packages/taiko-client/proposer/transaction_builder/common_test.go +++ b/packages/taiko-client/proposer/transaction_builder/common_test.go @@ -28,7 +28,7 @@ func (s *TransactionBuilderTestSuite) SetupTest() { s.Nil(err) protocolConfig := encoding.GetProtocolConfig(s.RPCClient.L2.ChainID.Uint64()) - chainConfig := config.NewChainConfig(s.RPCClient.L2.ChainID, new(big.Int).SetUint64(protocolConfig.OntakeForkHeight)) + chainConfig := config.NewChainConfig(protocolConfig) s.calldataTxBuilder = NewCalldataTransactionBuilder( s.RPCClient, @@ -53,7 +53,11 @@ func (s *TransactionBuilderTestSuite) SetupTest() { } func (s *TransactionBuilderTestSuite) TestGetParentMetaHash() { - metahash, err := getParentMetaHash(context.Background(), s.RPCClient, s.calldataTxBuilder.chainConfig.OnTakeBlock) + metahash, err := getParentMetaHash( + context.Background(), + s.RPCClient, + new(big.Int).SetUint64(s.calldataTxBuilder.chainConfig.ProtocolConfigs.OntakeForkHeight), + ) s.Nil(err) s.NotEmpty(metahash) }