github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/state_transition.go (about)

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