github.com/ethereum/go-ethereum@v1.16.1/core/vm/contract.go (about) 1 // Copyright 2015 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 vm 18 19 import ( 20 "github.com/ethereum/go-ethereum/common" 21 "github.com/ethereum/go-ethereum/core/tracing" 22 "github.com/holiman/uint256" 23 ) 24 25 // Contract represents an ethereum contract in the state database. It contains 26 // the contract code, calling arguments. Contract implements ContractRef 27 type Contract struct { 28 // caller is the result of the caller which initialised this 29 // contract. However, when the "call method" is delegated this 30 // value needs to be initialised to that of the caller's caller. 31 caller common.Address 32 address common.Address 33 34 jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis. 35 analysis bitvec // Locally cached result of JUMPDEST analysis 36 37 Code []byte 38 CodeHash common.Hash 39 Input []byte 40 41 // is the execution frame represented by this object a contract deployment 42 IsDeployment bool 43 IsSystemCall bool 44 45 Gas uint64 46 value *uint256.Int 47 } 48 49 // NewContract returns a new contract environment for the execution of EVM. 50 func NewContract(caller common.Address, address common.Address, value *uint256.Int, gas uint64, jumpDests map[common.Hash]bitvec) *Contract { 51 // Initialize the jump analysis map if it's nil, mostly for tests 52 if jumpDests == nil { 53 jumpDests = make(map[common.Hash]bitvec) 54 } 55 return &Contract{ 56 caller: caller, 57 address: address, 58 jumpdests: jumpDests, 59 Gas: gas, 60 value: value, 61 } 62 } 63 64 func (c *Contract) validJumpdest(dest *uint256.Int) bool { 65 udest, overflow := dest.Uint64WithOverflow() 66 // PC cannot go beyond len(code) and certainly can't be bigger than 63bits. 67 // Don't bother checking for JUMPDEST in that case. 68 if overflow || udest >= uint64(len(c.Code)) { 69 return false 70 } 71 // Only JUMPDESTs allowed for destinations 72 if OpCode(c.Code[udest]) != JUMPDEST { 73 return false 74 } 75 return c.isCode(udest) 76 } 77 78 // isCode returns true if the provided PC location is an actual opcode, as 79 // opposed to a data-segment following a PUSHN operation. 80 func (c *Contract) isCode(udest uint64) bool { 81 // Do we already have an analysis laying around? 82 if c.analysis != nil { 83 return c.analysis.codeSegment(udest) 84 } 85 // Do we have a contract hash already? 86 // If we do have a hash, that means it's a 'regular' contract. For regular 87 // contracts ( not temporary initcode), we store the analysis in a map 88 if c.CodeHash != (common.Hash{}) { 89 // Does parent context have the analysis? 90 analysis, exist := c.jumpdests[c.CodeHash] 91 if !exist { 92 // Do the analysis and save in parent context 93 // We do not need to store it in c.analysis 94 analysis = codeBitmap(c.Code) 95 c.jumpdests[c.CodeHash] = analysis 96 } 97 // Also stash it in current contract for faster access 98 c.analysis = analysis 99 return analysis.codeSegment(udest) 100 } 101 // We don't have the code hash, most likely a piece of initcode not already 102 // in state trie. In that case, we do an analysis, and save it locally, so 103 // we don't have to recalculate it for every JUMP instruction in the execution 104 // However, we don't save it within the parent context 105 if c.analysis == nil { 106 c.analysis = codeBitmap(c.Code) 107 } 108 return c.analysis.codeSegment(udest) 109 } 110 111 // GetOp returns the n'th element in the contract's byte array 112 func (c *Contract) GetOp(n uint64) OpCode { 113 if n < uint64(len(c.Code)) { 114 return OpCode(c.Code[n]) 115 } 116 117 return STOP 118 } 119 120 // Caller returns the caller of the contract. 121 // 122 // Caller will recursively call caller when the contract is a delegate 123 // call, including that of caller's caller. 124 func (c *Contract) Caller() common.Address { 125 return c.caller 126 } 127 128 // UseGas attempts the use gas and subtracts it and returns true on success 129 func (c *Contract) UseGas(gas uint64, logger *tracing.Hooks, reason tracing.GasChangeReason) (ok bool) { 130 if c.Gas < gas { 131 return false 132 } 133 if logger != nil && logger.OnGasChange != nil && reason != tracing.GasChangeIgnored { 134 logger.OnGasChange(c.Gas, c.Gas-gas, reason) 135 } 136 c.Gas -= gas 137 return true 138 } 139 140 // RefundGas refunds gas to the contract 141 func (c *Contract) RefundGas(gas uint64, logger *tracing.Hooks, reason tracing.GasChangeReason) { 142 if gas == 0 { 143 return 144 } 145 if logger != nil && logger.OnGasChange != nil && reason != tracing.GasChangeIgnored { 146 logger.OnGasChange(c.Gas, c.Gas+gas, reason) 147 } 148 c.Gas += gas 149 } 150 151 // Address returns the contracts address 152 func (c *Contract) Address() common.Address { 153 return c.address 154 } 155 156 // Value returns the contract's value (sent to it from it's caller) 157 func (c *Contract) Value() *uint256.Int { 158 return c.value 159 } 160 161 // SetCallCode sets the code of the contract, 162 func (c *Contract) SetCallCode(hash common.Hash, code []byte) { 163 c.Code = code 164 c.CodeHash = hash 165 }