github.com/insight-chain/inb-go@v1.1.3-0.20191221022159-da049980ae38/core/vm/evm.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software MiningReward, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package vm 18 19 import ( 20 "github.com/insight-chain/inb-go/core/types" 21 "math/big" 22 "strconv" 23 "sync/atomic" 24 "time" 25 26 "github.com/insight-chain/inb-go/common" 27 "github.com/insight-chain/inb-go/crypto" 28 "github.com/insight-chain/inb-go/params" 29 ) 30 31 // emptyCodeHash is used by create to ensure deployment is disallowed to already 32 // deployed contract addresses (relevant after the account abstraction). 33 var emptyCodeHash = crypto.Keccak256Hash(nil) 34 35 type ( 36 // CanTransferFunc is the signature of a transfer guard function 37 CanTransferFunc func(StateDB, common.Address, *big.Int) bool 38 // TransferFunc is the signature of a transfer function 39 TransferFunc func(StateDB, common.Address, common.Address, *big.Int) 40 //Resource by zc 41 MortgageTrasferFunc func(StateDB, common.Address, common.Address, *big.Int, *big.Int, big.Int, common.Hash) *big.Int 42 //Resource by zc 43 // GetHashFunc returns the nth block hash in the blockchain 44 // and is used by the BLOCKHASH EVM op code. 45 GetHashFunc func(uint64) common.Hash 46 47 CanResetFunc func(StateDB, common.Address, *big.Int) error 48 CanMortgageFunc func(StateDB, common.Address, *big.Int, *big.Int) error 49 CanRedeemFunc func(StateDB, common.Address, *big.Int) error 50 CanReceiveFunc func(StateDB, common.Address, *big.Int) error 51 RedeemTransferFunc func(StateDB, common.Address, common.Address, *big.Int, *big.Int) 52 ReceiveTransferFunc func(StateDB, common.Address, *big.Int) *big.Int 53 ResetTransferFunc func(StateDB, common.Address, *big.Int) *big.Int 54 55 CanReceiveLockedAwardFunc func(StateDB, common.Address, common.Hash, *big.Int, types.SpecialConsensus) (error, *big.Int, bool, common.Address) //2019.7.22 inb by ghy begin 56 ReceiveLockedAwardFunc func(StateDB, common.Address, common.Hash, *big.Int, bool, *big.Int, common.Address) //2019.7.22 inb by ghy begin 57 CanReceiveVoteAwardFunc func(StateDB, common.Address, *big.Int, types.SpecialConsensus) (error, *big.Int, common.Address) //2019.7.24 inb by ghy begin 58 ReceiveVoteAwardFunc func(StateDB, common.Address, *big.Int, *big.Int, common.Address) //2019.7.24 inb by ghy begin 59 VoteFunc func(StateDB, common.Address, *big.Int) 60 InsteadMortgageTransferFunc func(StateDB, common.Address, common.Address, *big.Int, *big.Int, big.Int, common.Hash) *big.Int //20190919 added replacement mortgage 61 CanInsteadMortgageFunc func(StateDB, common.Address, common.Address, *big.Int, *big.Int) error 62 CanUpdateNodeInformationFunc func(StateDB, common.Address, []byte) error //2019.10.17 inb by ghy 63 CanVoteFunc func(StateDB, []byte) error 64 CanIssueLightTokenFunc func(StateDB, common.Address, []byte, *big.Int) error 65 ) 66 67 // run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter. 68 func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) { 69 if contract.CodeAddr != nil { 70 precompiles := PrecompiledContractsHomestead 71 if evm.ChainConfig().IsByzantium(evm.BlockNumber) { 72 precompiles = PrecompiledContractsByzantium 73 } 74 if p := precompiles[*contract.CodeAddr]; p != nil { 75 return RunPrecompiledContract(p, input, contract) 76 } 77 } 78 for _, interpreter := range evm.interpreters { 79 if interpreter.CanRun(contract.Code) { 80 if evm.interpreter != interpreter { 81 // Ensure that the interpreter pointer is set back 82 // to its current value upon return. 83 defer func(i Interpreter) { 84 evm.interpreter = i 85 }(evm.interpreter) 86 evm.interpreter = interpreter 87 } 88 return interpreter.Run(contract, input, readOnly) 89 } 90 } 91 return nil, ErrNoCompatibleInterpreter 92 } 93 94 // Context provides the EVM with auxiliary information. Once provided 95 // it shouldn't be modified. 96 type Context struct { 97 // CanTransfer returns whether the account contains 98 // sufficient ether to transfer the value 99 CanTransfer CanTransferFunc 100 // Transfer transfers ether from one account to the other 101 Transfer TransferFunc 102 //Resource by zc 103 MortgageTransfer MortgageTrasferFunc 104 //Resource by zc 105 // GetHash returns the hash corresponding to n 106 GetHash GetHashFunc 107 108 // Message information 109 Origin common.Address // Provides information for ORIGIN 110 GasPrice *big.Int // Provides information for GASPRICE 111 112 // Block information 113 Coinbase common.Address // Provides information for COINBASE 114 GasLimit uint64 // Provides information for GASLIMIT 115 BlockNumber *big.Int // Provides information for NUMBER 116 Time *big.Int // Provides information for TIME 117 Difficulty *big.Int // Provides information for DIFFICULTY 118 SpecialConsensus types.SpecialConsensus //2019.7.31 inb by ghy 119 CanReset CanResetFunc 120 CanMortgage CanMortgageFunc 121 CanRedeem CanRedeemFunc 122 CanReceive CanReceiveFunc 123 RedeemTransfer RedeemTransferFunc 124 ResetTransfer ResetTransferFunc 125 ReceiveTransfer ReceiveTransferFunc 126 ReceiveLockedAward ReceiveLockedAwardFunc //2019.7.22 inb by ghy 127 Vote VoteFunc //2019.7.24 inb by ghy 128 CanReceiveLockedAward CanReceiveLockedAwardFunc 129 CanReceiveVoteAward CanReceiveVoteAwardFunc //2019.7.24 inb by ghy 130 ReceiveVoteAward ReceiveVoteAwardFunc //2019.7.24 inb by ghy 131 InsteadMortgageTransfer InsteadMortgageTransferFunc //20190919 added replacement mortgage 132 CanInsteadMortgage CanInsteadMortgageFunc 133 CanUpdateNodeInformation CanUpdateNodeInformationFunc //2019.10.17 inb by ghy 134 CanVote CanVoteFunc //2019.10.17 inb by ghy 135 CanIssueLightToken CanIssueLightTokenFunc //2019.10.18 inb by ghy 136 } 137 138 // EVM is the Ethereum Virtual Machine base object and provides 139 // the necessary tools to run a contract on the given state with 140 // the provided context. It should be noted that any error 141 // generated through any of the calls should be considered a 142 // revert-state-and-consume-all-gas operation, no checks on 143 // specific errors should ever be performed. The interpreter makes 144 // sure that any errors generated are to be considered faulty code. 145 // 146 // The EVM should never be reused and is not thread safe. 147 type EVM struct { 148 // Context provides auxiliary blockchain related information 149 Context 150 // StateDB gives access to the underlying state 151 StateDB StateDB 152 // Depth is the current call stack 153 depth int 154 155 // chainConfig contains information about the current chain 156 chainConfig *params.ChainConfig 157 // chain rules contains the chain rules for the current epoch 158 chainRules params.Rules 159 // virtual machine configuration options used to initialise the 160 // evm. 161 vmConfig Config 162 // global (to this context) ethereum virtual machine 163 // used throughout the execution of the tx. 164 interpreters []Interpreter 165 interpreter Interpreter 166 // abort is used to abort the EVM calling operations 167 // NOTE: must be set atomically 168 abort int32 169 // callGasTemp holds the gas available for the current call. This is needed because the 170 // available gas is calculated in gasCall* according to the 63/64 rule and later 171 // applied in opCall*. 172 callGasTemp uint64 173 } 174 175 // NewEVM returns a new EVM. The returned EVM is not thread safe and should 176 // only ever be used *once*. 177 func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM { 178 evm := &EVM{ 179 Context: ctx, 180 StateDB: statedb, 181 vmConfig: vmConfig, 182 chainConfig: chainConfig, 183 chainRules: chainConfig.Rules(ctx.BlockNumber), 184 interpreters: make([]Interpreter, 0, 1), 185 } 186 187 if chainConfig.IsEWASM(ctx.BlockNumber) { 188 // to be implemented by EVM-C and Wagon PRs. 189 // if vmConfig.EWASMInterpreter != "" { 190 // extIntOpts := strings.Split(vmConfig.EWASMInterpreter, ":") 191 // path := extIntOpts[0] 192 // options := []string{} 193 // if len(extIntOpts) > 1 { 194 // options = extIntOpts[1..] 195 // } 196 // evm.interpreters = append(evm.interpreters, NewEVMVCInterpreter(evm, vmConfig, options)) 197 // } else { 198 // evm.interpreters = append(evm.interpreters, NewEWASMInterpreter(evm, vmConfig)) 199 // } 200 panic("No supported ewasm interpreter yet.") 201 } 202 203 // vmConfig.EVMInterpreter will be used by EVM-C, it won't be checked here 204 // as we always want to have the built-in EVM as the failover option. 205 evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, vmConfig)) 206 evm.interpreter = evm.interpreters[0] 207 208 return evm 209 } 210 211 // Cancel cancels any running EVM operation. This may be called concurrently and 212 // it's safe to be called multiple times. 213 func (evm *EVM) Cancel() { 214 atomic.StoreInt32(&evm.abort, 1) 215 } 216 217 // Interpreter returns the current interpreter 218 func (evm *EVM) Interpreter() Interpreter { 219 return evm.interpreter 220 } 221 222 func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, res uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error, receive *big.Int) { 223 return evm.NewCall(caller, addr, input, res, value, types.Ordinary, [32]byte{}) 224 } 225 226 // Call executes the contract associated with the addr with the given input as 227 // parameters. It also handles any necessary value transfer required and takes 228 // the necessary steps to create accounts and reverses the state in case of an 229 // execution error or failed value transfer. 230 func (evm *EVM) NewCall(caller ContractRef, addr common.Address, input []byte, res uint64, value *big.Int, txType types.TxType, hash common.Hash) (ret []byte, leftOverGas uint64, err error, receive *big.Int) { 231 if evm.vmConfig.NoRecursion && evm.depth > 0 { 232 return nil, res, nil, nil 233 } 234 //valiedate to is nil for required transaction type 235 /*var toAddr common.Address 236 if types.ValidateTo(txType) && toAddr == addr { 237 return nil, res, ErrToRequired, nil 238 }*/ 239 // Fail if we're trying to execute above the call depth limit 240 if evm.depth > int(params.CallCreateDepth) { 241 return nil, res, ErrDepth, nil 242 } 243 var ( 244 to = AccountRef(addr) 245 snapshot = evm.StateDB.Snapshot() 246 ) 247 // achilles improve mortgage 248 inputStr := string(input) 249 days := 0 // duration of mortgagtion, 250 251 //2019.7.22 inb by ghy begin 252 LockedAward := big.NewInt(0) 253 VoteAward := big.NewInt(0) 254 reses := big.NewInt(0) 255 isAll := false 256 lockHash := [32]byte{} 257 toAddress := common.Address{} 258 if txType == types.ReceiveLockedAward { 259 260 lockHash = common.BytesToHash(input) 261 //if err != nil { 262 // return nil, res, err, nil 263 //} 264 err, LockedAward, isAll, toAddress = evm.CanReceiveLockedAward(evm.StateDB, caller.Address(), lockHash, evm.BlockNumber, evm.SpecialConsensus) 265 if err != nil { 266 return nil, res, err, nil 267 } 268 //2019.7.22 inb by ghy end 269 } else if txType == types.Regular { 270 //regulars := strings.Split(inputStr, ":") 271 //if len(regulars) <= 1 { 272 // return nil, res, ErrNotResolveInput, big.NewInt(0) 273 //} 274 //convert, err := strconv.Atoi(regulars[1]) 275 convert, err := strconv.Atoi(inputStr) 276 if err != nil { 277 return nil, res, err, nil 278 } 279 days = convert 280 if err := evm.Context.CanMortgage(evm.StateDB, caller.Address(), value, big.NewInt(int64(days))); err != nil { 281 return nil, res, err, nil 282 283 } 284 } else if txType == types.Mortgage { 285 if err := evm.Context.CanMortgage(evm.StateDB, caller.Address(), value, big.NewInt(int64(days))); err != nil { 286 return nil, res, err, nil 287 } 288 } else if txType == types.InsteadMortgage { 289 //regulars := strings.Split(inputStr, ":") 290 //if len(regulars) <= 1 { 291 // return nil, res, ErrNotResolveInput, big.NewInt(0) 292 //} 293 //convert, err := strconv.Atoi(regulars[1]) 294 convert, err := strconv.Atoi(inputStr) 295 if err != nil { 296 return nil, res, err, nil 297 } 298 days = convert 299 if err := evm.Context.CanInsteadMortgage(evm.StateDB, caller.Address(), to.Address(), value, big.NewInt(int64(days))); err != nil { 300 return nil, res, err, nil 301 } 302 } else if txType == types.Redeem { 303 if err := evm.Context.CanRedeem(evm.StateDB, caller.Address(), value); err != nil { 304 return nil, res, err, nil 305 } 306 } else if txType == types.Reset { 307 if err := evm.Context.CanReset(evm.StateDB, caller.Address(), evm.BlockNumber); err != nil { 308 return nil, res, err, nil 309 } 310 } else if txType == types.Receive { 311 if err := evm.Context.CanReceive(evm.StateDB, caller.Address(), evm.BlockNumber); err != nil { 312 return nil, res, err, nil 313 } 314 } else if txType == types.ReceiveVoteAward { //2019.7.24 inb by ghy 315 if err, VoteAward, toAddress = evm.Context.CanReceiveVoteAward(evm.StateDB, caller.Address(), evm.BlockNumber, evm.SpecialConsensus); err != nil { 316 317 return nil, res, err, nil 318 } 319 } else if txType == types.UpdateNodeInformation { //2019.10.17 inb by ghy 320 if err = evm.Context.CanUpdateNodeInformation(evm.StateDB, caller.Address(), input); err != nil { 321 return nil, res, err, nil 322 } 323 } else if txType == types.Vote { 324 if err = evm.Context.CanVote(evm.StateDB, input); err != nil { 325 return nil, res, err, nil 326 } 327 } else if txType == types.IssueLightToken { 328 if err = evm.Context.CanIssueLightToken(evm.StateDB, caller.Address(), input, value); err != nil { 329 return nil, res, err, nil 330 } 331 } else if txType == types.TransferLightToken || txType == types.RegularLightToken || txType == types.RedeemLightToken || txType == types.InsteadRegularLightToken { 332 // do nothing because we don't need to check up value when transferLightToken,regularLightToken,redeemLightToken,insteadRegularLightToken 333 } else { 334 // Fail if we're trying to transfer more than the available balance 335 if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { 336 return nil, res, ErrInsufficientBalance, nil 337 } 338 } 339 340 // add by ssh 190925 begin 341 // check up if the tx need 'to' address 342 //if !evm.StateDB.Exist(addr) { 343 if !evm.StateDB.Exist(addr) && types.ValidateTo(txType) { 344 // add by ssh 190925 end 345 precompiles := PrecompiledContractsHomestead 346 if evm.ChainConfig().IsByzantium(evm.BlockNumber) { 347 precompiles = PrecompiledContractsByzantium 348 } 349 if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 { 350 // Calling a non existing account, don't do anything, but ping the tracer 351 if evm.vmConfig.Debug && evm.depth == 0 { 352 evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, res, value) 353 evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil) 354 } 355 return nil, res, nil, nil 356 } 357 evm.StateDB.CreateAccount(addr) 358 } 359 //evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value) 360 //Resource by zc 361 362 if txType == types.Vote { 363 evm.Vote(evm.StateDB, caller.Address(), evm.BlockNumber) 364 } else if txType == types.Redeem { 365 evm.RedeemTransfer(evm.StateDB, caller.Address(), to.Address(), value, evm.BlockNumber) 366 } else if txType == types.Regular || txType == types.Mortgage { 367 reses = evm.MortgageTransfer(evm.StateDB, caller.Address(), to.Address(), value, big.NewInt(int64(days)), *evm.BlockNumber, hash) 368 } else if txType == types.InsteadMortgage { 369 reses = evm.InsteadMortgageTransfer(evm.StateDB, caller.Address(), to.Address(), value, big.NewInt(int64(days)), *evm.BlockNumber, hash) 370 } else if txType == types.Reset { 371 reses = evm.ResetTransfer(evm.StateDB, caller.Address(), evm.BlockNumber) 372 } else if txType == types.ReceiveVoteAward { //2019.7.22 inb by ghy begin 373 evm.ReceiveVoteAward(evm.StateDB, caller.Address(), VoteAward, evm.BlockNumber, toAddress) 374 } else if txType == types.ReceiveLockedAward { 375 evm.ReceiveLockedAward(evm.StateDB, caller.Address(), lockHash, LockedAward, isAll, evm.BlockNumber, toAddress) 376 //2019.7.22 inb by ghy end 377 } else if txType == types.Receive { 378 reses = evm.ReceiveTransfer(evm.StateDB, caller.Address(), evm.BlockNumber) 379 } else if txType == types.IssueLightToken { 380 //for _, v := range evm.SpecialConsensus.SpecialConsensusAddress { 381 // if v.SpecialType == state.OnlineMarketing { 382 // evm.Transfer(evm.StateDB, caller.Address(), v.ToAddress, value) 383 // break 384 // } 385 //} 386 } else if txType == types.TransferLightToken || txType == types.RegularLightToken || txType == types.RedeemLightToken || txType == types.InsteadRegularLightToken { 387 // do nothing when transferLightToken,regularLightToken,redeemLightToken,insteadRegularLightToken 388 } else { 389 evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value) 390 } 391 392 // Initialise a new contract and set the code that is to be used by the EVM. 393 // The contract is a scoped environment for this execution context only. 394 contract := NewContract(caller, to, value, res) 395 contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) 396 397 // Even if the account has no code, we need to continue because it might be a precompile 398 start := time.Now() 399 400 // Capture the tracer start/end events in debug mode 401 if evm.vmConfig.Debug && evm.depth == 0 { 402 evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, res, value) 403 404 defer func() { // Lazy evaluation of the parameters 405 evm.vmConfig.Tracer.CaptureEnd(ret, res-contract.Gas, time.Since(start), err) 406 }() 407 } 408 ret, err = run(evm, contract, input, false) 409 410 // When an error was returned by the EVM or when setting the creation code 411 // above we revert to the snapshot and consume any gas remaining. Additionally 412 // when we're in homestead this also counts for code storage gas errors. 413 if err != nil { 414 evm.StateDB.RevertToSnapshot(snapshot) 415 if err != errExecutionReverted { 416 contract.UseGas(contract.Gas) 417 } 418 } 419 420 switch txType { 421 case types.ReceiveVoteAward: 422 return ret, contract.Gas, err, VoteAward 423 case types.ReceiveLockedAward: 424 return ret, contract.Gas, err, LockedAward 425 case types.IssueLightToken: 426 return ret, contract.Gas, err, big.NewInt(1) 427 default: 428 return ret, contract.Gas, err, reses 429 } 430 } 431 432 // CallCode executes the contract associated with the addr with the given input 433 // as parameters. It also handles any necessary value transfer required and takes 434 // the necessary steps to create accounts and reverses the state in case of an 435 // execution error or failed value transfer. 436 // 437 // CallCode differs from Call in the sense that it executes the given address' 438 // code with the caller as context. 439 func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { 440 if evm.vmConfig.NoRecursion && evm.depth > 0 { 441 return nil, gas, nil 442 } 443 444 // Fail if we're trying to execute above the call depth limit 445 if evm.depth > int(params.CallCreateDepth) { 446 return nil, gas, ErrDepth 447 } 448 // Fail if we're trying to transfer more than the available balance 449 if !evm.CanTransfer(evm.StateDB, caller.Address(), value) { 450 return nil, gas, ErrInsufficientBalance 451 } 452 453 var ( 454 snapshot = evm.StateDB.Snapshot() 455 to = AccountRef(caller.Address()) 456 ) 457 // initialise a new contract and set the code that is to be used by the 458 // EVM. The contract is a scoped environment for this execution context 459 // only. 460 contract := NewContract(caller, to, value, gas) 461 contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) 462 463 ret, err = run(evm, contract, input, false) 464 if err != nil { 465 evm.StateDB.RevertToSnapshot(snapshot) 466 if err != errExecutionReverted { 467 contract.UseGas(contract.Gas) 468 } 469 } 470 return ret, contract.Gas, err 471 } 472 473 // DelegateCall executes the contract associated with the addr with the given input 474 // as parameters. It reverses the state in case of an execution error. 475 // 476 // DelegateCall differs from CallCode in the sense that it executes the given address' 477 // code with the caller as context and the caller is set to the caller of the caller. 478 func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { 479 if evm.vmConfig.NoRecursion && evm.depth > 0 { 480 return nil, gas, nil 481 } 482 // Fail if we're trying to execute above the call depth limit 483 if evm.depth > int(params.CallCreateDepth) { 484 return nil, gas, ErrDepth 485 } 486 487 var ( 488 snapshot = evm.StateDB.Snapshot() 489 to = AccountRef(caller.Address()) 490 ) 491 492 // Initialise a new contract and make initialise the delegate values 493 contract := NewContract(caller, to, nil, gas).AsDelegate() 494 contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) 495 496 ret, err = run(evm, contract, input, false) 497 if err != nil { 498 evm.StateDB.RevertToSnapshot(snapshot) 499 if err != errExecutionReverted { 500 contract.UseGas(contract.Gas) 501 } 502 } 503 return ret, contract.Gas, err 504 } 505 506 // StaticCall executes the contract associated with the addr with the given input 507 // as parameters while disallowing any modifications to the state during the call. 508 // Opcodes that attempt to perform such modifications will result in exceptions 509 // instead of performing the modifications. 510 func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { 511 if evm.vmConfig.NoRecursion && evm.depth > 0 { 512 return nil, gas, nil 513 } 514 // Fail if we're trying to execute above the call depth limit 515 if evm.depth > int(params.CallCreateDepth) { 516 return nil, gas, ErrDepth 517 } 518 519 var ( 520 to = AccountRef(addr) 521 snapshot = evm.StateDB.Snapshot() 522 ) 523 // Initialise a new contract and set the code that is to be used by the 524 // EVM. The contract is a scoped environment for this execution context 525 // only. 526 contract := NewContract(caller, to, new(big.Int), gas) 527 contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) 528 529 // We do an AddBalance of zero here, just in order to trigger a touch. 530 // This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium, 531 // but is the correct thing to do and matters on other networks, in tests, and potential 532 // future scenarios 533 evm.StateDB.AddBalance(addr, bigZero) 534 535 // When an error was returned by the EVM or when setting the creation code 536 // above we revert to the snapshot and consume any gas remaining. Additionally 537 // when we're in Homestead this also counts for code storage gas errors. 538 ret, err = run(evm, contract, input, true) 539 if err != nil { 540 evm.StateDB.RevertToSnapshot(snapshot) 541 if err != errExecutionReverted { 542 contract.UseGas(contract.Gas) 543 } 544 } 545 return ret, contract.Gas, err 546 } 547 548 type codeAndHash struct { 549 code []byte 550 hash common.Hash 551 } 552 553 func (c *codeAndHash) Hash() common.Hash { 554 if c.hash == (common.Hash{}) { 555 c.hash = crypto.Keccak256Hash(c.code) 556 } 557 return c.hash 558 } 559 560 // create creates a new contract using code as deployment code. 561 func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) { 562 // Depth check execution. Fail if we're trying to execute above the 563 // limit. 564 if evm.depth > int(params.CallCreateDepth) { 565 return nil, common.Address{}, gas, ErrDepth 566 } 567 if !evm.CanTransfer(evm.StateDB, caller.Address(), value) { 568 return nil, common.Address{}, gas, ErrInsufficientBalance 569 } 570 nonce := evm.StateDB.GetNonce(caller.Address()) 571 evm.StateDB.SetNonce(caller.Address(), nonce+1) 572 573 // Ensure there's no existing contract already at the designated address 574 contractHash := evm.StateDB.GetCodeHash(address) 575 if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) { 576 return nil, common.Address{}, 0, ErrContractAddressCollision 577 } 578 // Create a new account on the state 579 snapshot := evm.StateDB.Snapshot() 580 evm.StateDB.CreateAccount(address) 581 if evm.ChainConfig().IsEIP158(evm.BlockNumber) { 582 evm.StateDB.SetNonce(address, 1) 583 } 584 evm.Transfer(evm.StateDB, caller.Address(), address, value) 585 586 // initialise a new contract and set the code that is to be used by the 587 // EVM. The contract is a scoped environment for this execution context 588 // only. 589 contract := NewContract(caller, AccountRef(address), value, gas) 590 contract.SetCodeOptionalHash(&address, codeAndHash) 591 592 if evm.vmConfig.NoRecursion && evm.depth > 0 { 593 return nil, address, gas, nil 594 } 595 596 if evm.vmConfig.Debug && evm.depth == 0 { 597 evm.vmConfig.Tracer.CaptureStart(caller.Address(), address, true, codeAndHash.code, gas, value) 598 } 599 start := time.Now() 600 601 ret, err := run(evm, contract, nil, false) 602 603 // check whether the max code size has been exceeded 604 maxCodeSizeExceeded := evm.ChainConfig().IsEIP158(evm.BlockNumber) && len(ret) > params.MaxCodeSize 605 // if the contract creation ran successfully and no errors were returned 606 // calculate the gas required to store the code. If the code could not 607 // be stored due to not enough gas set an error and let it be handled 608 // by the error checking condition below. 609 if err == nil && !maxCodeSizeExceeded { 610 createDataGas := uint64(len(ret)) * params.CreateDataGas 611 if contract.UseGas(createDataGas) { 612 evm.StateDB.SetCode(address, ret) 613 } else { 614 err = ErrCodeStoreOutOfGas 615 } 616 } 617 618 // When an error was returned by the EVM or when setting the creation code 619 // above we revert to the snapshot and consume any gas remaining. Additionally 620 // when we're in homestead this also counts for code storage gas errors. 621 if maxCodeSizeExceeded || (err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) { 622 evm.StateDB.RevertToSnapshot(snapshot) 623 if err != errExecutionReverted { 624 contract.UseGas(contract.Gas) 625 } 626 } 627 // Assign err if contract code size exceeds the max while the err is still empty. 628 if maxCodeSizeExceeded && err == nil { 629 err = errMaxCodeSizeExceeded 630 } 631 if evm.vmConfig.Debug && evm.depth == 0 { 632 evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) 633 } 634 return ret, address, contract.Gas, err 635 636 } 637 638 // Create creates a new contract using code as deployment code. 639 func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { 640 contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address())) 641 return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr) 642 } 643 644 // Create2 creates a new contract using code as deployment code. 645 // 646 // The different between Create2 with Create is Create2 uses sha3(0xff ++ msg.sender ++ salt ++ sha3(init_code))[12:] 647 // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. 648 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) { 649 codeAndHash := &codeAndHash{code: code} 650 contractAddr = crypto.CreateAddress2(caller.Address(), common.BigToHash(salt), codeAndHash.Hash().Bytes()) 651 return evm.create(caller, codeAndHash, gas, endowment, contractAddr) 652 } 653 654 // ChainConfig returns the environment's chain configuration 655 func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }