github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/vm/evm.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 vm
    26  
    27  import (
    28  	"math/big"
    29  	"sync/atomic"
    30  	"time"
    31  
    32  	"github.com/ethereum/go-ethereum/common"
    33  	"github.com/ethereum/go-ethereum/crypto"
    34  	"github.com/ethereum/go-ethereum/params"
    35  )
    36  
    37  //create使用EmptyCodeHash来确保已不允许部署
    38  //已部署的合同地址(在帐户提取之后相关)。
    39  var emptyCodeHash = crypto.Keccak256Hash(nil)
    40  
    41  type (
    42  //cantransferfunc是传递保护函数的签名
    43  	CanTransferFunc func(StateDB, common.Address, *big.Int) bool
    44  //transferFunc是传递函数的签名
    45  	TransferFunc func(StateDB, common.Address, common.Address, *big.Int)
    46  //gethashfunc返回区块链中的第n个区块哈希
    47  //并由blockhash evm op代码使用。
    48  	GetHashFunc func(uint64) common.Hash
    49  )
    50  
    51  //Run运行给定的合同,并负责运行回退到字节码解释器的预编译。
    52  func run(evm *EVM, contract *Contract, input []byte) ([]byte, error) {
    53  	if contract.CodeAddr != nil {
    54  		precompiles := PrecompiledContractsHomestead
    55  		if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
    56  			precompiles = PrecompiledContractsByzantium
    57  		}
    58  		if p := precompiles[*contract.CodeAddr]; p != nil {
    59  			return RunPrecompiledContract(p, input, contract)
    60  		}
    61  	}
    62  	for _, interpreter := range evm.interpreters {
    63  		if interpreter.CanRun(contract.Code) {
    64  			if evm.interpreter != interpreter {
    65  //确保解释器指针设置回原处
    66  //返回到当前值。
    67  				defer func(i Interpreter) {
    68  					evm.interpreter = i
    69  				}(evm.interpreter)
    70  				evm.interpreter = interpreter
    71  			}
    72  			return interpreter.Run(contract, input)
    73  		}
    74  	}
    75  	return nil, ErrNoCompatibleInterpreter
    76  }
    77  
    78  //上下文为EVM提供辅助信息。一旦提供
    79  //它不应该被修改。
    80  type Context struct {
    81  //CanTransfer返回帐户是否包含
    82  //足够的乙醚转移价值
    83  	CanTransfer CanTransferFunc
    84  //将乙醚从一个帐户转移到另一个帐户
    85  	Transfer TransferFunc
    86  //GetHash返回与n对应的哈希
    87  	GetHash GetHashFunc
    88  
    89  //消息信息
    90  Origin   common.Address //提供源站信息
    91  GasPrice *big.Int       //为Gasprice提供信息
    92  
    93  //阻止信息
    94  Coinbase    common.Address //为CoinBase提供信息
    95  GasLimit    uint64         //提供气体限制信息
    96  BlockNumber *big.Int       //提供数字信息
    97  Time        *big.Int       //提供时间信息
    98  Difficulty  *big.Int       //为困难提供信息
    99  }
   100  
   101  //EVM是以太坊虚拟机基础对象,它提供
   102  //在给定状态下运行合同所需的工具
   103  //提供的上下文。应该注意的是,任何错误
   104  //通过任何调用生成的应被视为
   105  //恢复状态并消耗所有气体操作,不检查
   106  //应执行特定错误。翻译使
   107  //确保生成的任何错误都被视为错误代码。
   108  //
   109  //EVM不应该被重用,也不是线程安全的。
   110  type EVM struct {
   111  //上下文提供辅助区块链相关信息
   112  	Context
   113  //statedb提供对底层状态的访问
   114  	StateDB StateDB
   115  //深度是当前调用堆栈
   116  	depth int
   117  
   118  //chainconfig包含有关当前链的信息
   119  	chainConfig *params.ChainConfig
   120  //链规则包含当前纪元的链规则
   121  	chainRules params.Rules
   122  //用于初始化的虚拟机配置选项
   123  //EVM。
   124  	vmConfig Config
   125  //全局(到此上下文)以太坊虚拟机
   126  //在整个Tx执行过程中使用。
   127  	interpreters []Interpreter
   128  	interpreter  Interpreter
   129  //abort用于中止EVM调用操作
   130  //注:必须按原子顺序设置
   131  	abort int32
   132  //callgastemp保留当前呼叫可用的气体。这是需要的,因为
   133  //根据63/64规则和更高版本,可用气体在GasCall*中计算。
   134  //在opcall*中应用。
   135  	callGasTemp uint64
   136  }
   137  
   138  //new evm返回新的evm。返回的EVM不是线程安全的,应该
   139  //只能使用一次。
   140  func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
   141  	evm := &EVM{
   142  		Context:      ctx,
   143  		StateDB:      statedb,
   144  		vmConfig:     vmConfig,
   145  		chainConfig:  chainConfig,
   146  		chainRules:   chainConfig.Rules(ctx.BlockNumber),
   147  		interpreters: make([]Interpreter, 1),
   148  	}
   149  
   150  	evm.interpreters[0] = NewEVMInterpreter(evm, vmConfig)
   151  	evm.interpreter = evm.interpreters[0]
   152  
   153  	return evm
   154  }
   155  
   156  //取消取消任何正在运行的EVM操作。这可以同时调用,并且
   157  //多次打电话是安全的。
   158  func (evm *EVM) Cancel() {
   159  	atomic.StoreInt32(&evm.abort, 1)
   160  }
   161  
   162  //解释器返回当前解释器
   163  func (evm *EVM) Interpreter() Interpreter {
   164  	return evm.interpreter
   165  }
   166  
   167  //调用执行与给定输入为的addr关联的协定
   168  //参数。它还处理任何必要的价值转移,并采取
   169  //创建帐户和在
   170  //执行错误或值传输失败。
   171  func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
   172  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   173  		return nil, gas, nil
   174  	}
   175  
   176  //如果我们试图执行超过调用深度限制,则失败
   177  	if evm.depth > int(params.CallCreateDepth) {
   178  		return nil, gas, ErrDepth
   179  	}
   180  //如果我们试图转移的余额超过可用余额,则失败
   181  	if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
   182  		return nil, gas, ErrInsufficientBalance
   183  	}
   184  
   185  	var (
   186  		to       = AccountRef(addr)
   187  		snapshot = evm.StateDB.Snapshot()
   188  	)
   189  	if !evm.StateDB.Exist(addr) {
   190  		precompiles := PrecompiledContractsHomestead
   191  		if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
   192  			precompiles = PrecompiledContractsByzantium
   193  		}
   194  		if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
   195  //调用一个不存在的帐户,不要做任何事情,只需ping跟踪程序
   196  			if evm.vmConfig.Debug && evm.depth == 0 {
   197  				evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
   198  				evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil)
   199  			}
   200  			return nil, gas, nil
   201  		}
   202  		evm.StateDB.CreateAccount(addr)
   203  	}
   204  	evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
   205  
   206  //初始化新合同并设置EVM要使用的代码。
   207  //契约只是这个执行上下文的作用域环境。
   208  	contract := NewContract(caller, to, value, gas)
   209  	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
   210  
   211  	start := time.Now()
   212  
   213  //在调试模式下捕获跟踪程序开始/结束事件
   214  	if evm.vmConfig.Debug && evm.depth == 0 {
   215  		evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
   216  
   217  defer func() { //参数的延迟评估
   218  			evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
   219  		}()
   220  	}
   221  	ret, err = run(evm, contract, input)
   222  
   223  //当EVM返回错误或设置创建代码时
   224  //在上面,我们返回快照并消耗所有剩余的气体。另外
   225  //当我们在宅基地时,这也算是代码存储气体错误。
   226  	if err != nil {
   227  		evm.StateDB.RevertToSnapshot(snapshot)
   228  		if err != errExecutionReverted {
   229  			contract.UseGas(contract.Gas)
   230  		}
   231  	}
   232  	return ret, contract.Gas, err
   233  }
   234  
   235  //callcode使用给定的输入执行与addr关联的协定
   236  //作为参数。它还处理任何必要的价值转移,并采取
   237  //创建帐户和在
   238  //执行错误或值传输失败。
   239  //
   240  //callcode与call的区别在于它执行给定的地址'
   241  //以调用方为上下文的代码。
   242  func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
   243  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   244  		return nil, gas, nil
   245  	}
   246  
   247  //如果我们试图执行超过调用深度限制,则失败
   248  	if evm.depth > int(params.CallCreateDepth) {
   249  		return nil, gas, ErrDepth
   250  	}
   251  //如果我们试图转移的余额超过可用余额,则失败
   252  	if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
   253  		return nil, gas, ErrInsufficientBalance
   254  	}
   255  
   256  	var (
   257  		snapshot = evm.StateDB.Snapshot()
   258  		to       = AccountRef(caller.Address())
   259  	)
   260  //初始化新合同并设置
   261  //EVM。合同是此执行上下文的作用域环境
   262  //只有。
   263  	contract := NewContract(caller, to, value, gas)
   264  	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
   265  
   266  	ret, err = run(evm, contract, input)
   267  	if err != nil {
   268  		evm.StateDB.RevertToSnapshot(snapshot)
   269  		if err != errExecutionReverted {
   270  			contract.UseGas(contract.Gas)
   271  		}
   272  	}
   273  	return ret, contract.Gas, err
   274  }
   275  
   276  //DelegateCall执行与给定输入的addr关联的协定
   277  //作为参数。如果发生执行错误,它将反转状态。
   278  //
   279  //delegateCall与callcode的区别在于它执行给定的地址'
   280  //以调用者为上下文的代码,调用者被设置为调用者的调用者。
   281  func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
   282  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   283  		return nil, gas, nil
   284  	}
   285  //如果我们试图执行超过调用深度限制,则失败
   286  	if evm.depth > int(params.CallCreateDepth) {
   287  		return nil, gas, ErrDepth
   288  	}
   289  
   290  	var (
   291  		snapshot = evm.StateDB.Snapshot()
   292  		to       = AccountRef(caller.Address())
   293  	)
   294  
   295  //初始化新合同并使委托值初始化
   296  	contract := NewContract(caller, to, nil, gas).AsDelegate()
   297  	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
   298  
   299  	ret, err = run(evm, contract, input)
   300  	if err != nil {
   301  		evm.StateDB.RevertToSnapshot(snapshot)
   302  		if err != errExecutionReverted {
   303  			contract.UseGas(contract.Gas)
   304  		}
   305  	}
   306  	return ret, contract.Gas, err
   307  }
   308  
   309  //staticCall使用给定的输入执行与addr关联的协定
   310  //作为参数,同时不允许在调用期间对状态进行任何修改。
   311  //试图执行此类修改的操作码将导致异常
   312  //而不是执行修改。
   313  func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
   314  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   315  		return nil, gas, nil
   316  	}
   317  //如果我们试图执行超过调用深度限制,则失败
   318  	if evm.depth > int(params.CallCreateDepth) {
   319  		return nil, gas, ErrDepth
   320  	}
   321  //确保仅当我们不在readonly中时才设置readonly
   322  //这还确保不会为删除只读标志
   323  //儿童电话。
   324  	if !evm.interpreter.IsReadOnly() {
   325  		evm.interpreter.SetReadOnly(true)
   326  		defer func() { evm.interpreter.SetReadOnly(false) }()
   327  	}
   328  
   329  	var (
   330  		to       = AccountRef(addr)
   331  		snapshot = evm.StateDB.Snapshot()
   332  	)
   333  //初始化新合同并设置
   334  //EVM。合同是此执行上下文的作用域环境
   335  //只有。
   336  	contract := NewContract(caller, to, new(big.Int), gas)
   337  	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
   338  
   339  //当EVM返回错误或设置创建代码时
   340  //在上面,我们返回快照并消耗所有剩余的气体。另外
   341  //当我们在宅基地时,这也算是代码存储气体错误。
   342  	ret, err = run(evm, contract, input)
   343  	if err != nil {
   344  		evm.StateDB.RevertToSnapshot(snapshot)
   345  		if err != errExecutionReverted {
   346  			contract.UseGas(contract.Gas)
   347  		}
   348  	}
   349  	return ret, contract.Gas, err
   350  }
   351  
   352  //创建使用代码作为部署代码创建新合同。
   353  func (evm *EVM) create(caller ContractRef, code []byte, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) {
   354  //深度检查执行。如果我们试图执行上面的
   355  //极限。
   356  	if evm.depth > int(params.CallCreateDepth) {
   357  		return nil, common.Address{}, gas, ErrDepth
   358  	}
   359  	if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
   360  		return nil, common.Address{}, gas, ErrInsufficientBalance
   361  	}
   362  	nonce := evm.StateDB.GetNonce(caller.Address())
   363  	evm.StateDB.SetNonce(caller.Address(), nonce+1)
   364  
   365  //确保指定地址没有现有合同
   366  	contractHash := evm.StateDB.GetCodeHash(address)
   367  	if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) {
   368  		return nil, common.Address{}, 0, ErrContractAddressCollision
   369  	}
   370  //在该州创建新帐户
   371  	snapshot := evm.StateDB.Snapshot()
   372  	evm.StateDB.CreateAccount(address)
   373  	if evm.ChainConfig().IsEIP158(evm.BlockNumber) {
   374  		evm.StateDB.SetNonce(address, 1)
   375  	}
   376  	evm.Transfer(evm.StateDB, caller.Address(), address, value)
   377  
   378  //初始化新合同并设置
   379  //EVM。合同是此执行上下文的作用域环境
   380  //只有。
   381  	contract := NewContract(caller, AccountRef(address), value, gas)
   382  	contract.SetCallCode(&address, crypto.Keccak256Hash(code), code)
   383  
   384  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   385  		return nil, address, gas, nil
   386  	}
   387  
   388  	if evm.vmConfig.Debug && evm.depth == 0 {
   389  		evm.vmConfig.Tracer.CaptureStart(caller.Address(), address, true, code, gas, value)
   390  	}
   391  	start := time.Now()
   392  
   393  	ret, err := run(evm, contract, nil)
   394  
   395  //检查是否超过了最大代码大小
   396  	maxCodeSizeExceeded := evm.ChainConfig().IsEIP158(evm.BlockNumber) && len(ret) > params.MaxCodeSize
   397  //如果合同创建成功运行且未返回错误
   398  //计算存储代码所需的气体。如果代码不能
   399  //因气量不足而储存,设置错误并处理
   400  //通过下面的错误检查条件。
   401  	if err == nil && !maxCodeSizeExceeded {
   402  		createDataGas := uint64(len(ret)) * params.CreateDataGas
   403  		if contract.UseGas(createDataGas) {
   404  			evm.StateDB.SetCode(address, ret)
   405  		} else {
   406  			err = ErrCodeStoreOutOfGas
   407  		}
   408  	}
   409  
   410  //当EVM返回错误或设置创建代码时
   411  //在上面,我们返回快照并消耗所有剩余的气体。另外
   412  //当我们在宅基地时,这也算是代码存储气体错误。
   413  	if maxCodeSizeExceeded || (err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) {
   414  		evm.StateDB.RevertToSnapshot(snapshot)
   415  		if err != errExecutionReverted {
   416  			contract.UseGas(contract.Gas)
   417  		}
   418  	}
   419  //如果合同代码大小超过最大值而错误仍然为空,则分配错误。
   420  	if maxCodeSizeExceeded && err == nil {
   421  		err = errMaxCodeSizeExceeded
   422  	}
   423  	if evm.vmConfig.Debug && evm.depth == 0 {
   424  		evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
   425  	}
   426  	return ret, address, contract.Gas, err
   427  
   428  }
   429  
   430  //创建使用代码作为部署代码创建新合同。
   431  func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
   432  	contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address()))
   433  	return evm.create(caller, code, gas, value, contractAddr)
   434  }
   435  
   436  //Create2使用代码作为部署代码创建新合同。
   437  //
   438  //create2与create的区别是create2使用sha3(0xff++msg.sender++salt++sha3(init_code))[12:]
   439  //而不是通常的发送者和nonce散列作为合同初始化的地址。
   440  func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
   441  	contractAddr = crypto.CreateAddress2(caller.Address(), common.BigToHash(salt), code)
   442  	return evm.create(caller, code, gas, endowment, contractAddr)
   443  }
   444  
   445  //chainconfig返回环境的链配置
   446  func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }