github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/txs/base/base.go (about)

     1  package base
     2  
     3  import (
     4  	"math/big"
     5  
     6  	ethtypes "github.com/ethereum/go-ethereum/core/types"
     7  
     8  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     9  	authexported "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/exported"
    10  	bam "github.com/fibonacci-chain/fbc/libs/system/trace"
    11  	tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/types"
    12  	"github.com/fibonacci-chain/fbc/x/evm/keeper"
    13  	"github.com/fibonacci-chain/fbc/x/evm/types"
    14  )
    15  
    16  // Keeper alias of keeper.Keeper, to solve import circle. also evm.Keeper is alias keeper.Keeper
    17  type Keeper = keeper.Keeper
    18  
    19  // Config tx's needed ctx and keeper
    20  type Config struct {
    21  	Ctx    sdk.Context
    22  	Keeper *Keeper
    23  }
    24  
    25  // Result evm execute result
    26  type Result struct {
    27  	ExecResult     *types.ExecutionResult
    28  	ResultData     *types.ResultData
    29  	InnerTxs       interface{}
    30  	Erc20Contracts interface{}
    31  }
    32  
    33  // Tx evm tx
    34  type Tx struct {
    35  	Ctx    sdk.Context
    36  	Keeper *Keeper
    37  
    38  	StateTransition types.StateTransition
    39  	reuseCsdb       bool
    40  }
    41  
    42  // Prepare convert msg to state transition
    43  func (tx *Tx) Prepare(msg *types.MsgEthereumTx) (err error) {
    44  	tx.AnalyzeStart(bam.Txhash)
    45  	defer tx.AnalyzeStop(bam.Txhash)
    46  
    47  	tx.reuseCsdb, err = msg2st(&tx.Ctx, tx.Keeper, msg, &tx.StateTransition)
    48  	return
    49  }
    50  
    51  // GetChainConfig get chain config, the chain config may cached
    52  func (tx *Tx) GetChainConfig() (types.ChainConfig, bool) {
    53  	return tx.Keeper.GetChainConfig(tx.Ctx)
    54  }
    55  
    56  // Transition execute evm tx
    57  func (tx *Tx) Transition(config types.ChainConfig) (result Result, err error) {
    58  	result.ExecResult, result.ResultData, err, result.InnerTxs, result.Erc20Contracts = tx.StateTransition.TransitionDb(tx.Ctx, config)
    59  
    60  	if err != nil {
    61  		return
    62  	}
    63  
    64  	// call evm hooks
    65  	if tmtypes.HigherThanVenus1(tx.Ctx.BlockHeight()) && !tx.Ctx.IsCheckTx() {
    66  		receipt := &ethtypes.Receipt{
    67  			Status:           ethtypes.ReceiptStatusSuccessful,
    68  			Bloom:            result.ResultData.Bloom,
    69  			Logs:             result.ResultData.Logs,
    70  			TxHash:           result.ResultData.TxHash,
    71  			ContractAddress:  result.ResultData.ContractAddress,
    72  			GasUsed:          result.ExecResult.GasInfo.GasConsumed,
    73  			BlockNumber:      big.NewInt(tx.Ctx.BlockHeight()),
    74  			TransactionIndex: uint(tx.Keeper.TxCount),
    75  		}
    76  		err = tx.Keeper.CallEvmHooks(tx.Ctx, &tx.StateTransition, receipt)
    77  		if err != nil {
    78  			tx.Keeper.Logger().Error("tx call evm hooks failed", "error", err)
    79  		}
    80  	}
    81  
    82  	return
    83  }
    84  
    85  // DecorateResult TraceTxLog situation Decorate the result
    86  // it was replaced to trace logs when trace tx even if err != nil
    87  func (tx *Tx) DecorateResult(inResult *Result, inErr error) (result *sdk.Result, err error) {
    88  	if inErr != nil {
    89  		return nil, inErr
    90  	}
    91  	return inResult.ExecResult.Result, inErr
    92  }
    93  
    94  func (tx *Tx) EmitEvent(msg *types.MsgEthereumTx, result *Result) {
    95  	tx.Ctx.EventManager().EmitEvents(sdk.Events{
    96  		sdk.NewEvent(
    97  			types.EventTypeEthereumTx,
    98  			sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Data.Amount.String()),
    99  		),
   100  		sdk.NewEvent(
   101  			sdk.EventTypeMessage,
   102  			sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
   103  			sdk.NewAttribute(sdk.AttributeKeySender, types.EthAddressStringer(tx.StateTransition.Sender).String()),
   104  		),
   105  	})
   106  
   107  	if msg.Data.Recipient != nil {
   108  		tx.Ctx.EventManager().EmitEvent(
   109  			sdk.NewEvent(
   110  				types.EventTypeEthereumTx,
   111  				sdk.NewAttribute(types.AttributeKeyRecipient, types.EthAddressStringer(*msg.Data.Recipient).String()),
   112  			),
   113  		)
   114  	}
   115  
   116  	// set the events to the result
   117  	result.ExecResult.Result.Events = tx.Ctx.EventManager().Events()
   118  }
   119  
   120  func NewTx(config Config) *Tx {
   121  	return &Tx{
   122  		Ctx:    config.Ctx,
   123  		Keeper: config.Keeper,
   124  	}
   125  }
   126  
   127  func (tx *Tx) AnalyzeStart(tag string) {
   128  	bam.StartTxLog(tag)
   129  }
   130  
   131  func (tx *Tx) AnalyzeStop(tag string) {
   132  	bam.StopTxLog(tag)
   133  }
   134  
   135  // SaveTx check Tx do not transition state db
   136  func (tx *Tx) SaveTx(msg *types.MsgEthereumTx) {}
   137  
   138  // GetSenderAccount check Tx do not need this
   139  func (tx *Tx) GetSenderAccount() authexported.Account { return nil }
   140  
   141  // Commit check Tx do not need
   142  func (tx *Tx) Commit(msg *types.MsgEthereumTx, result *Result) {}
   143  
   144  // FinalizeWatcher check Tx do not need this
   145  func (tx *Tx) FinalizeWatcher(msg *types.MsgEthereumTx, err error, panic bool) {}
   146  
   147  func (tx *Tx) Dispose() {
   148  	if tx != nil && tx.reuseCsdb {
   149  		tx.reuseCsdb = false
   150  		if tx.StateTransition.Csdb != nil {
   151  			putCommitStateDB(tx.StateTransition.Csdb)
   152  			tx.StateTransition.Csdb = nil
   153  		}
   154  	}
   155  }