github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/light/state_object.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 "bytes" 21 "context" 22 "fmt" 23 "math/big" 24 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/crypto" 27 "github.com/ethereum/go-ethereum/rlp" 28 ) 29 30 var emptyCodeHash = crypto.Keccak256(nil) 31 32 // Code represents a contract code in binary form 33 type Code []byte 34 35 // String returns a string representation of the code 36 func (self Code) String() string { 37 return string(self) //strings.Join(Disassemble(self), " ") 38 } 39 40 // Storage is a memory map cache of a contract storage 41 type Storage map[common.Hash]common.Hash 42 43 // String returns a string representation of the storage cache 44 func (self Storage) String() (str string) { 45 for key, value := range self { 46 str += fmt.Sprintf("%X : %X\n", key, value) 47 } 48 49 return 50 } 51 52 // Copy copies the contents of a storage cache 53 func (self Storage) Copy() Storage { 54 cpy := make(Storage) 55 for key, value := range self { 56 cpy[key] = value 57 } 58 59 return cpy 60 } 61 62 // StateObject is a memory representation of an account or contract and its storage. 63 // This version is ODR capable, caching only the already accessed part of the 64 // storage, retrieving unknown parts on-demand from the ODR backend. Changes are 65 // never stored in the local database, only in the memory objects. 66 type StateObject struct { 67 odr OdrBackend 68 trie *LightTrie 69 70 // Address belonging to this account 71 address common.Address 72 // The balance of the account 73 balance *big.Int 74 // The nonce of the account 75 nonce uint64 76 // The code hash if code is present (i.e. a contract) 77 codeHash []byte 78 // The code for this account 79 code Code 80 // Cached storage (flushed when updated) 81 storage Storage 82 83 // Mark for deletion 84 // When an object is marked for deletion it will be delete from the trie 85 // during the "update" phase of the state transition 86 remove bool 87 deleted bool 88 dirty bool 89 } 90 91 // NewStateObject creates a new StateObject of the specified account address 92 func NewStateObject(address common.Address, odr OdrBackend) *StateObject { 93 object := &StateObject{ 94 odr: odr, 95 address: address, 96 balance: new(big.Int), 97 dirty: true, 98 codeHash: emptyCodeHash, 99 storage: make(Storage), 100 } 101 object.trie = NewLightTrie(&TrieID{}, odr, true) 102 return object 103 } 104 105 // MarkForDeletion marks an account to be removed 106 func (self *StateObject) MarkForDeletion() { 107 self.remove = true 108 self.dirty = true 109 } 110 111 // getAddr gets the storage value at the given address from the trie 112 func (c *StateObject) getAddr(ctx context.Context, addr common.Hash) (common.Hash, error) { 113 var ret []byte 114 val, err := c.trie.Get(ctx, addr[:]) 115 if err != nil { 116 return common.Hash{}, err 117 } 118 rlp.DecodeBytes(val, &ret) 119 return common.BytesToHash(ret), nil 120 } 121 122 // Storage returns the storage cache object of the account 123 func (self *StateObject) Storage() Storage { 124 return self.storage 125 } 126 127 // GetState returns the storage value at the given address from either the cache 128 // or the trie 129 func (self *StateObject) GetState(ctx context.Context, key common.Hash) (common.Hash, error) { 130 value, exists := self.storage[key] 131 if !exists { 132 var err error 133 value, err = self.getAddr(ctx, key) 134 if err != nil { 135 return common.Hash{}, err 136 } 137 if (value != common.Hash{}) { 138 self.storage[key] = value 139 } 140 } 141 142 return value, nil 143 } 144 145 // SetState sets the storage value at the given address 146 func (self *StateObject) SetState(k, value common.Hash) { 147 self.storage[k] = value 148 self.dirty = true 149 } 150 151 // AddBalance adds the given amount to the account balance 152 func (c *StateObject) AddBalance(amount *big.Int) { 153 c.SetBalance(new(big.Int).Add(c.balance, amount)) 154 } 155 156 // SubBalance subtracts the given amount from the account balance 157 func (c *StateObject) SubBalance(amount *big.Int) { 158 c.SetBalance(new(big.Int).Sub(c.balance, amount)) 159 } 160 161 // SetBalance sets the account balance to the given amount 162 func (c *StateObject) SetBalance(amount *big.Int) { 163 c.balance = amount 164 c.dirty = true 165 } 166 167 // ReturnGas returns the gas back to the origin. Used by the Virtual machine or Closures 168 func (c *StateObject) ReturnGas(gas *big.Int) {} 169 170 // Copy creates a copy of the state object 171 func (self *StateObject) Copy() *StateObject { 172 stateObject := NewStateObject(self.Address(), self.odr) 173 stateObject.balance.Set(self.balance) 174 stateObject.codeHash = common.CopyBytes(self.codeHash) 175 stateObject.nonce = self.nonce 176 stateObject.trie = self.trie 177 stateObject.code = self.code 178 stateObject.storage = self.storage.Copy() 179 stateObject.remove = self.remove 180 stateObject.dirty = self.dirty 181 stateObject.deleted = self.deleted 182 183 return stateObject 184 } 185 186 // 187 // Attribute accessors 188 // 189 190 // empty returns whether the account is considered empty. 191 func (self *StateObject) empty() bool { 192 return self.nonce == 0 && self.balance.Sign() == 0 && bytes.Equal(self.codeHash, emptyCodeHash) 193 } 194 195 // Balance returns the account balance 196 func (self *StateObject) Balance() *big.Int { 197 return self.balance 198 } 199 200 // Address returns the address of the contract/account 201 func (self *StateObject) Address() common.Address { 202 return self.address 203 } 204 205 // Code returns the contract code 206 func (self *StateObject) Code() []byte { 207 return self.code 208 } 209 210 // SetCode sets the contract code 211 func (self *StateObject) SetCode(hash common.Hash, code []byte) { 212 self.code = code 213 self.codeHash = hash[:] 214 self.dirty = true 215 } 216 217 // SetNonce sets the account nonce 218 func (self *StateObject) SetNonce(nonce uint64) { 219 self.nonce = nonce 220 self.dirty = true 221 } 222 223 // Nonce returns the account nonce 224 func (self *StateObject) Nonce() uint64 { 225 return self.nonce 226 } 227 228 // ForEachStorage calls a callback function for every key/value pair found 229 // in the local storage cache. Note that unlike core/state.StateObject, 230 // light.StateObject only returns cached values and doesn't download the 231 // entire storage tree. 232 func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) { 233 for h, v := range self.storage { 234 cb(h, v) 235 } 236 } 237 238 // Never called, but must be present to allow StateObject to be used 239 // as a vm.Account interface that also satisfies the vm.ContractRef 240 // interface. Interfaces are awesome. 241 func (self *StateObject) Value() *big.Int { 242 panic("Value on StateObject should never be called") 243 } 244 245 // Encoding 246 247 type extStateObject struct { 248 Nonce uint64 249 Balance *big.Int 250 Root common.Hash 251 CodeHash []byte 252 } 253 254 // DecodeObject decodes an RLP-encoded state object. 255 func DecodeObject(ctx context.Context, stateID *TrieID, address common.Address, odr OdrBackend, data []byte) (*StateObject, error) { 256 var ( 257 obj = &StateObject{address: address, odr: odr, storage: make(Storage)} 258 ext extStateObject 259 err error 260 ) 261 if err = rlp.DecodeBytes(data, &ext); err != nil { 262 return nil, err 263 } 264 trieID := StorageTrieID(stateID, address, ext.Root) 265 obj.trie = NewLightTrie(trieID, odr, true) 266 if !bytes.Equal(ext.CodeHash, emptyCodeHash) { 267 if obj.code, err = retrieveContractCode(ctx, obj.odr, trieID, common.BytesToHash(ext.CodeHash)); err != nil { 268 return nil, fmt.Errorf("can't find code for hash %x: %v", ext.CodeHash, err) 269 } 270 } 271 obj.nonce = ext.Nonce 272 obj.balance = ext.Balance 273 obj.codeHash = ext.CodeHash 274 return obj, nil 275 }