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 }