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