feat(core): introduce BasefeeSharingPctg in BlockMetadata (#287)

* feat(core): introduce `BasefeeSharingPctg` in `BlockMetadata`

* feat: update message

* feat: check BasefeeSharingPctg
This commit is contained in:
David 2024-07-26 17:02:03 +08:00 committed by GitHub
parent b137b2ac11
commit e6487f00ed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 44 additions and 28 deletions

View file

@ -5,7 +5,6 @@ package engine
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
@ -16,13 +15,13 @@ var _ = (*blockMetadataMarshaling)(nil)
// MarshalJSON marshals as JSON. // MarshalJSON marshals as JSON.
func (b BlockMetadata) MarshalJSON() ([]byte, error) { func (b BlockMetadata) MarshalJSON() ([]byte, error) {
type BlockMetadata struct { type BlockMetadata struct {
Beneficiary common.Address `json:"beneficiary" gencodec:"required"` Beneficiary common.Address `json:"beneficiary" gencodec:"required"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"` GasLimit uint64 `json:"gasLimit" gencodec:"required"`
Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"`
MixHash common.Hash `json:"mixHash" gencodec:"required"` MixHash common.Hash `json:"mixHash" gencodec:"required"`
TxList hexutil.Bytes `json:"txList" gencodec:"required"` TxList hexutil.Bytes `json:"txList" gencodec:"required"`
HighestBlockID *big.Int `json:"highestBlockID" gencodec:"required"` ExtraData []byte `json:"extraData" gencodec:"required"`
ExtraData []byte `json:"extraData" gencodec:"required"` BasefeeSharingPctg uint8 `json:"basefeeSharingPctg"`
} }
var enc BlockMetadata var enc BlockMetadata
enc.Beneficiary = b.Beneficiary enc.Beneficiary = b.Beneficiary
@ -30,21 +29,21 @@ func (b BlockMetadata) MarshalJSON() ([]byte, error) {
enc.Timestamp = hexutil.Uint64(b.Timestamp) enc.Timestamp = hexutil.Uint64(b.Timestamp)
enc.MixHash = b.MixHash enc.MixHash = b.MixHash
enc.TxList = b.TxList enc.TxList = b.TxList
enc.HighestBlockID = b.HighestBlockID
enc.ExtraData = b.ExtraData enc.ExtraData = b.ExtraData
enc.BasefeeSharingPctg = b.BasefeeSharingPctg
return json.Marshal(&enc) return json.Marshal(&enc)
} }
// UnmarshalJSON unmarshals from JSON. // UnmarshalJSON unmarshals from JSON.
func (b *BlockMetadata) UnmarshalJSON(input []byte) error { func (b *BlockMetadata) UnmarshalJSON(input []byte) error {
type BlockMetadata struct { type BlockMetadata struct {
Beneficiary *common.Address `json:"beneficiary" gencodec:"required"` Beneficiary *common.Address `json:"beneficiary" gencodec:"required"`
GasLimit *uint64 `json:"gasLimit" gencodec:"required"` GasLimit *uint64 `json:"gasLimit" gencodec:"required"`
Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
MixHash *common.Hash `json:"mixHash" gencodec:"required"` MixHash *common.Hash `json:"mixHash" gencodec:"required"`
TxList *hexutil.Bytes `json:"txList" gencodec:"required"` TxList *hexutil.Bytes `json:"txList" gencodec:"required"`
HighestBlockID *big.Int `json:"highestBlockID" gencodec:"required"` ExtraData []byte `json:"extraData" gencodec:"required"`
ExtraData []byte `json:"extraData" gencodec:"required"` BasefeeSharingPctg *uint8 `json:"basefeeSharingPctg"`
} }
var dec BlockMetadata var dec BlockMetadata
if err := json.Unmarshal(input, &dec); err != nil { if err := json.Unmarshal(input, &dec); err != nil {
@ -70,13 +69,12 @@ func (b *BlockMetadata) UnmarshalJSON(input []byte) error {
return errors.New("missing required field 'txList' for BlockMetadata") return errors.New("missing required field 'txList' for BlockMetadata")
} }
b.TxList = *dec.TxList b.TxList = *dec.TxList
if dec.HighestBlockID == nil {
return errors.New("missing required field 'highestBlockID' for BlockMetadata")
}
b.HighestBlockID = dec.HighestBlockID
if dec.ExtraData == nil { if dec.ExtraData == nil {
return errors.New("missing required field 'extraData' for BlockMetadata") return errors.New("missing required field 'extraData' for BlockMetadata")
} }
b.ExtraData = dec.ExtraData b.ExtraData = dec.ExtraData
if dec.BasefeeSharingPctg != nil {
b.BasefeeSharingPctg = *dec.BasefeeSharingPctg
}
return nil return nil
} }

View file

@ -64,16 +64,15 @@ type payloadAttributesMarshaling struct {
// CHANGE(taiko): BlockMetadata represents a `BlockMetadata` struct defined in // CHANGE(taiko): BlockMetadata represents a `BlockMetadata` struct defined in
// protocol. // protocol.
type BlockMetadata struct { type BlockMetadata struct {
// Fields defined in `LibData.blockMetadata`.
Beneficiary common.Address `json:"beneficiary" gencodec:"required"` Beneficiary common.Address `json:"beneficiary" gencodec:"required"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"` GasLimit uint64 `json:"gasLimit" gencodec:"required"`
Timestamp uint64 `json:"timestamp" gencodec:"required"` Timestamp uint64 `json:"timestamp" gencodec:"required"`
MixHash common.Hash `json:"mixHash" gencodec:"required"` MixHash common.Hash `json:"mixHash" gencodec:"required"`
// Extra fields required in taiko-geth. // Extra fields required in taiko-geth.
TxList []byte `json:"txList" gencodec:"required"` TxList []byte `json:"txList" gencodec:"required"`
HighestBlockID *big.Int `json:"highestBlockID" gencodec:"required"` ExtraData []byte `json:"extraData" gencodec:"required"`
ExtraData []byte `json:"extraData" gencodec:"required"` BasefeeSharingPctg uint8 `json:"basefeeSharingPctg"`
} }
// CHANGE(taiko): JSON type overrides for BlockMetadata. // CHANGE(taiko): JSON type overrides for BlockMetadata.

View file

@ -138,6 +138,10 @@ type StateDB struct {
// Testing hooks // Testing hooks
onCommit func(states *triestate.Set) // Hook invoked when commit is performed onCommit func(states *triestate.Set) // Hook invoked when commit is performed
// CHANGE(taiko): basefeeSharingPctg of the basefee will be sent to the block.coinbase,
// the remaining will be sent to the treasury address.
BasefeeSharingPctg uint8
} }
// New creates a new state from a given trie. // New creates a new state from a given trie.

View file

@ -169,6 +169,8 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
if err != nil { if err != nil {
return nil, err return nil, err
} }
// CHANGE(taiko): set `BasefeeSharingPctg` for the current message.
msg.BasefeeSharingPctg = statedb.BasefeeSharingPctg
// Create a new context to be used in the EVM environment // Create a new context to be used in the EVM environment
blockContext := NewEVMBlockContext(header, bc, author) blockContext := NewEVMBlockContext(header, bc, author)
txContext := NewEVMTxContext(msg) txContext := NewEVMTxContext(msg)

View file

@ -149,6 +149,9 @@ type Message struct {
// CHANGE(taiko): whether the current transaction is the first TaikoL2.anchor transaction in a block. // CHANGE(taiko): whether the current transaction is the first TaikoL2.anchor transaction in a block.
IsAnchor bool IsAnchor bool
// CHANGE(taiko): basefeeSharingPctg of the basefee will be sent to the block.coinbase,
// the remaining will be sent to the treasury address.
BasefeeSharingPctg uint8
} }
// TransactionToMessage converts a transaction into a Message. // TransactionToMessage converts a transaction into a Message.
@ -467,12 +470,16 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
fee := new(uint256.Int).SetUint64(st.gasUsed()) fee := new(uint256.Int).SetUint64(st.gasUsed())
fee.Mul(fee, effectiveTipU256) fee.Mul(fee, effectiveTipU256)
st.state.AddBalance(st.evm.Context.Coinbase, fee) st.state.AddBalance(st.evm.Context.Coinbase, fee)
// CHANGE(taiko): basefee is not burnt, but sent to a treasury instead. // CHANGE(taiko): basefee is not burnt, but sent to a treasury and block.coinbase instead.
if st.evm.ChainConfig().Taiko && st.evm.Context.BaseFee != nil && !st.msg.IsAnchor { if st.evm.ChainConfig().Taiko && st.evm.Context.BaseFee != nil && !st.msg.IsAnchor {
st.state.AddBalance( totalFee := new(big.Int).Mul(st.evm.Context.BaseFee, new(big.Int).SetUint64(st.gasUsed()))
st.getTreasuryAddress(), feeCoinbase := new(big.Int).Div(
uint256.MustFromBig(new(big.Int).Mul(st.evm.Context.BaseFee, new(big.Int).SetUint64(st.gasUsed()))), new(big.Int).Mul(totalFee, new(big.Int).SetUint64(uint64(st.msg.BasefeeSharingPctg))),
new(big.Int).SetUint64(100),
) )
feeTreasury := new(big.Int).Sub(totalFee, feeCoinbase)
st.state.AddBalance(st.getTreasuryAddress(), uint256.MustFromBig(feeTreasury))
st.state.AddBalance(st.evm.Context.Coinbase, uint256.MustFromBig(feeCoinbase))
} }
} }

View file

@ -382,6 +382,11 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
if payloadAttributes != nil { if payloadAttributes != nil {
// CHANGE(taiko): create a L2 block by Taiko protocol. // CHANGE(taiko): create a L2 block by Taiko protocol.
if isTaiko { if isTaiko {
if payloadAttributes.BlockMetadata.BasefeeSharingPctg > 100 {
return valid(nil), engine.InvalidPayloadAttributes.With(
fmt.Errorf("invalid basefeeSharingPctg %d", payloadAttributes.BlockMetadata.BasefeeSharingPctg),
)
}
// No need to check payloadAttribute here, because all its fields are // No need to check payloadAttribute here, because all its fields are
// marked as required. // marked as required.
block, err := api.eth.Miner().SealBlockWith( block, err := api.eth.Miner().SealBlockWith(

View file

@ -170,6 +170,7 @@ func (w *worker) sealBlockWith(
defer env.discard() defer env.discard()
env.header.GasLimit = blkMeta.GasLimit env.header.GasLimit = blkMeta.GasLimit
env.state.BasefeeSharingPctg = blkMeta.BasefeeSharingPctg
// Commit transactions. // Commit transactions.
gasLimit := env.header.GasLimit gasLimit := env.header.GasLimit