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