1 // Aleth: Ethereum C++ client, tools and libraries. 2 // Copyright 2014-2019 Aleth Authors. 3 // Licensed under the GNU General Public License, Version 3. 4 5 6 #pragma once 7 8 #include <libdevcore/Common.h> 9 #include <libdevcore/SHA3.h> 10 #include <libdevcore/TrieCommon.h> 11 #include <libethcore/Common.h> 12 13 #include <boost/filesystem/path.hpp> 14 15 namespace dev 16 { 17 class OverlayDB; 18 19 namespace eth 20 { 21 22 /** 23 * Models the state of a single Ethereum account. 24 * Used to cache a portion of the full Ethereum state. State keeps a mapping of Address's to Accounts. 25 * 26 * Aside from storing the nonce and balance, the account may also be "dead" (where isAlive() returns false). 27 * This allows State to explicitly store the notion of a deleted account in it's cache. kill() can be used 28 * for this. 29 * 30 * For the account's storage, the class operates a cache. baseRoot() specifies the base state of the storage 31 * given as the Trie root to be looked up in the state database. Alterations beyond this base are specified 32 * in the overlay, stored in this class and retrieved with storageOverlay(). setStorage allows the overlay 33 * to be altered. 34 * 35 * The constructor allows you to create an one of a number of "types" of accounts. The default constructor 36 * makes a dead account (this is ignored by State when writing out the Trie). Another three allow a basic 37 * or contract account to be specified along with an initial balance. The fina two allow either a basic or 38 * a contract account to be created with arbitrary values. 39 */ 40 class Account 41 { 42 public: 43 /// Changedness of account to create. 44 enum Changedness 45 { 46 /// Account starts as though it has been changed. 47 Changed, 48 /// Account starts as though it has not been changed. 49 Unchanged 50 }; 51 52 /// Construct a dead Account. Account()53 Account() {} 54 55 /// Construct an alive Account, with given endowment, for either a normal (non-contract) account 56 /// or for a contract account in the conception phase, where the code is not yet known. m_isAlive(true)57 Account(u256 _nonce, u256 _balance, Changedness _c = Changed): m_isAlive(true), m_isUnchanged(_c == Unchanged), m_nonce(_nonce), m_balance(_balance) {} 58 59 /// Explicit constructor for wierd cases of construction or a contract account. Account(u256 const & _nonce,u256 const & _balance,h256 const & _contractRoot,h256 const & _codeHash,u256 const & _version,Changedness _c)60 Account(u256 const& _nonce, u256 const& _balance, h256 const& _contractRoot, 61 h256 const& _codeHash, u256 const& _version, Changedness _c) 62 : m_isAlive(true), 63 m_isUnchanged(_c == Unchanged), 64 m_nonce(_nonce), 65 m_balance(_balance), 66 m_storageRoot(_contractRoot), 67 m_codeHash(_codeHash), 68 m_version(_version) 69 { 70 assert(_contractRoot); 71 } 72 73 74 /// Kill this account. Useful for the SELFDESTRUCT instruction. 75 /// Following this call, isAlive() returns false. kill()76 void kill() 77 { 78 m_isAlive = false; 79 m_storageOverlay.clear(); 80 m_storageOriginal.clear(); 81 m_codeHash = EmptySHA3; 82 m_storageRoot = EmptyTrie; 83 m_balance = 0; 84 m_nonce = 0; 85 m_version = 0; 86 changed(); 87 } 88 89 /// @returns true iff this object represents an account in the state. 90 /// Returns false if this object represents an account that should no longer exist in the trie 91 /// (an account that never existed or was selfdestructed). isAlive()92 bool isAlive() const { return m_isAlive; } 93 94 /// @returns true if the account is unchanged from creation. isDirty()95 bool isDirty() const { return !m_isUnchanged; } 96 untouch()97 void untouch() { m_isUnchanged = true; } 98 99 /// @returns true if the nonce, balance and code is zero / empty. Code is considered empty 100 /// during creation phase. isEmpty()101 bool isEmpty() const { return nonce() == 0 && balance() == 0 && codeHash() == EmptySHA3; } 102 103 /// @returns the balance of this account. balance()104 u256 const& balance() const { return m_balance; } 105 106 /// Increments the balance of this account by the given amount. addBalance(u256 _value)107 void addBalance(u256 _value) { m_balance += _value; changed(); } 108 109 /// @returns the nonce of the account. nonce()110 u256 nonce() const { return m_nonce; } 111 112 /// Increment the nonce of the account by one. incNonce()113 void incNonce() { ++m_nonce; changed(); } 114 115 /// Set nonce to a new value. This is used when reverting changes made to 116 /// the account. setNonce(u256 const & _nonce)117 void setNonce(u256 const& _nonce) { m_nonce = _nonce; changed(); } 118 119 /// @returns the root of the trie (whose nodes are stored in the state db externally to this class) 120 /// which encodes the base-state of the account's storage (upon which the storage is overlaid). baseRoot()121 h256 baseRoot() const { assert(m_storageRoot); return m_storageRoot; } 122 123 /// @returns account's storage value corresponding to the @_key 124 /// taking into account overlayed modifications storageValue(u256 const & _key,OverlayDB const & _db)125 u256 storageValue(u256 const& _key, OverlayDB const& _db) const 126 { 127 auto mit = m_storageOverlay.find(_key); 128 if (mit != m_storageOverlay.end()) 129 return mit->second; 130 131 return originalStorageValue(_key, _db); 132 } 133 134 /// @returns account's original storage value corresponding to the @_key 135 /// not taking into account overlayed modifications 136 u256 originalStorageValue(u256 const& _key, OverlayDB const& _db) const; 137 138 /// @returns the storage overlay as a simple hash map. storageOverlay()139 std::unordered_map<u256, u256> const& storageOverlay() const { return m_storageOverlay; } 140 141 /// Set a key/value pair in the account's storage. This actually goes into the overlay, for committing 142 /// to the trie later. setStorage(u256 _p,u256 _v)143 void setStorage(u256 _p, u256 _v) { m_storageOverlay[_p] = _v; changed(); } 144 145 /// Empty the storage. Used when a contract is overwritten. clearStorage()146 void clearStorage() 147 { 148 m_storageOverlay.clear(); 149 m_storageOriginal.clear(); 150 m_storageRoot = EmptyTrie; 151 changed(); 152 } 153 154 /// Set the storage root. Used when clearStorage() is reverted. setStorageRoot(h256 const & _root)155 void setStorageRoot(h256 const& _root) 156 { 157 m_storageOverlay.clear(); 158 m_storageOriginal.clear(); 159 m_storageRoot = _root; 160 changed(); 161 } 162 163 /// @returns the hash of the account's code. codeHash()164 h256 codeHash() const { return m_codeHash; } 165 hasNewCode()166 bool hasNewCode() const { return m_hasNewCode; } 167 168 /// Sets the code of the account. Used by "create" messages. 169 void setCode(bytes&& _code, u256 const& _version); 170 171 /// Reset the code set by previous setCode 172 void resetCode(); 173 174 /// Specify to the object what the actual code is for the account. @a _code must have a SHA3 175 /// equal to codeHash(). noteCode(bytesConstRef _code)176 void noteCode(bytesConstRef _code) { assert(sha3(_code) == m_codeHash); m_codeCache = _code.toBytes(); } 177 178 /// @returns the account's code. code()179 bytes const& code() const { return m_codeCache; } 180 version()181 u256 version() const { return m_version; } 182 183 private: 184 /// Note that we've altered the account. changed()185 void changed() { m_isUnchanged = false; } 186 187 /// Is this account existant? If not, it represents a deleted account. 188 bool m_isAlive = false; 189 190 /// True if we've not made any alteration to the account having been given it's properties directly. 191 bool m_isUnchanged = false; 192 193 /// True if new code was deployed to the account 194 bool m_hasNewCode = false; 195 196 /// Account's nonce. 197 u256 m_nonce; 198 199 /// Account's balance. 200 u256 m_balance = 0; 201 202 /// The base storage root. Used with the state DB to give a base to the storage. m_storageOverlay is 203 /// overlaid on this and takes precedence for all values set. 204 h256 m_storageRoot = EmptyTrie; 205 206 /** If c_contractConceptionCodeHash then we're in the limbo where we're running the initialisation code. 207 * We expect a setCode() at some point later. 208 * If EmptySHA3, then m_code, which should be empty, is valid. 209 * If anything else, then m_code is valid iff it's not empty, otherwise, State::ensureCached() needs to 210 * be called with the correct args. 211 */ 212 h256 m_codeHash = EmptySHA3; 213 214 /// Account's version 215 u256 m_version = 0; 216 217 /// The map with is overlaid onto whatever storage is implied by the m_storageRoot in the trie. 218 mutable std::unordered_map<u256, u256> m_storageOverlay; 219 220 /// The cache of unmodifed storage items 221 mutable std::unordered_map<u256, u256> m_storageOriginal; 222 223 /// The associated code for this account. The SHA3 of this should be equal to m_codeHash unless 224 /// m_codeHash equals c_contractConceptionCodeHash. 225 bytes m_codeCache; 226 227 /// Value for m_codeHash when this account is having its code determined. 228 static const h256 c_contractConceptionCodeHash; 229 }; 230 231 class AccountMask 232 { 233 public: 234 AccountMask(bool _all = false): m_hasBalance(_all)235 m_hasBalance(_all), 236 m_hasNonce(_all), 237 m_hasCode(_all), 238 m_hasStorage(_all) 239 {} 240 241 AccountMask( 242 bool _hasBalance, 243 bool _hasNonce, 244 bool _hasCode, 245 bool _hasStorage, 246 bool _shouldNotExist = false 247 ): m_hasBalance(_hasBalance)248 m_hasBalance(_hasBalance), 249 m_hasNonce(_hasNonce), 250 m_hasCode(_hasCode), 251 m_hasStorage(_hasStorage), 252 m_shouldNotExist(_shouldNotExist) 253 {} 254 allSet()255 bool allSet() const { return m_hasBalance && m_hasNonce && m_hasCode && m_hasStorage; } hasBalance()256 bool hasBalance() const { return m_hasBalance; } hasNonce()257 bool hasNonce() const { return m_hasNonce; } hasCode()258 bool hasCode() const { return m_hasCode; } hasStorage()259 bool hasStorage() const { return m_hasStorage; } shouldExist()260 bool shouldExist() const { return !m_shouldNotExist; } 261 262 private: 263 bool m_hasBalance; 264 bool m_hasNonce; 265 bool m_hasCode; 266 bool m_hasStorage; 267 bool m_shouldNotExist = false; 268 }; 269 270 using AccountMap = std::unordered_map<Address, Account>; 271 using AccountMaskMap = std::unordered_map<Address, AccountMask>; 272 273 AccountMap jsonToAccountMap(std::string const& _json, u256 const& _defaultNonce = 0, 274 AccountMaskMap* o_mask = nullptr, const boost::filesystem::path& _configPath = {}); 275 } 276 } 277