简介
分析以太坊代码中交易费的处理逻辑。
- 代码:github.com:ethereum/go-ethereum
- 版本:1.14.6
概述
交易费采用先扣除,再返还剩余gas的方式:
- 交易执行前,先按照gasLimit,扣除用户的最大交易费。
- 交易执行过程中,统计gasRemaing以及gasUsed,此时并不扣除。
- 交易执行过程中,有些指令涉及退费,统计相关的refund,此时并不扣除。
- 交易执行后,返还用户剩余gas(gasRemaining+refund)。
- 支付矿工tip费用。
代码分析
核心逻辑位于交易执行的主流程state_transition.go文件的TransitionDb方法中。
1. 扣除最大gas费(gasLimit)
交易执行前,首先会按照用户的gasLimit,以及真实的gasPrice,扣除用户的最大费用
func (st *StateTransition) buyGas() error { //按照gasLimit计算最大费用 mgval := new(big.Int).SetUint64(st.msg.GasLimit) mgval.Mul(mgval, st.msg.GasPrice) ... st.gasRemaining = st.msg.GasLimit st.initialGas = st.msg.GasLimit //从用户账户扣除最大费用 mgvalU256, _ := uint256.FromBig(mgval) st.state.SubBalance(st.msg.From, mgvalU256, tracing.BalanceDecreaseGasBuy) return nil }
调用堆栈为:
func (st *StateTransition) buyGas()//state_transition.go func (st *StateTransition) preCheck()//state_transition.go func (st *StateTransition) TransitionDb()//state_transition.go func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool)//state_transition.go func ApplyTransactionWithEVM //state_processor.go func ApplyTransaction //state_processor.go
2. 返回gasRemaining以及Refund
在交易执行完成后,计算剩下的gasRemaining,以及退费refund,返还用户。
其中gasRemaing和refund由具体的opcode决定,会在具体指令执行过程中记录。
func (st *StateTransition) refundGas(refundQuotient uint64) uint64 { // Apply refund counter, capped to a refund quotient // 计算退费Refund refund := st.gasUsed() / refundQuotient if refund > st.state.GetRefund() { refund = st.state.GetRefund() } ... //把退费加在原本的gas剩余gasRemaining上 st.gasRemaining += refund // Return ETH for remaining gas, exchanged at the original rate. remaining := uint256.NewInt(st.gasRemaining) remaining.Mul(remaining, uint256.MustFromBig(st.msg.GasPrice)) //返还用户 st.state.AddBalance(st.msg.From, remaining, tracing.BalanceIncreaseGasReturn) }
调用堆栈为:
func (st *StateTransition) refundGas()//state_transition.go func (st *StateTransition) TransitionDb()//state_transition.go func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool)//state_transition.go func ApplyTransactionWithEVM //state_processor.go func ApplyTransaction //state_processor.go
3. 矿工coinbase账户增加交易费
支付矿工tip费用。
func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { ... //统计本笔交易使用的gas, gasUsed fee := new(uint256.Int).SetUint64(st.gasUsed()) fee.Mul(fee, effectiveTipU256) //给Coinbase账户增加交易费 st.state.AddBalance(st.evm.Context.Coinbase, fee, tracing.BalanceIncreaseRewardTransactionFee) }
调用堆栈为:
func (st *StateTransition) refundGas()//state_transition.go func (st *StateTransition) TransitionDb()//state_transition.go func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool)//state_transition.go func ApplyTransactionWithEVM //state_processor.go func ApplyTransaction //state_processor.go
回复 french bulldog rescue 取消回复