github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/core/vm/context.go (about) 1 // Copyright 2016 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 "math/big" 21 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/consensus" 24 "github.com/ethereum/go-ethereum/core/state" 25 "github.com/ethereum/go-ethereum/core/types" 26 "github.com/ethereum/go-ethereum/params" 27 ) 28 29 // Message represents a message sent to a contract. 30 type Message interface { 31 From() common.Address 32 //FromFrontier() (common.Address, error) 33 To() *common.Address 34 35 GasPrice() *big.Int 36 Gas() uint64 37 38 // FeeCurrency specifies the currency for gas and gateway fees. 39 // nil correspond to Celo Gold (native currency). 40 // All other values should correspond to ERC20 contract addresses extended to be compatible with gas payments. 41 FeeCurrency() *common.Address 42 GatewayFeeRecipient() *common.Address 43 GatewayFee() *big.Int 44 Value() *big.Int 45 46 Nonce() uint64 47 CheckNonce() bool 48 Data() []byte 49 } 50 51 // ChainContext supports retrieving chain data and consensus parameters 52 // from the blockchain to be used during transaction processing. 53 type ChainContext interface { 54 // Engine retrieves the blockchain's consensus engine. 55 Engine() consensus.Engine 56 57 // GetHeader returns the hash corresponding to the given hash and number. 58 GetHeader(common.Hash, uint64) *types.Header 59 60 // GetHeaderByNumber returns the hash corresponding number. 61 // FIXME: Use of this function, as implemented, in the EVM context produces undefined behavior 62 // in the pressence of forks. A new method needs to be created to retrieve a header by number 63 // in the correct fork. 64 GetHeaderByNumber(uint64) *types.Header 65 66 // GetVMConfig returns the node's vm configuration 67 GetVMConfig() *Config 68 69 CurrentHeader() *types.Header 70 71 State() (*state.StateDB, error) 72 73 // Config returns the blockchain's chain configuration 74 Config() *params.ChainConfig 75 } 76 77 // NewEVMContext creates a new context for use in the EVM. 78 func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author *common.Address) Context { 79 // If we don't have an explicit author (i.e. not mining), extract from the header 80 var beneficiary common.Address 81 if author == nil { 82 beneficiary, _ = chain.Engine().Author(header) // Ignore error, we're past header validation 83 } else { 84 beneficiary = *author 85 } 86 87 var engine consensus.Engine 88 var getHeaderByNumberFn func(uint64) *types.Header 89 if chain != nil { 90 engine = chain.Engine() 91 getHeaderByNumberFn = chain.GetHeaderByNumber 92 } 93 94 return Context{ 95 CanTransfer: CanTransfer, 96 Transfer: Transfer, 97 GetHash: GetHashFn(header, chain), 98 GetHeaderByNumber: getHeaderByNumberFn, 99 VerifySeal: VerifySealFn(header, chain), 100 Origin: msg.From(), 101 Coinbase: beneficiary, 102 BlockNumber: new(big.Int).Set(header.Number), 103 Time: new(big.Int).Set(header.Time), 104 Difficulty: new(big.Int).Set(header.Difficulty), 105 GasLimit: header.GasLimit, 106 GasPrice: new(big.Int).Set(msg.GasPrice()), 107 Engine: engine, 108 } 109 } 110 111 // GetHashFn returns a GetHashFunc which retrieves header hashes by number 112 func GetHashFn(ref *types.Header, chain ChainContext) func(uint64) common.Hash { 113 var cache map[uint64]common.Hash 114 115 return func(n uint64) common.Hash { 116 // If there's no hash cache yet, make one 117 if cache == nil { 118 cache = map[uint64]common.Hash{ 119 ref.Number.Uint64() - 1: ref.ParentHash, 120 } 121 } 122 // Try to fulfill the request from the cache 123 if hash, ok := cache[n]; ok { 124 return hash 125 } 126 // Not cached, iterate the blocks and cache the hashes (up to a limit of 256) 127 for i, header := 0, chain.GetHeader(ref.ParentHash, ref.Number.Uint64()-1); header != nil && i <= 256; i, header = i+1, chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) { 128 cache[header.Number.Uint64()-1] = header.ParentHash 129 if n == header.Number.Uint64()-1 { 130 return header.ParentHash 131 } 132 } 133 return common.Hash{} 134 } 135 } 136 137 // CanTransfer checks whether there are enough funds in the address' account to make a transfer. 138 // This does not take the necessary gas into account to make the transfer valid. 139 func CanTransfer(db StateDB, addr common.Address, amount *big.Int) bool { 140 return db.GetBalance(addr).Cmp(amount) >= 0 141 } 142 143 // Transfer subtracts amount from sender and adds amount to recipient using the given Db 144 func Transfer(db StateDB, sender, recipient common.Address, amount *big.Int) { 145 db.SubBalance(sender, amount) 146 db.AddBalance(recipient, amount) 147 } 148 149 // VerifySealFn returns a function which returns true when the given header has a verifiable seal. 150 func VerifySealFn(ref *types.Header, chain ChainContext) func(*types.Header) bool { 151 return func(header *types.Header) bool { 152 // If the block is later than the unsealed reference block, return false. 153 if header.Number.Cmp(ref.Number) > 0 { 154 return false 155 } 156 157 // FIXME: Implementation currently relies on the Istanbul engine's internal view of the 158 // chain, so return false if this is not an Istanbul chain. As a consequence of this the 159 // seal is always verified against the canonical chain, which makes behavior undefined if 160 // this function is evaluated on a chain which does not have the highest total difficulty. 161 if chain.Config().Istanbul == nil { 162 return false 163 } 164 165 // Submit the header to the engine's seal verification function. 166 return chain.Engine().VerifySeal(nil, header) == nil 167 } 168 }