Skip to content

Commit

Permalink
Merge pull request #47 from mantlenetworkio/release/v0.5.0
Browse files Browse the repository at this point in the history
[R4R]-feat: merge from release/v0.5.0 to develop
Core changes:
- [R4R]feat: mint eth to msg.from and transfer revertable #31
- [R4R]feat: metatx add from field into MetaTxSignData, so that to sign hash with from's addr #37
- [R4R]feat: add error message when failing to forward tx to sequencer #39
- [R4R]fix: fix tx cost #41
  • Loading branch information
Tri-stone committed Mar 1, 2024
2 parents 97be26d + 52122bd commit b2cb932
Show file tree
Hide file tree
Showing 25 changed files with 437 additions and 95 deletions.
3 changes: 2 additions & 1 deletion cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
misc.ApplyDAOHardFork(statedb)
}

rules := chainConfig.Rules(new(big.Int).SetUint64(pre.Env.Number), false, pre.Env.Timestamp)
for i, tx := range txs {
msg, err := core.TransactionToMessage(tx, signer, pre.Env.BaseFee)
msg, err := core.TransactionToMessage(tx, signer, pre.Env.BaseFee, &rules)
if err != nil {
log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", err)
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
Expand Down
2 changes: 2 additions & 0 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
mantleUpgradeChainConfig := GetUpgradeConfigForMantle(config.ChainID)
if mantleUpgradeChainConfig != nil {
config.BaseFeeTime = mantleUpgradeChainConfig.BaseFeeTime
config.BVMETHMintUpgradeTime = mantleUpgradeChainConfig.BVMETHMintUpgradeTime
config.MetaTxUpgradeTime = mantleUpgradeChainConfig.MetaTxUpgradeTime
}

if overrides != nil && overrides.OverrideShanghai != nil {
Expand Down
29 changes: 20 additions & 9 deletions core/mantle_upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,37 @@ import (

var (
MantleMainnetUpgradeConfig = MantleUpgradeChainConfig{
ChainID: params.MantleMainnetChainId,
BaseFeeTime: u64Ptr(0),
ChainID: params.MantleMainnetChainId,
BaseFeeTime: u64Ptr(0),
BVMETHMintUpgradeTime: u64Ptr(0),
MetaTxUpgradeTime: u64Ptr(0),
}

MantleSepoliaUpgradeConfig = MantleUpgradeChainConfig{
ChainID: params.MantleSepoliaChainId,
BaseFeeTime: u64Ptr(1_704_891_600),
ChainID: params.MantleSepoliaChainId,
BaseFeeTime: u64Ptr(1_704_891_600),
BVMETHMintUpgradeTime: nil, //TODO set upgrade timestamp
MetaTxUpgradeTime: nil, //TODO set upgrade timestamp
}
MantleLocalUpgradeConfig = MantleUpgradeChainConfig{
ChainID: params.MantleLocalChainId,
BaseFeeTime: u64Ptr(0),
ChainID: params.MantleLocalChainId,
BaseFeeTime: u64Ptr(0),
BVMETHMintUpgradeTime: u64Ptr(0),
MetaTxUpgradeTime: u64Ptr(0),
}
MantleDefaultUpgradeConfig = MantleUpgradeChainConfig{
BaseFeeTime: u64Ptr(0),
BaseFeeTime: u64Ptr(0),
BVMETHMintUpgradeTime: u64Ptr(0),
MetaTxUpgradeTime: u64Ptr(0),
}
)

type MantleUpgradeChainConfig struct {
ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection
BaseFeeTime *uint64 `json:"BaseFeeTime"` // Mantle BaseFee switch time (nil = no fork, 0 = already on mantle baseFee)
ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection

BaseFeeTime *uint64 `json:"BaseFeeTime"` // Mantle BaseFee switch time (nil = no fork, 0 = already on mantle baseFee)
BVMETHMintUpgradeTime *uint64 `json:"BVMETHMintUpgradeTime"` // BVM_ETH mint upgrade switch time (nil = no fork, 0 = already on)
MetaTxUpgradeTime *uint64 `json:"metaTxUpgradeTime"` // MetaTxUpgradeBlock identifies the current block height is using metaTx with MetaTxSignDataV2
}

func GetUpgradeConfigForMantle(chainID *big.Int) *MantleUpgradeChainConfig {
Expand Down
4 changes: 3 additions & 1 deletion core/state_prefetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,15 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
)
// Iterate over and process the individual transactions
byzantium := p.config.IsByzantium(block.Number())
rules := evm.ChainConfig().Rules(block.Number(), false, header.Time)

for i, tx := range block.Transactions() {
// If block precaching was interrupted, abort
if interrupt != nil && atomic.LoadUint32(interrupt) == 1 {
return
}
// Convert the transaction into an executable message and pre-cache its sender
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
msg, err := TransactionToMessage(tx, signer, header.BaseFee, &rules)
if err != nil {
return // Also invalid block, bail out
}
Expand Down
7 changes: 5 additions & 2 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
}
blockContext := NewEVMBlockContext(header, p.bc, nil, p.config, statedb)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
rules := vmenv.ChainConfig().Rules(header.Number, false, header.Time)

// Iterate over and process the individual transactions
for i, tx := range block.Transactions() {
msg, err := TransactionToMessage(tx, types.MakeSigner(p.config, header.Number), header.BaseFee)
msg, err := TransactionToMessage(tx, types.MakeSigner(p.config, header.Number), header.BaseFee, &rules)
if err != nil {
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
}
Expand Down Expand Up @@ -171,7 +173,8 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta
// for the transaction, gas used and an error if the transaction failed,
// indicating the block was invalid.
func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) {
msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number), header.BaseFee)
rules := config.Rules(header.Number, false, header.Time)
msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number), header.BaseFee, &rules)
if err != nil {
return nil, err
}
Expand Down
103 changes: 90 additions & 13 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package core

import (
"errors"
"fmt"
"math"
"math/big"
Expand Down Expand Up @@ -161,6 +162,7 @@ type Message struct {
IsDepositTx bool // IsDepositTx indicates the message is force-included and can persist a mint.
Mint *big.Int // Mint is the amount to mint before EVM processing, or nil if there is no minting.
ETHValue *big.Int // ETHValue is the amount to mint BVM_ETH before EVM processing, or nil if there is no minting.
ETHTxValue *big.Int // ETHTxValue is the amount to be transferred to msg.To before EVM processing, and the transfer will be reverted if EVM failed
MetaTxParams *types.MetaTxParams // MetaTxParams contains necessary parameter to sponsor gas fee for msg.From.
RollupDataGas types.RollupGasData // RollupDataGas indicates the rollup cost of the message, 0 if not a rollup or no cost.

Expand All @@ -169,8 +171,11 @@ type Message struct {
}

// TransactionToMessage converts a transaction into a Message.
func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int) (*Message, error) {
metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx)
func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int, rules *params.Rules) (*Message, error) {
if rules == nil {
return nil, errors.New("param rules is nil pointer")
}
metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, rules.IsMetaTxV2)
if err != nil {
return nil, err
}
Expand All @@ -189,6 +194,7 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
Mint: tx.Mint(),
RollupDataGas: tx.RollupDataGas(),
ETHValue: tx.ETHValue(),
ETHTxValue: tx.ETHTxValue(),
MetaTxParams: metaTxParams,
SkipAccountChecks: false,
RunMode: CommitMode,
Expand Down Expand Up @@ -438,19 +444,18 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
if mint := st.msg.Mint; mint != nil {
st.state.AddBalance(st.msg.From, mint)
}

//Mint BVM_ETH
rules := st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil, st.evm.Context.Time)
//add eth value
if ethValue := st.msg.ETHValue; ethValue != nil && ethValue.Cmp(big.NewInt(0)) != 0 {
var ethRecipient common.Address
if st.msg.To != nil {
ethRecipient = *st.msg.To
} else {
ethRecipient = crypto.CreateAddress(st.msg.From, st.evm.StateDB.GetNonce(st.msg.From))
}
st.addBVMETHBalance(ethRecipient, ethValue)
st.addBVMETHTotalSupply(ethValue)
st.generateBVMETHMintEvent(ethRecipient, ethValue)
st.mintBVMETH(ethValue, rules)
}
snap := st.state.Snapshot()
// Will be reverted if failed
if ethTxValue := st.msg.ETHTxValue; ethTxValue != nil && ethTxValue.Cmp(big.NewInt(0)) != 0 {
st.transferBVMETH(ethTxValue, rules)
}

