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 := ðtypes.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 }