github.com/alanchchen/go-ethereum@v1.6.6-0.20170601190819-6171d01b1195/light/state.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 light 18 19 import ( 20 "context" 21 "math/big" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/crypto" 25 ) 26 27 // LightState is a memory representation of a state. 28 // This version is ODR capable, caching only the already accessed part of the 29 // state, retrieving unknown parts on-demand from the ODR backend. Changes are 30 // never stored in the local database, only in the memory objects. 31 type LightState struct { 32 odr OdrBackend 33 trie *LightTrie 34 id *TrieID 35 stateObjects map[string]*StateObject 36 refund *big.Int 37 } 38 39 // NewLightState creates a new LightState with the specified root. 40 // Note that the creation of a light state is always successful, even if the 41 // root is non-existent. In that case, ODR retrieval will always be unsuccessful 42 // and every operation will return with an error or wait for the context to be 43 // cancelled. 44 func NewLightState(id *TrieID, odr OdrBackend) *LightState { 45 var tr *LightTrie 46 if id != nil { 47 tr = NewLightTrie(id, odr, true) 48 } 49 return &LightState{ 50 odr: odr, 51 trie: tr, 52 id: id, 53 stateObjects: make(map[string]*StateObject), 54 refund: new(big.Int), 55 } 56 } 57 58 // AddRefund adds an amount to the refund value collected during a vm execution 59 func (self *LightState) AddRefund(gas *big.Int) { 60 self.refund.Add(self.refund, gas) 61 } 62 63 // HasAccount returns true if an account exists at the given address 64 func (self *LightState) HasAccount(ctx context.Context, addr common.Address) (bool, error) { 65 so, err := self.GetStateObject(ctx, addr) 66 return so != nil, err 67 } 68 69 // GetBalance retrieves the balance from the given address or 0 if the account does 70 // not exist 71 func (self *LightState) GetBalance(ctx context.Context, addr common.Address) (*big.Int, error) { 72 stateObject, err := self.GetStateObject(ctx, addr) 73 if err != nil { 74 return common.Big0, err 75 } 76 if stateObject != nil { 77 return stateObject.balance, nil 78 } 79 80 return common.Big0, nil 81 } 82 83 // GetNonce returns the nonce at the given address or 0 if the account does 84 // not exist 85 func (self *LightState) GetNonce(ctx context.Context, addr common.Address) (uint64, error) { 86 stateObject, err := self.GetStateObject(ctx, addr) 87 if err != nil { 88 return 0, err 89 } 90 if stateObject != nil { 91 return stateObject.nonce, nil 92 } 93 return 0, nil 94 } 95 96 // GetCode returns the contract code at the given address or nil if the account 97 // does not exist 98 func (self *LightState) GetCode(ctx context.Context, addr common.Address) ([]byte, error) { 99 stateObject, err := self.GetStateObject(ctx, addr) 100 if err != nil { 101 return nil, err 102 } 103 if stateObject != nil { 104 return stateObject.code, nil 105 } 106 return nil, nil 107 } 108 109 // GetState returns the contract storage value at storage address b from the 110 // contract address a or common.Hash{} if the account does not exist 111 func (self *LightState) GetState(ctx context.Context, a common.Address, b common.Hash) (common.Hash, error) { 112 stateObject, err := self.GetStateObject(ctx, a) 113 if err == nil && stateObject != nil { 114 return stateObject.GetState(ctx, b) 115 } 116 return common.Hash{}, err 117 } 118 119 // HasSuicided returns true if the given account has been marked for deletion 120 // or false if the account does not exist 121 func (self *LightState) HasSuicided(ctx context.Context, addr common.Address) (bool, error) { 122 stateObject, err := self.GetStateObject(ctx, addr) 123 if err == nil && stateObject != nil { 124 return stateObject.remove, nil 125 } 126 return false, err 127 } 128 129 /* 130 * SETTERS 131 */ 132 133 // AddBalance adds the given amount to the balance of the specified account 134 func (self *LightState) AddBalance(ctx context.Context, addr common.Address, amount *big.Int) error { 135 stateObject, err := self.GetOrNewStateObject(ctx, addr) 136 if err == nil && stateObject != nil { 137 stateObject.AddBalance(amount) 138 } 139 return err 140 } 141 142 // SubBalance adds the given amount to the balance of the specified account 143 func (self *LightState) SubBalance(ctx context.Context, addr common.Address, amount *big.Int) error { 144 stateObject, err := self.GetOrNewStateObject(ctx, addr) 145 if err == nil && stateObject != nil { 146 stateObject.SubBalance(amount) 147 } 148 return err 149 } 150 151 // SetNonce sets the nonce of the specified account 152 func (self *LightState) SetNonce(ctx context.Context, addr common.Address, nonce uint64) error { 153 stateObject, err := self.GetOrNewStateObject(ctx, addr) 154 if err == nil && stateObject != nil { 155 stateObject.SetNonce(nonce) 156 } 157 return err 158 } 159 160 // SetCode sets the contract code at the specified account 161 func (self *LightState) SetCode(ctx context.Context, addr common.Address, code []byte) error { 162 stateObject, err := self.GetOrNewStateObject(ctx, addr) 163 if err == nil && stateObject != nil { 164 stateObject.SetCode(crypto.Keccak256Hash(code), code) 165 } 166 return err 167 } 168 169 // SetState sets the storage value at storage address key of the account addr 170 func (self *LightState) SetState(ctx context.Context, addr common.Address, key common.Hash, value common.Hash) error { 171 stateObject, err := self.GetOrNewStateObject(ctx, addr) 172 if err == nil && stateObject != nil { 173 stateObject.SetState(key, value) 174 } 175 return err 176 } 177 178 // Delete marks an account to be removed and clears its balance 179 func (self *LightState) Suicide(ctx context.Context, addr common.Address) (bool, error) { 180 stateObject, err := self.GetOrNewStateObject(ctx, addr) 181 if err == nil && stateObject != nil { 182 stateObject.MarkForDeletion() 183 stateObject.balance = new(big.Int) 184 185 return true, nil 186 } 187 188 return false, err 189 } 190 191 // 192 // Get, set, new state object methods 193 // 194 195 // GetStateObject returns the state object of the given account or nil if the 196 // account does not exist 197 func (self *LightState) GetStateObject(ctx context.Context, addr common.Address) (stateObject *StateObject, err error) { 198 stateObject = self.stateObjects[addr.Str()] 199 if stateObject != nil { 200 if stateObject.deleted { 201 stateObject = nil 202 } 203 return stateObject, nil 204 } 205 data, err := self.trie.Get(ctx, addr[:]) 206 if err != nil { 207 return nil, err 208 } 209 if len(data) == 0 { 210 return nil, nil 211 } 212 213 stateObject, err = DecodeObject(ctx, self.id, addr, self.odr, []byte(data)) 214 if err != nil { 215 return nil, err 216 } 217 218 self.SetStateObject(stateObject) 219 220 return stateObject, nil 221 } 222 223 // SetStateObject sets the state object of the given account 224 func (self *LightState) SetStateObject(object *StateObject) { 225 self.stateObjects[object.Address().Str()] = object 226 } 227 228 // GetOrNewStateObject returns the state object of the given account or creates a 229 // new one if the account does not exist 230 func (self *LightState) GetOrNewStateObject(ctx context.Context, addr common.Address) (*StateObject, error) { 231 stateObject, err := self.GetStateObject(ctx, addr) 232 if err == nil && (stateObject == nil || stateObject.deleted) { 233 stateObject, err = self.CreateStateObject(ctx, addr) 234 } 235 return stateObject, err 236 } 237 238 // newStateObject creates a state object whether it exists in the state or not 239 func (self *LightState) newStateObject(addr common.Address) *StateObject { 240 stateObject := NewStateObject(addr, self.odr) 241 self.stateObjects[addr.Str()] = stateObject 242 243 return stateObject 244 } 245 246 // CreateStateObject creates creates a new state object and takes ownership. 247 // This is different from "NewStateObject" 248 func (self *LightState) CreateStateObject(ctx context.Context, addr common.Address) (*StateObject, error) { 249 // Get previous (if any) 250 so, err := self.GetStateObject(ctx, addr) 251 if err != nil { 252 return nil, err 253 } 254 // Create a new one 255 newSo := self.newStateObject(addr) 256 257 // If it existed set the balance to the new account 258 if so != nil { 259 newSo.balance = so.balance 260 } 261 262 return newSo, nil 263 } 264 265 // ForEachStorage calls a callback function for every key/value pair found 266 // in the local storage cache. Note that unlike core/state.StateObject, 267 // light.StateObject only returns cached values and doesn't download the 268 // entire storage tree. 269 func (self *LightState) ForEachStorage(ctx context.Context, addr common.Address, cb func(key, value common.Hash) bool) error { 270 so, err := self.GetStateObject(ctx, addr) 271 if err != nil { 272 return err 273 } 274 275 if so == nil { 276 return nil 277 } 278 279 for h, v := range so.storage { 280 cb(h, v) 281 } 282 return nil 283 } 284 285 // 286 // Setting, copying of the state methods 287 // 288 289 // Copy creates a copy of the state 290 func (self *LightState) Copy() *LightState { 291 // ignore error - we assume state-to-be-copied always exists 292 state := NewLightState(nil, self.odr) 293 state.trie = self.trie 294 state.id = self.id 295 for k, stateObject := range self.stateObjects { 296 if stateObject.dirty { 297 state.stateObjects[k] = stateObject.Copy() 298 } 299 } 300 301 state.refund.Set(self.refund) 302 return state 303 } 304 305 // Set copies the contents of the given state onto this state, overwriting 306 // its contents 307 func (self *LightState) Set(state *LightState) { 308 self.trie = state.trie 309 self.stateObjects = state.stateObjects 310 self.refund = state.refund 311 } 312 313 // GetRefund returns the refund value collected during a vm execution 314 func (self *LightState) GetRefund() *big.Int { 315 return self.refund 316 }