result, err := st.innerTransitionDb()
// Failed deposits must still be included. Unless we cannot produce the block at all due to the gas limit.
Expand Down Expand Up @@ -671,12 +676,33 @@ func (st *StateTransition) gasUsed() uint64 {
return st.initialGas - st.gasRemaining
}

func (st *StateTransition) addBVMETHBalance(ethRecipient common.Address, ethValue *big.Int) {
key := getBVMETHBalanceKey(ethRecipient)
func (st *StateTransition) mintBVMETH(ethValue *big.Int, rules params.Rules) {
if !rules.IsMantleBVMETHMintUpgrade {
var key common.Hash
var ethRecipient common.Address
if st.msg.To != nil {
ethRecipient = *st.msg.To
} else {
ethRecipient = crypto.CreateAddress(st.msg.From, st.evm.StateDB.GetNonce(st.msg.From))
}
key = getBVMETHBalanceKey(ethRecipient)
value := st.state.GetState(BVM_ETH_ADDR, key)
bal := value.Big()
bal = bal.Add(bal, ethValue)
st.state.SetState(BVM_ETH_ADDR, key, common.BigToHash(bal))

st.addBVMETHTotalSupply(ethValue)
st.generateBVMETHMintEvent(ethRecipient, ethValue)
return
}
key := getBVMETHBalanceKey(st.msg.From)
value := st.state.GetState(BVM_ETH_ADDR, key)
bal := value.Big()
bal = bal.Add(bal, ethValue)
st.state.SetState(BVM_ETH_ADDR, key, common.BigToHash(bal))

st.addBVMETHTotalSupply(ethValue)
st.generateBVMETHMintEvent(st.msg.From, ethValue)
}

func (st *StateTransition) addBVMETHTotalSupply(ethValue *big.Int) {
Expand All @@ -687,6 +713,38 @@ func (st *StateTransition) addBVMETHTotalSupply(ethValue *big.Int) {
st.state.SetState(BVM_ETH_ADDR, key, common.BigToHash(bal))
}

func (st *StateTransition) transferBVMETH(ethValue *big.Int, rules params.Rules) {
if !rules.IsMantleBVMETHMintUpgrade {
return
}
var ethRecipient common.Address
if st.msg.To != nil {
ethRecipient = *st.msg.To
} else {
ethRecipient = crypto.CreateAddress(st.msg.From, st.evm.StateDB.GetNonce(st.msg.From))
}
if ethRecipient == st.msg.From {
return
}

fromKey := getBVMETHBalanceKey(st.msg.From)
toKey := getBVMETHBalanceKey(ethRecipient)

fromBalanceValue := st.state.GetState(BVM_ETH_ADDR, fromKey)
toBalanceValue := st.state.GetState(BVM_ETH_ADDR, toKey)

fromBalance := fromBalanceValue.Big()
toBalance := toBalanceValue.Big()

fromBalance = new(big.Int).Sub(fromBalance, ethValue)
toBalance = new(big.Int).Add(toBalance, ethValue)

st.state.SetState(BVM_ETH_ADDR, fromKey, common.BigToHash(fromBalance))
st.state.SetState(BVM_ETH_ADDR, toKey, common.BigToHash(toBalance))

st.generateBVMETHTransferEvent(st.msg.From, ethRecipient, ethValue)
}

func getBVMETHBalanceKey(addr common.Address) common.Hash {
position := common.Big0
hasher := sha3.NewLegacyKeccak256()
Expand Down Expand Up @@ -717,3 +775,22 @@ func (st *StateTransition) generateBVMETHMintEvent(mintAddress common.Address, m
BlockNumber: st.evm.Context.BlockNumber.Uint64(),
})
}

func (st *StateTransition) generateBVMETHTransferEvent(from, to common.Address, amount *big.Int) {
// keccak("Transfer(address,address,uint256)") = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
methodHash := common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef")
topics := make([]common.Hash, 3)
topics[0] = methodHash
topics[1] = from.Hash()
topics[2] = to.Hash()
//data means the transfer amount in Transfer EVENT.
data := common.HexToHash(common.Bytes2Hex(amount.Bytes())).Bytes()
st.evm.StateDB.AddLog(&types.Log{
Address: BVM_ETH_ADDR,
Topics: topics,
Data: data,
// This is a non-consensus field, but assigned here because
// core/state doesn't know the current block number.
BlockNumber: st.evm.Context.BlockNumber.Uint64(),
})
}
7 changes: 5 additions & 2 deletions core/txpool/txpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,9 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
if tx.Type() == types.DepositTxType {
return core.ErrTxTypeNotSupported
}
if tx.Type() == types.BlobTxType {
return errors.New("BlobTxType of transaction is currently not supported.")
}
// Accept only legacy transactions until EIP-2718/2930 activates.
if !pool.eip2718 && tx.Type() != types.LegacyTxType {
return core.ErrTxTypeNotSupported
Expand Down Expand Up @@ -689,7 +692,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
cost = cost.Add(cost, l1Cost)
}

metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx)
metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time))
if err != nil {
return err
}
Expand Down Expand Up @@ -1480,7 +1483,7 @@ func (pool *TxPool) validateMetaTxList(list *list) ([]*types.Transaction, *big.I
var invalidMetaTxs []*types.Transaction
sponsorCostSum := big.NewInt(0)
for _, tx := range list.txs.Flatten() {
metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx)
metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time))
if err != nil {
invalidMetaTxs = append(invalidMetaTxs, tx)
continue
Expand Down
6 changes: 6 additions & 0 deletions core/types/deposit_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ type DepositTx struct {
EthValue *big.Int `rlp:"nil"`
// Normal Tx data
Data []byte
// EthTxValue means L2 BVM_ETH tx tag, nil means that there is no need to transfer BVM_ETH to msg.To.
EthTxValue *big.Int `rlp:"optional"`
}

// copy creates a deep copy of the transaction data and initializes all fields.
Expand All @@ -57,6 +59,7 @@ func (tx *DepositTx) copy() TxData {
IsSystemTransaction: tx.IsSystemTransaction,
Data: common.CopyBytes(tx.Data),
EthValue: nil,
EthTxValue: nil,
}
if tx.Mint != nil {
cpy.Mint = new(big.Int).Set(tx.Mint)
Expand All @@ -67,6 +70,9 @@ func (tx *DepositTx) copy() TxData {
if tx.EthValue != nil {
cpy.EthValue = new(big.Int).Set(tx.EthValue)
}
if tx.EthTxValue != nil {
cpy.EthTxValue = new(big.Int).Set(tx.EthTxValue)
}
return cpy
}

Expand Down
16 changes: 12 additions & 4 deletions core/types/gen_receipt_json.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b2cb932

Please sign in to comment.