Skip to content

Commit

Permalink
feat(taiko-client): introduce CalculateBaseFee() method (#17989)
Browse files Browse the repository at this point in the history
Co-authored-by: Gavin Yu <gavin@taiko.xyz>
  • Loading branch information
2 people authored and mask-pp committed Aug 28, 2024
1 parent fce824f commit ab4d2ce
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 108 deletions.
85 changes: 18 additions & 67 deletions packages/taiko-client/driver/chain_syncer/blob/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,10 @@ func (s *Syncer) insertNewHead(

// Insert a TaikoL2.anchor / TaikoL2.anchorV2 transaction at transactions list head
var (
txList []*types.Transaction
anchorTx *types.Transaction
baseFeeInfo struct {
Basefee *big.Int
ParentGasExcess uint64
}
err error
txList []*types.Transaction
anchorTx *types.Transaction
baseFee *big.Int
err error
)
if len(txListBytes) != 0 {
if err := rlp.DecodeBytes(txListBytes, &txList); err != nil {
Expand All @@ -342,76 +339,30 @@ func (s *Syncer) insertNewHead(
}
}

if !meta.IsOntakeBlock() {
// Get L2 baseFee
baseFeeInfo, err = s.rpc.TaikoL2.GetBasefee(
&bind.CallOpts{BlockNumber: parent.Number, Context: ctx},
meta.GetRawBlockHeight().Uint64()-1,
// #nosec G115
uint32(parent.GasUsed),
)
if err != nil {
return nil, fmt.Errorf("failed to get L2 baseFee: %w", encoding.TryParsingCustomError(err))
}
if baseFee, err = s.rpc.CalculateBaseFee(
ctx,
parent,
new(big.Int).SetUint64(meta.GetAnchorBlockID()),
meta.IsOntakeBlock(),
meta.GetBaseFeeConfig(),
); err != nil {
return nil, err
}

if !meta.IsOntakeBlock() {
// Assemble a TaikoL2.anchor transaction
anchorTx, err = s.anchorConstructor.AssembleAnchorTx(
ctx,
new(big.Int).SetUint64(meta.GetAnchorBlockID()),
meta.GetAnchorBlockHash(),
new(big.Int).Add(parent.Number, common.Big1),
baseFeeInfo.Basefee,
baseFee,
parent.GasUsed,
)
if err != nil {
return nil, fmt.Errorf("failed to create TaikoL2.anchor transaction: %w", err)
}
} else {
newGasTarget := uint64(meta.GetBaseFeeConfig().GasIssuancePerSecond) *
uint64(meta.GetBaseFeeConfig().AdjustmentQuotient)
parentGasTarget, err := s.rpc.TaikoL2.ParentGasTarget(&bind.CallOpts{
BlockNumber: parent.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 := s.rpc.TaikoL2.ParentGasExcess(&bind.CallOpts{
BlockNumber: parent.Number, Context: ctx,
})
if err != nil {
return nil, fmt.Errorf("failed to fetch old parent gas excess: %w", err)
}
if parentGasExcess, err = s.rpc.TaikoL2.AdjustExcess(
&bind.CallOpts{BlockNumber: parent.Number, Context: ctx},
oldParentGasExcess,
parentGasTarget,
newGasTarget,
); err != nil {
return nil, fmt.Errorf("failed to adjust parent gas excess: %w", err)
}
} else {
if parentGasExcess, err = s.rpc.TaikoL2.ParentGasExcess(&bind.CallOpts{
BlockNumber: parent.Number, Context: ctx,
}); err != nil {
return nil, fmt.Errorf("failed to fetch parent gas excess: %w", err)
}
}
// Get L2 baseFee
baseFeeInfo, err = s.rpc.TaikoL2.CalculateBaseFee(
&bind.CallOpts{BlockNumber: parent.Number, Context: ctx},
*meta.GetBaseFeeConfig(),
meta.GetTimestamp()-parent.Time,
parentGasExcess,
// #nosec G115
uint32(parent.GasUsed),
)
if err != nil {
return nil, fmt.Errorf("failed to get L2 baseFee: %w", encoding.TryParsingCustomError(err))
}

// Assemble a TaikoL2.anchorV2 transaction
anchorBlockHeader, err := s.rpc.L1.HeaderByHash(ctx, meta.GetAnchorBlockHash())
if err != nil {
Expand All @@ -424,7 +375,7 @@ func (s *Syncer) insertNewHead(
parent.GasUsed,
meta.GetBaseFeeConfig(),
new(big.Int).Add(parent.Number, common.Big1),
baseFeeInfo.Basefee,
baseFee,
)
if err != nil {
return nil, fmt.Errorf("failed to create TaikoL2.anchorV2 transaction: %w", err)
Expand All @@ -434,7 +385,7 @@ func (s *Syncer) insertNewHead(
log.Info(
"L2 baseFee",
"blockID", meta.GetBlockID(),
"baseFee", utils.WeiToGWei(baseFeeInfo.Basefee),
"baseFee", utils.WeiToGWei(baseFee),
"syncedL1Height", meta.GetRawBlockHeight(),
"parentGasUsed", parent.GasUsed,
)
Expand All @@ -452,7 +403,7 @@ func (s *Syncer) insertNewHead(
parent.Hash(),
l1Origin,
txListBytes,
baseFeeInfo.Basefee,
baseFee,
make(types.Withdrawals, 0),
)
if err != nil {
Expand Down
115 changes: 74 additions & 41 deletions packages/taiko-client/pkg/rpc/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,50 +267,38 @@ func (c *Client) WaitL2Header(ctx context.Context, blockID *big.Int) (*types.Hea
return nil, fmt.Errorf("failed to fetch block header from L2 execution engine, blockID: %d", blockID)
}

// GetPoolContent fetches the transactions list from L2 execution engine's transactions pool with given
// upper limit.
func (c *Client) GetPoolContent(
// CalculateBaseFee calculates the base fee from the L2 protocol.
func (c *Client) CalculateBaseFee(
ctx context.Context,
beneficiary common.Address,
blockMaxGasLimit uint32,
maxBytesPerTxList uint64,
locals []common.Address,
maxTransactionsLists uint64,
minTip uint64,
chainConfig *config.ChainConfig,
) ([]*miner.PreBuiltTxList, error) {
ctxWithTimeout, cancel := CtxWithTimeoutOrDefault(ctx, defaultTimeout)
defer cancel()

l1Head, err := c.L1.HeaderByNumber(ctx, nil)
if err != nil {
return nil, err
}

l2Head, err := c.L2.HeaderByNumber(ctx, nil)
if err != nil {
return nil, err
}
l2Head *types.Header,
anchorBlockID *big.Int,
isOntake bool,
baseFeeConfig *bindings.TaikoDataBaseFeeConfig,
) (*big.Int, error) {
var (
baseFeeInfo struct {
Basefee *big.Int
ParentGasExcess uint64
}
err error
)

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 isOntake {
var (
newGasTarget = uint64(baseFeeConfig.GasIssuancePerSecond) * uint64(baseFeeConfig.AdjustmentQuotient)
parentGasExcess uint64
)
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,
})
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)
}
Expand All @@ -331,7 +319,7 @@ func (c *Client) GetPoolContent(
}
baseFeeInfo, err = c.TaikoL2.CalculateBaseFee(
&bind.CallOpts{Context: ctx},
chainConfig.ProtocolConfigs.BaseFeeConfig,
*baseFeeConfig,
uint64(time.Now().Unix())-l2Head.Time,
parentGasExcess,
uint32(l2Head.GasUsed), // #nosec G115
Expand All @@ -342,7 +330,7 @@ func (c *Client) GetPoolContent(
} else {
baseFeeInfo, err = c.TaikoL2.GetBasefee(
&bind.CallOpts{Context: ctx},
l1Head.Number.Uint64(),
anchorBlockID.Uint64(),
uint32(l2Head.GasUsed), // #nosec G115
)
if err != nil {
Expand All @@ -354,7 +342,52 @@ func (c *Client) GetPoolContent(
return nil, err
}

log.Info("Current base fee", "fee", utils.WeiToGWei(baseFeeInfo.Basefee))
log.Info(
"Base fee information",
"fee", utils.WeiToGWei(baseFeeInfo.Basefee),
"l2Head", l2Head.Number,
"anchorBlockID", anchorBlockID,
"isOntake", isOntake,
)

return baseFeeInfo.Basefee, nil
}

// GetPoolContent fetches the transactions list from L2 execution engine's transactions pool with given
// upper limit.
func (c *Client) GetPoolContent(
ctx context.Context,
beneficiary common.Address,
blockMaxGasLimit uint32,
maxBytesPerTxList uint64,
locals []common.Address,
maxTransactionsLists uint64,
minTip uint64,
chainConfig *config.ChainConfig,
) ([]*miner.PreBuiltTxList, error) {
ctxWithTimeout, cancel := CtxWithTimeoutOrDefault(ctx, defaultTimeout)
defer cancel()

l1Head, err := c.L1.HeaderByNumber(ctx, nil)
if err != nil {
return nil, err
}

l2Head, err := c.L2.HeaderByNumber(ctx, nil)
if err != nil {
return nil, err
}

baseFee, err := c.CalculateBaseFee(
ctx,
l2Head,
l1Head.Number,
chainConfig.IsOntake(l2Head.Number),
&chainConfig.ProtocolConfigs.BaseFeeConfig,
)
if err != nil {
return nil, err
}

var localsArg []string
for _, local := range locals {
Expand All @@ -364,7 +397,7 @@ func (c *Client) GetPoolContent(
return c.L2Engine.TxPoolContentWithMinTip(
ctxWithTimeout,
beneficiary,
baseFeeInfo.Basefee,
baseFee,
uint64(blockMaxGasLimit),
maxBytesPerTxList,
localsArg,
Expand Down

0 comments on commit ab4d2ce

Please sign in to comment.