github.com/annchain/OG@v0.0.9/vm/ovm/ovm.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 Foundation, 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 ovm 18 19 import ( 20 ogTypes "github.com/annchain/OG/arefactor/og_interface" 21 ogcrypto2 "github.com/annchain/OG/deprecated/ogcrypto" 22 "math/big" 23 "sync/atomic" 24 25 "github.com/annchain/OG/common/hexutil" 26 "github.com/annchain/OG/vm/eth/params" 27 vmtypes "github.com/annchain/OG/vm/types" 28 "github.com/sirupsen/logrus" 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 = ogcrypto2.Keccak256Hash(nil) 34 35 // run runs the given contract and takes care of running precompiles with a fallback to the byte Code interpreter. 36 func run(ovm *OVM, contract *vmtypes.Contract, input []byte, readOnly bool) ([]byte, error) { 37 if contract.CodeAddr != nil { 38 precompiles := PrecompiledContractsByzantium 39 if p := precompiles[*contract.CodeAddr]; p != nil { 40 return RunPrecompiledContract(p, input, contract) 41 } 42 } 43 for _, interpreter := range ovm.Interpreters { 44 if interpreter.CanRun(contract.Code) { 45 if ovm.Interpreter != interpreter { 46 // Ensure that the interpreter pointer is set back 47 // to its current value upon return. 48 defer func(i Interpreter) { 49 ovm.Interpreter = i 50 }(ovm.Interpreter) 51 ovm.Interpreter = interpreter 52 } 53 return interpreter.Run(contract, input, readOnly) 54 } 55 } 56 return nil, vmtypes.ErrNoCompatibleInterpreter 57 } 58 59 // OVM is the Ethereum Virtual Machine base object and provides 60 // the necessary tools to run a contract on the given state with 61 // the provided context. It should be noted that any error 62 // generated through any of the calls should be considered a 63 // revert-state-and-consume-all-gas operation, no checks on 64 // specific errors should ever be performed. The interpreter makes 65 // sure that any errors generated are to be considered faulty Code. 66 // 67 // The OVM should never be reused and is not thread safe. 68 type OVM struct { 69 // Context provides auxiliary blockchain related information 70 VMContext *vmtypes.Context 71 // StateDB gives access to the underlying state 72 // StateDB ovm.StateDB moved to Context 73 74 // chainConfig contains information about the current chain 75 // ChainConfig *params.ChainConfig 76 // chain rules contains the chain rules for the current epoch 77 // chainRules params.Rules 78 // virtual machine configuration options used to initialise the 79 // evm. 80 OVMConfigs *OVMConfig 81 // global (to this context) ethereum virtual machine 82 // used throughout the execution of the tx. 83 Interpreters []Interpreter 84 Interpreter Interpreter 85 // abort is used to abort the OVM calling operations 86 // NOTE: must be set atomically 87 // Abort int32 88 // callGasTemp holds the gas available for the current call. This is needed because the 89 // available gas is calculated in gasCall* according to the 63/64 rule and later 90 // applied in opCall*. 91 // CallGasTemp uint64 moved to Context 92 } 93 94 // NewOVM returns a new OVM. The returned OVM is not thread safe and should 95 // only ever be used *once*. 96 func NewOVM(ctx *vmtypes.Context, supportInterpreters []Interpreter, ovmConfig *OVMConfig) *OVM { 97 ovm := &OVM{ 98 VMContext: ctx, 99 OVMConfigs: ovmConfig, 100 //chainRules: chainConfig.Rules(ctx.SequenceID), 101 Interpreters: supportInterpreters, 102 } 103 if ovm.Interpreters != nil && len(ovm.Interpreters) > 0 { 104 // set callers 105 for _, interpreter := range ovm.Interpreters { 106 interpreter.SetCaller(ovm) 107 } 108 109 ovm.Interpreter = ovm.Interpreters[0] 110 } 111 return ovm 112 } 113 114 // Cancel cancels any running OVM operation. This may be called concurrently and 115 // it's safe to be called multiple times. 116 func (ovm *OVM) Cancel() { 117 atomic.StoreInt32(&ovm.VMContext.Abort, 1) 118 } 119 120 // Call executes the contract associated with the addr with the given input as 121 // parameters. It also handles any necessary value transfer required and takes 122 // the necessary steps to create accounts and reverses the state in case of an 123 // execution error or failed value transfer. 124 func (ovm *OVM) Call(caller vmtypes.ContractRef, addr ogTypes.Address20, input []byte, gas uint64, value *big.Int, txCall bool) (ret []byte, leftOverGas uint64, err error) { 125 logrus.WithFields(logrus.Fields{ 126 "caller": caller.Address().Hex(), 127 "addr": addr.Hex(), 128 "input": hexutil.Encode(input), 129 "gas": gas, 130 "value": value, 131 }).Info("It is calling") 132 ctx := ovm.VMContext 133 if ovm.OVMConfigs.NoRecursion && ctx.Depth > 0 { 134 return nil, gas, nil 135 } 136 137 // Fail if we're trying to execute above the call depth limit 138 if ctx.Depth > int(params.CallCreateDepth) { 139 return nil, gas, vmtypes.ErrDepth 140 } 141 // Fail if we're trying to transfer more than the available Balance 142 if !ctx.CanTransfer(ctx.StateDB, caller.Address(), value) { 143 return nil, gas, vmtypes.ErrInsufficientBalance 144 } 145 146 var ( 147 to = vmtypes.AccountRef(addr) 148 snapshot = ctx.StateDB.Snapshot() 149 ) 150 if !ctx.StateDB.Exist(&addr) { 151 precompiles := PrecompiledContractsByzantium 152 if precompiles[addr] == nil && value.Sign() == 0 { 153 // Calling a non existing account, don't do anything, but ping the tracer 154 //if ovm.InterpreterConfig.Debug && ovm.Depth == 0 { 155 // ovm.InterpreterConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) 156 // ovm.InterpreterConfig.Tracer.CaptureEnd(ret, 0, 0, nil) 157 //} 158 return nil, gas, nil 159 } 160 ctx.StateDB.CreateAccount(&addr) 161 } 162 if value.Sign() != 0 && !txCall { 163 164 ctx.Transfer(ctx.StateDB, caller.Address(), to.Address(), value) 165 } 166 167 // Initialise a new contract and set the Code that is to be used by the OVM. 168 // The contract is a scoped environment for this execution context only. 169 contract := vmtypes.NewContract(caller, to, value, gas) 170 codeHash := ctx.StateDB.GetCodeHash(&addr).(*ogTypes.Hash32) 171 contract.SetCallCode(addr, *codeHash, ctx.StateDB.GetCode(&addr)) 172 173 // Even if the account has no Code, we need to continue because it might be a precompile 174 //start := time.Now() 175 176 // Capture the tracer start/end events in debug mode 177 //if ovm.InterpreterConfig.Debug && ovm.Depth == 0 { 178 // ovm.InterpreterConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) 179 // 180 // defer func() { // Lazy evaluation of the parameters 181 // ovm.InterpreterConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) 182 // }() 183 //} 184 ret, err = run(ovm, contract, input, false) 185 186 // When an error was returned by the OVM or when setting the creation Code 187 // above we revert to the snapshot and consume any gas remaining. Additionally 188 // when we're in homestead this also counts for Code storage gas errors. 189 if err != nil { 190 ctx.StateDB.RevertToSnapshot(snapshot) 191 if err != vmtypes.ErrExecutionReverted { 192 contract.UseGas(contract.Gas) 193 } 194 } 195 return ret, contract.Gas, err 196 } 197 198 // CallCode executes the contract associated with the addr with the given input 199 // as parameters. It also handles any necessary value transfer required and takes 200 // the necessary steps to create accounts and reverses the state in case of an 201 // execution error or failed value transfer. 202 // 203 // CallCode differs from Call in the sense that it executes the given address' 204 // Code with the caller as context. 205 func (ovm *OVM) CallCode(caller vmtypes.ContractRef, addr ogTypes.Address20, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { 206 logrus.WithFields(logrus.Fields{ 207 "caller": caller.Address().Hex(), 208 "addr": addr.Hex(), 209 "input": hexutil.Encode(input), 210 "gas": gas, 211 "value": value, 212 }).Info("It is code calling") 213 214 ctx := ovm.VMContext 215 if ovm.OVMConfigs.NoRecursion && ctx.Depth > 0 { 216 return nil, gas, nil 217 } 218 219 // Fail if we're trying to execute above the call depth limit 220 if ctx.Depth > int(params.CallCreateDepth) { 221 return nil, gas, vmtypes.ErrDepth 222 } 223 // Fail if we're trying to transfer more than the available Balance 224 if !ctx.CanTransfer(ctx.StateDB, caller.Address(), value) { 225 return nil, gas, vmtypes.ErrInsufficientBalance 226 } 227 228 var ( 229 snapshot = ctx.StateDB.Snapshot() 230 to = vmtypes.AccountRef(caller.Address()) 231 ) 232 // initialise a new contract and set the Code that is to be used by the 233 // OVM. The contract is a scoped environment for this execution context 234 // only. 235 contract := vmtypes.NewContract(caller, to, value, gas) 236 callCodeHash := ctx.StateDB.GetCodeHash(&addr).(*ogTypes.Hash32) 237 contract.SetCallCode(addr, *callCodeHash, ctx.StateDB.GetCode(&addr)) 238 239 ret, err = run(ovm, contract, input, false) 240 if err != nil { 241 ctx.StateDB.RevertToSnapshot(snapshot) 242 if err != vmtypes.ErrExecutionReverted { 243 contract.UseGas(contract.Gas) 244 } 245 } 246 return ret, contract.Gas, err 247 } 248 249 // DelegateCall executes the contract associated with the addr with the given input 250 // as parameters. It reverses the state in case of an execution error. 251 // 252 // DelegateCall differs from CallCode in the sense that it executes the given address' 253 // Code with the caller as context and the caller is set to the caller of the caller. 254 func (ovm *OVM) DelegateCall(caller vmtypes.ContractRef, addr ogTypes.Address20, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { 255 logrus.WithFields(logrus.Fields{ 256 "caller": caller.Address().Hex(), 257 "addr": addr.Hex(), 258 "input": hexutil.Encode(input), 259 "gas": gas, 260 //"value": value, 261 }).Info("It is delegate calling") 262 ctx := ovm.VMContext 263 if ovm.OVMConfigs.NoRecursion && ctx.Depth > 0 { 264 return nil, gas, nil 265 } 266 // Fail if we're trying to execute above the call depth limit 267 if ctx.Depth > int(params.CallCreateDepth) { 268 return nil, gas, vmtypes.ErrDepth 269 } 270 271 var ( 272 snapshot = ctx.StateDB.Snapshot() 273 to = vmtypes.AccountRef(caller.Address()) 274 ) 275 276 // Initialise a new contract and make initialise the delegate values 277 contract := vmtypes.NewContract(caller, to, nil, gas).AsDelegate() 278 callCodeHash := ctx.StateDB.GetCodeHash(&addr).(*ogTypes.Hash32) 279 contract.SetCallCode(addr, *callCodeHash, ctx.StateDB.GetCode(&addr)) 280 281 ret, err = run(ovm, contract, input, false) 282 if err != nil { 283 ctx.StateDB.RevertToSnapshot(snapshot) 284 if err != vmtypes.ErrExecutionReverted { 285 contract.UseGas(contract.Gas) 286 } 287 } 288 return ret, contract.Gas, err 289 } 290 291 // StaticCall executes the contract associated with the addr with the given input 292 // as parameters while disallowing any modifications to the state during the call. 293 // Opcodes that attempt to perform such modifications will result in exceptions 294 // instead of performing the modifications. 295 func (ovm *OVM) StaticCall(caller vmtypes.ContractRef, addr ogTypes.Address20, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { 296 logrus.WithFields(logrus.Fields{ 297 "caller": caller.Address().Hex(), 298 "addr": addr.Hex(), 299 "input": hexutil.Encode(input), 300 "gas": gas, 301 //"value": value, 302 }).Info("It is static calling") 303 ctx := ovm.VMContext 304 if ovm.OVMConfigs.NoRecursion && ctx.Depth > 0 { 305 return nil, gas, nil 306 } 307 // Fail if we're trying to execute above the call depth limit 308 if ctx.Depth > int(params.CallCreateDepth) { 309 return nil, gas, vmtypes.ErrDepth 310 } 311 312 var ( 313 to = vmtypes.AccountRef(addr) 314 snapshot = ctx.StateDB.Snapshot() 315 ) 316 // Initialise a new contract and set the Code that is to be used by the 317 // OVM. The contract is a scoped environment for this execution context 318 // only. 319 contract := vmtypes.NewContract(caller, to, new(big.Int), gas) 320 callCodeHash := ctx.StateDB.GetCodeHash(&addr).(*ogTypes.Hash32) 321 contract.SetCallCode(addr, *callCodeHash, ctx.StateDB.GetCode(&addr)) 322 323 // When an error was returned by the OVM or when setting the creation Code 324 // above we revert to the snapshot and consume any gas remaining. Additionally 325 // when we're in Homestead this also counts for Code storage gas errors. 326 ret, err = run(ovm, contract, input, true) 327 if err != nil { 328 ctx.StateDB.RevertToSnapshot(snapshot) 329 if err != vmtypes.ErrExecutionReverted { 330 contract.UseGas(contract.Gas) 331 } 332 } 333 return ret, contract.Gas, err 334 } 335 336 // create creates a new contract using Code as deployment Code. 337 func (ovm *OVM) create(caller vmtypes.ContractRef, codeAndHash *vmtypes.CodeAndHash, gas uint64, value *big.Int, address ogTypes.Address20, txCall bool) ([]byte, ogTypes.Address20, uint64, error) { 338 ctx := ovm.VMContext 339 // Depth check execution. Fail if we're trying to execute above the 340 // limit. 341 if ctx.Depth > int(params.CallCreateDepth) { 342 return nil, ogTypes.Address20{}, gas, vmtypes.ErrDepth 343 } 344 if !ctx.CanTransfer(ctx.StateDB, caller.Address(), value) { 345 return nil, ogTypes.Address20{}, gas, vmtypes.ErrInsufficientBalance 346 } 347 callerAddr := caller.Address() 348 nonce := ctx.StateDB.GetNonce(&callerAddr) 349 if !txCall { 350 ctx.StateDB.SetNonce(&callerAddr, nonce+1) 351 } 352 353 // Ensure there's no existing contract already at the designated address 354 contractHash := ctx.StateDB.GetCodeHash(&address).(*ogTypes.Hash32) 355 if ctx.StateDB.GetNonce(&address) != 0 || (*contractHash != (ogTypes.Hash32{}) && contractHash != emptyCodeHash) { 356 return nil, ogTypes.Address20{}, 0, vmtypes.ErrContractAddressCollision 357 } 358 // Create a new account on the state 359 snapshot := ctx.StateDB.Snapshot() 360 ctx.StateDB.CreateAccount(&address) 361 ctx.StateDB.SetNonce(&address, 1) 362 363 if value.Sign() != 0 && !txCall { 364 ctx.Transfer(ctx.StateDB, caller.Address(), address, value) 365 } 366 367 // initialise a new contract and set the Code that is to be used by the 368 // OVM. The contract is a scoped environment for this execution context 369 // only. 370 contract := vmtypes.NewContract(caller, vmtypes.AccountRef(address), value, gas) 371 contract.SetCodeOptionalHash(address, codeAndHash) 372 373 if ovm.OVMConfigs.NoRecursion && ctx.Depth > 0 { 374 return nil, address, gas, nil 375 } 376 377 //if ovm.InterpreterConfig.Debug && ovm.Depth == 0 { 378 // ovm.InterpreterConfig.Tracer.CaptureStart(caller.Address(), address, true, codeAndHash.Code, gas, value) 379 //} 380 //start := time.Now() 381 382 ret, err := run(ovm, contract, nil, false) 383 384 // check whether the max Code size has been exceeded 385 maxCodeSizeExceeded := len(ret) > params.MaxCodeSize 386 // if the contract creation ran successfully and no errors were returned 387 // calculate the gas required to store the Code. If the Code could not 388 // be stored due to not enough gas set an error and let it be handled 389 // by the error checking condition below. 390 if err == nil && !maxCodeSizeExceeded { 391 createDataGas := uint64(len(ret)) * params.CreateDataGas 392 if contract.UseGas(createDataGas) { 393 ctx.StateDB.SetCode(&address, ret) 394 } else { 395 err = vmtypes.ErrCodeStoreOutOfGas 396 } 397 } 398 399 // When an error was returned by the OVM or when setting the creation Code 400 // above we revert to the snapshot and consume any gas remaining. Additionally 401 // when we're in homestead this also counts for Code storage gas errors. 402 if maxCodeSizeExceeded || (err != nil && err != vmtypes.ErrCodeStoreOutOfGas) { 403 ctx.StateDB.RevertToSnapshot(snapshot) 404 if err != vmtypes.ErrExecutionReverted { 405 contract.UseGas(contract.Gas) 406 } 407 } 408 // Assign err if contract Code size exceeds the max while the err is still empty. 409 if maxCodeSizeExceeded && err == nil { 410 err = vmtypes.ErrMaxCodeSizeExceeded 411 } 412 //if ovm.InterpreterConfig.Debug && ovm.Depth == 0 { 413 // ovm.InterpreterConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) 414 //} 415 return ret, address, contract.Gas, err 416 417 } 418 419 // Create creates a new contract using Code as deployment Code. 420 func (ovm *OVM) Create(caller vmtypes.ContractRef, code []byte, gas uint64, value *big.Int, txCall bool) (ret []byte, contractAddr ogTypes.Address20, leftOverGas uint64, err error) { 421 callerAddr := caller.Address() 422 contractAddr = ogTypes.CreateAddress20(caller.Address(), ovm.VMContext.StateDB.GetNonce(&callerAddr)) 423 return ovm.create(caller, &vmtypes.CodeAndHash{Code: code}, gas, value, contractAddr, txCall) 424 } 425 426 // Create2 creates a new contract using Code as deployment Code. 427 // 428 // The different between Create2 with Create is Create2 uses sha3(0xff ++ msg.sender ++ salt ++ sha3(init_code))[12:] 429 // instead of the usual sender-and-Nonce-hash as the address where the contract is initialized at. 430 func (ovm *OVM) Create2(caller vmtypes.ContractRef, code []byte, gas uint64, endowment *big.Int, salt *big.Int, txCall bool) (ret []byte, contractAddr ogTypes.Address20, leftOverGas uint64, err error) { 431 codeAndHash := &vmtypes.CodeAndHash{Code: code} 432 433 saltHash32 := ogTypes.BigToHash32(salt) 434 contractAddr = ogTypes.CreateAddress20_2(caller.Address(), *saltHash32, codeAndHash.Hash().Bytes()) 435 return ovm.create(caller, codeAndHash, gas, endowment, contractAddr, txCall) 436 }