github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/core/state_transition.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:35</date>
    10  //</624450080660787200>
    11  
    12  
    13  package core
    14  
    15  import (
    16  	"errors"
    17  	"math"
    18  	"math/big"
    19  
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/core/vm"
    22  	"github.com/ethereum/go-ethereum/log"
    23  	"github.com/ethereum/go-ethereum/params"
    24  )
    25  
    26  var (
    27  	errInsufficientBalanceForGas = errors.New("insufficient balance to pay for gas")
    28  )
    29  
    30  /*
    31  状态转换模型
    32  
    33  状态转换是将事务应用于当前世界状态时所做的更改。
    34  状态转换模型完成了所有必要的工作,以计算出有效的新状态根。
    35  
    36  1)非紧急处理
    37  2)预付费煤气
    38  3)如果收件人是\0*32,则创建新的状态对象
    39  4)价值转移
    40  ==如果合同创建==
    41    4a)尝试运行事务数据
    42    4b)如果有效,将结果用作新状态对象的代码
    43  =结束==
    44  5)运行脚本部分
    45  6)派生新状态根
    46  **/
    47  
    48  type StateTransition struct {
    49  	gp         *GasPool
    50  	msg        Message
    51  	gas        uint64
    52  	gasPrice   *big.Int
    53  	initialGas uint64
    54  	value      *big.Int
    55  	data       []byte
    56  	state      vm.StateDB
    57  	evm        *vm.EVM
    58  }
    59  
    60  //消息表示发送到合同的消息。
    61  type Message interface {
    62  	From() common.Address
    63  //fromfrontier()(common.address,错误)
    64  	To() *common.Address
    65  
    66  	GasPrice() *big.Int
    67  	Gas() uint64
    68  	Value() *big.Int
    69  
    70  	Nonce() uint64
    71  	CheckNonce() bool
    72  	Data() []byte
    73  }
    74  
    75  //IntrinsicGas用给定的数据计算消息的“固有气体”。
    76  func IntrinsicGas(data []byte, contractCreation, homestead bool) (uint64, error) {
    77  //设置原始交易的起始气体
    78  	var gas uint64
    79  	if contractCreation && homestead {
    80  		gas = params.TxGasContractCreation
    81  	} else {
    82  		gas = params.TxGas
    83  	}
    84  //按事务数据量通气所需的气体
    85  	if len(data) > 0 {
    86  //零字节和非零字节的定价不同
    87  		var nz uint64
    88  		for _, byt := range data {
    89  			if byt != 0 {
    90  				nz++
    91  			}
    92  		}
    93  //确保所有数据组合都不超过uint64
    94  		if (math.MaxUint64-gas)/params.TxDataNonZeroGas < nz {
    95  			return 0, vm.ErrOutOfGas
    96  		}
    97  		gas += nz * params.TxDataNonZeroGas
    98  
    99  		z := uint64(len(data)) - nz
   100  		if (math.MaxUint64-gas)/params.TxDataZeroGas < z {
   101  			return 0, vm.ErrOutOfGas
   102  		}
   103  		gas += z * params.TxDataZeroGas
   104  	}
   105  	return gas, nil
   106  }
   107  
   108  //NewStateTransmission初始化并返回新的状态转换对象。
   109  func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition {
   110  	return &StateTransition{
   111  		gp:       gp,
   112  		evm:      evm,
   113  		msg:      msg,
   114  		gasPrice: msg.GasPrice(),
   115  		value:    msg.Value(),
   116  		data:     msg.Data(),
   117  		state:    evm.StateDB,
   118  	}
   119  }
   120  
   121  //ApplyMessage通过应用给定消息来计算新状态
   122  //反对环境中的旧状态。
   123  //
   124  //ApplyMessage返回任何EVM执行(如果发生)返回的字节,
   125  //使用的气体(包括气体退款)和失败的错误。总是出错
   126  //指示一个核心错误,意味着该消息将总是失败。
   127  //在一个街区内永远不会被接受。
   128  func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, uint64, bool, error) {
   129  	return NewStateTransition(evm, msg, gp).TransitionDb()
   130  }
   131  
   132  //返回邮件的收件人。
   133  func (st *StateTransition) to() common.Address {
   134   /*st.msg==nil st.msg.to()==nil/*合同创建*/
   135    返回公共地址
   136   }
   137   返回*st.msg.to()。
   138  }
   139  
   140  func (st *StateTransition) useGas(amount uint64) error {
   141   如果st.gas<amount
   142    返回vm.erroutofgas
   143   }
   144   ST.气体-=数量
   145  
   146   返回零
   147  }
   148  
   149  func(st*statetransition)buygas()错误
   150   mgval:=new(big.int).mul(new(big.int).setuint64(st.msg.gas()),st.gasprice)
   151   if st.state.getbalance(st.msg.from()).cmp(mgval)<0_
   152    返回不平衡气体
   153   }
   154   如果错误:=st.gp.subgas(st.msg.gas());错误!= nIL{
   155    返回错误
   156   }
   157   st.gas+=st.msg.gas()。
   158  
   159   st.initialgas=st.msg.gas()。
   160   st.state.subbalance(st.msg.from(),mgval)
   161   返回零
   162  }
   163  
   164  func(st*statetransition)precheck()错误
   165   //确保此事务的nonce是正确的。
   166   if st.msg.checknonce()
   167    nonce:=st.state.getnonce(st.msg.from())
   168    如果nonce<st.msg.nonce()
   169     返回erroncetohohigh
   170    else if nonce>st.msg.nonce()
   171     返回erroncetoolow
   172    }
   173   }
   174   返回圣布伊加斯(St.Buygas)
   175  }
   176  
   177  //transitionDB将通过应用当前消息和
   178  //返回包括已用气体在内的结果。如果失败,则返回错误。
   179  //错误表示一致性问题。
   180  func(st*statetransition)transitiondb()(ret[]byte,usedgas uint64,failed bool,err error)
   181   如果err=st.precheck();err!= nIL{
   182    返回
   183   }
   184   MSG:= ST.MSG
   185   发件人:=vm.accountRef(msg.from())
   186   homestead:=st.evm.chainconfig().ishomestead(st.evm.blocknumber)
   187   合同创建:=msg.to()==nil
   188  
   189   //支付天然气
   190   气体,误差:=内部气体(St.Data,ContractCreation,Homestead)
   191   如果犯错!= nIL{
   192    返回nil、0、false、err
   193   }
   194   如果err=st.usegas(gas);err!= nIL{
   195    返回nil、0、false、err
   196   }
   197  
   198   var
   199    EVM=ST.EVM
   200    //VM错误不影响共识,因此
   201    //未分配给err,余额不足除外
   202    /错误。
   203    VMER误差
   204   )
   205   如果合同创建
   206    ret,,st.gas,vmerr=evm.create(发送方,st.data,st.gas,st.value)
   207   }否则{
   208    //为下一个事务增加nonce
   209    st.state.setnonce(msg.from(),st.state.getnonce(sender.address())+1)
   210    ret,st.gas,vmerr=evm.call(sender,st.to(),st.data,st.gas,st.value)
   211   }
   212   如果VMRR!= nIL{
   213    log.debug(“返回的VM有错误”,“err”,vm err)
   214    //唯一可能的共识错误是如果没有
   215    //有足够的余额进行转移。第一
   216    //余额转移永远不会失败。
   217    如果vmerr==vm.errUnsuffictBalance
   218     返回nil、0、false、vmerr
   219    }
   220   }
   221   S.ReffgdGas()
   222   添加平衡(st.evm.coinbase,new(big.int).mul(new(big.int).setuint64(st.gasused()),st.gasprice)
   223  
   224   返回ret,st.gasused(),vmerr!=零
   225  }
   226  
   227  func(st*statetransition)refundgas()
   228   //申请退款柜台,上限为已用气体的一半。
   229   退款:=st.gasused()/2
   230   如果退款>st.state.get退款()
   231    退款=st.state.get退款()
   232   }
   233   ST.GAS+=退款
   234  
   235   //剩余气体返回eth,按原汇率交换。
   236   剩余:=new(big.int).mul(new(big.int).setuint64(st.gas),st.gasprice)
   237   st.state.addbalance(st.msg.from(),剩余)
   238  
   239   //同时将剩余气体返回至区块气计数器,因此
   240   //可用于下一个事务。
   241   添加气体(ST.GAS)
   242  }
   243  
   244  //gas used返回状态转换所消耗的气体量。
   245  func(st*statetransition)gasused()uint64_
   246   返回St.InitialGas-St.Gas
   247  }
   248