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

View file

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

View file

@ -138,6 +138,10 @@ type StateDB struct {
// Testing hooks
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.

View file

@ -169,6 +169,8 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
if err != nil {
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
blockContext := NewEVMBlockContext(header, bc, author)
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.
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.
@ -467,12 +470,16 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
fee := new(uint256.Int).SetUint64(st.gasUsed())
fee.Mul(fee, effectiveTipU256)
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 {
st.state.AddBalance(
st.getTreasuryAddress(),
uint256.MustFromBig(new(big.Int).Mul(st.evm.Context.BaseFee, new(big.Int).SetUint64(st.gasUsed()))),
totalFee := new(big.Int).Mul(st.evm.Context.BaseFee, new(big.Int).SetUint64(st.gasUsed()))
feeCoinbase := new(big.Int).Div(
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 {
// CHANGE(taiko): create a L2 block by Taiko protocol.
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
// marked as required.
block, err := api.eth.Miner().SealBlockWith(

View file

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