From 14f80389a58e57449ee9ec5215ac98eb3110a7a0 Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Thu, 23 Oct 2014 18:44:38 +0200 Subject: [PATCH 1/6] fixed bug in name of error_info typedef --- libdevcore/Exceptions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/Exceptions.h b/libdevcore/Exceptions.h index 74315ff26..932276d01 100644 --- a/libdevcore/Exceptions.h +++ b/libdevcore/Exceptions.h @@ -44,6 +44,6 @@ struct FileError: virtual Exception {}; // error information to be added to exceptions typedef boost::error_info errinfo_invalidSymbol; -typedef boost::error_info errinfo_wrongAddress; +typedef boost::error_info errinfo_wrongAddress; typedef boost::error_info errinfo_comment; } From 9987248907d67d68008d5d0116d1a2c41077d353 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 30 Oct 2014 13:47:28 +0100 Subject: [PATCH 2/6] Fix for Trie roots. AddressState -> Account. --- libethereum/{AddressState.cpp => Account.cpp} | 4 ++-- libethereum/{AddressState.h => Account.h} | 18 +++++++-------- libethereum/All.h | 2 +- libethereum/BlockChain.cpp | 6 ++--- libethereum/BlockChain.h | 4 ++-- libethereum/Executive.cpp | 2 +- libethereum/ExtVM.h | 2 +- libethereum/State.cpp | 22 +++++++++---------- libethereum/State.h | 8 +++---- test/vm.cpp | 2 +- 10 files changed, 35 insertions(+), 35 deletions(-) rename libethereum/{AddressState.cpp => Account.cpp} (94%) rename libethereum/{AddressState.h => Account.h} (81%) diff --git a/libethereum/AddressState.cpp b/libethereum/Account.cpp similarity index 94% rename from libethereum/AddressState.cpp rename to libethereum/Account.cpp index 268440314..dcd97f037 100644 --- a/libethereum/AddressState.cpp +++ b/libethereum/Account.cpp @@ -14,12 +14,12 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file AddressState.cpp +/** @file Account.cpp * @author Gav Wood * @date 2014 */ -#include "AddressState.h" +#include "Account.h" #include using namespace std; using namespace dev; diff --git a/libethereum/AddressState.h b/libethereum/Account.h similarity index 81% rename from libethereum/AddressState.h rename to libethereum/Account.h index 8b4505909..00344a9e6 100644 --- a/libethereum/AddressState.h +++ b/libethereum/Account.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file AddressState.h +/** @file Account.h * @author Gav Wood * @date 2014 */ @@ -33,20 +33,20 @@ namespace eth // TODO: Document fully. -class AddressState +class Account { public: enum NewAccountType { NormalCreation, ContractConception }; - /// Construct a dead AddressState. - AddressState() {} - /// Construct an alive AddressState, with given endowment, for either a normal (non-contract) account or for a contract account in the + /// Construct a dead Account. + Account() {} + /// Construct an alive Account, with given endowment, for either a normal (non-contract) account or for a contract account in the /// conception phase, where the code is not yet known. - AddressState(u256 _balance, NewAccountType _t): m_isAlive(true), m_balance(_balance), m_codeHash(_t == NormalCreation ? h256() : EmptySHA3) {} + Account(u256 _balance, NewAccountType _t): m_isAlive(true), m_balance(_balance), m_codeHash(_t == NormalCreation ? h256() : EmptySHA3) {} /// Explicit constructor for wierd cases of construction of a normal account. - AddressState(u256 _nonce, u256 _balance): m_isAlive(true), m_nonce(_nonce), m_balance(_balance) {} + Account(u256 _nonce, u256 _balance): m_isAlive(true), m_nonce(_nonce), m_balance(_balance) {} /// Explicit constructor for wierd cases of construction or a contract account. - AddressState(u256 _nonce, u256 _balance, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_nonce(_nonce), m_balance(_balance), m_storageRoot(_contractRoot), m_codeHash(_codeHash) {} + Account(u256 _nonce, u256 _balance, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_nonce(_nonce), m_balance(_balance), m_storageRoot(_contractRoot), m_codeHash(_codeHash) { assert(_contractRoot); } void kill() { m_isAlive = false; m_storageOverlay.clear(); m_codeHash = EmptySHA3; m_storageRoot = EmptyTrie; m_balance = 0; m_nonce = 0; } bool isAlive() const { return m_isAlive; } @@ -59,7 +59,7 @@ public: u256 const& nonce() const { return m_nonce; } void incNonce() { m_nonce++; } - h256 baseRoot() const { return m_storageRoot; } + h256 baseRoot() const { assert(m_storageRoot); return m_storageRoot; } std::map const& storage() const { return m_storageOverlay; } void setStorage(u256 _p, u256 _v) { m_storageOverlay[_p] = _v; } diff --git a/libethereum/All.h b/libethereum/All.h index ba22640e7..11e0d55f3 100644 --- a/libethereum/All.h +++ b/libethereum/All.h @@ -1,6 +1,6 @@ #pragma once -#include "AddressState.h" +#include "Account.h" #include "BlockChain.h" #include "Client.h" #include "Defaults.h" diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 9672f722c..710f17214 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -52,9 +52,9 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, BlockChain const& _bc) return _out; } -std::map const& dev::eth::genesisState() +std::map const& dev::eth::genesisState() { - static std::map s_ret; + static std::map s_ret; if (s_ret.empty()) // Initialise. for (auto i: vector({ @@ -67,7 +67,7 @@ std::map const& dev::eth::genesisState() "6c386a4b26f73c802f34673f7248bb118f97424a", "e4157b34ea9615cfbde6b4fda419828124b70c78" })) - s_ret[Address(fromHex(i))] = AddressState(u256(1) << 200, AddressState::NormalCreation); + s_ret[Address(fromHex(i))] = Account(u256(1) << 200, Account::NormalCreation); return s_ret; } diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 6c96082a5..30f5633c1 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -33,7 +33,7 @@ #include #include #include "BlockDetails.h" -#include "AddressState.h" +#include "Account.h" #include "BlockQueue.h" namespace ldb = leveldb; @@ -57,7 +57,7 @@ struct BlockChainChat: public LogChannel { static const char* name() { return "- struct BlockChainNote: public LogChannel { static const char* name() { return "=B="; } static const int verbosity = 4; }; // TODO: Move all this Genesis stuff into Genesis.h/.cpp -std::map const& genesisState(); +std::map const& genesisState(); ldb::Slice toSlice(h256 _h, unsigned _sub = 0); diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 5a983b66e..885ab5535 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -138,7 +138,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g m_newAddress = right160(sha3(rlpList(_sender, m_s.transactionsFrom(_sender) - 1))); // Set up new account... - m_s.m_cache[m_newAddress] = AddressState(0, m_s.balance(m_newAddress) + _endowment, h256(), h256()); + m_s.m_cache[m_newAddress] = Account(m_s.balance(m_newAddress) + _endowment, Account::ContractConception); // Execute _init. m_vm = new VM(_gas); diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index 59b6eb2ab..cf80b2352 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -102,7 +102,7 @@ public: private: State& m_s; ///< A reference to the base state. - std::map m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution. + std::map m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution. Manifest* m_ms; }; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 183b2b8de..a438622fa 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -224,7 +224,7 @@ Address State::nextActiveAddress(Address _a) const // TODO: repot struct CachedAddressState { - CachedAddressState(std::string const& _rlp, AddressState const* _s, OverlayDB const* _o): rS(_rlp), r(rS), s(_s), o(_o) {} + CachedAddressState(std::string const& _rlp, Account const* _s, OverlayDB const* _o): rS(_rlp), r(rS), s(_s), o(_o) {} bool exists() const { @@ -300,7 +300,7 @@ struct CachedAddressState std::string rS; RLP r; - AddressState const* s; + Account const* s; OverlayDB const* o; }; @@ -346,7 +346,7 @@ void State::ensureCached(Address _a, bool _requireCode, bool _forceCreate) const ensureCached(m_cache, _a, _requireCode, _forceCreate); } -void State::ensureCached(std::map& _cache, Address _a, bool _requireCode, bool _forceCreate) const +void State::ensureCached(std::map& _cache, Address _a, bool _requireCode, bool _forceCreate) const { auto it = _cache.find(_a); if (it == _cache.end()) @@ -356,11 +356,11 @@ void State::ensureCached(std::map& _cache, Address _a, bo if (stateBack.empty() && !_forceCreate) return; RLP state(stateBack); - AddressState s; + Account s; if (state.isNull()) - s = AddressState(0, AddressState::NormalCreation); + s = Account(0, Account::NormalCreation); else - s = AddressState(state[0].toInt(), state[1].toInt(), state[2].toHash(), state[3].toHash()); + s = Account(state[0].toInt(), state[1].toInt(), state[2].toHash(), state[3].toHash()); bool ok; tie(it, ok) = _cache.insert(make_pair(_a, s)); } @@ -965,7 +965,7 @@ void State::noteSending(Address _id) { cwarn << "Sending from non-existant account. How did it pay!?!"; // this is impossible. but we'll continue regardless... - m_cache[_id] = AddressState(1, 0); + m_cache[_id] = Account(1, 0); } else it->second.incNonce(); @@ -976,7 +976,7 @@ void State::addBalance(Address _id, u256 _amount) ensureCached(_id, false, false); auto it = m_cache.find(_id); if (it == m_cache.end()) - m_cache[_id] = AddressState(_amount, AddressState::NormalCreation); + m_cache[_id] = Account(_amount, Account::NormalCreation); else it->second.addBalance(_amount); } @@ -1057,7 +1057,7 @@ h256 State::storageRoot(Address _id) const RLP r(s); return r[2].toHash(); } - return h256(); + return EmptyTrie; } bytes const& State::code(Address _contract) const @@ -1267,7 +1267,7 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, Address newAddress = right160(sha3(rlpList(_sender, transactionsFrom(_sender) - 1))); // Set up new account... - m_cache[newAddress] = AddressState(balance(newAddress) + _endowment, AddressState::ContractConception); + m_cache[newAddress] = Account(balance(newAddress) + _endowment, Account::ContractConception); // Execute init code. VM vm(*_gas); @@ -1366,7 +1366,7 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, State const& _s) for (auto i: d) { auto it = _s.m_cache.find(i); - AddressState* cache = it != _s.m_cache.end() ? &it->second : nullptr; + Account* cache = it != _s.m_cache.end() ? &it->second : nullptr; string rlpString = dtr.count(i) ? trie.at(i) : ""; RLP r(rlpString); assert(cache || r); diff --git a/libethereum/State.h b/libethereum/State.h index a90812880..a8c23de84 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -33,7 +33,7 @@ #include #include #include "TransactionQueue.h" -#include "AddressState.h" +#include "Account.h" #include "Transaction.h" #include "Executive.h" #include "AccountDiff.h" @@ -299,7 +299,7 @@ private: void ensureCached(Address _a, bool _requireCode, bool _forceCreate) const; /// Retrieve all information about a given address into a cache. - void ensureCached(std::map& _cache, Address _a, bool _requireCode, bool _forceCreate) const; + void ensureCached(std::map& _cache, Address _a, bool _requireCode, bool _forceCreate) const; /// Commit all changes waiting in the address cache to the DB. void commit(); @@ -340,7 +340,7 @@ private: std::set m_transactionSet; ///< The set of transaction hashes that we've included in the state. OverlayDB m_lastTx; - mutable std::map m_cache; ///< Our address cache. This stores the states of each address that has (or at least might have) been changed. + mutable std::map m_cache; ///< Our address cache. This stores the states of each address that has (or at least might have) been changed. BlockInfo m_previousBlock; ///< The previous block's information. BlockInfo m_currentBlock; ///< The current block's information. @@ -365,7 +365,7 @@ private: std::ostream& operator<<(std::ostream& _out, State const& _s); template -void commit(std::map const& _cache, DB& _db, TrieDB& _state) +void commit(std::map const& _cache, DB& _db, TrieDB& _state) { for (auto const& i: _cache) if (!i.second.isAlive()) diff --git a/test/vm.cpp b/test/vm.cpp index 76ed41a44..617cb95c7 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -471,7 +471,7 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end } // Set up new account... - m_cache[_newAddress] = AddressState(0, balance(_newAddress) + _endowment, h256(), h256()); + m_cache[_newAddress] = Account(0, balance(_newAddress) + _endowment, h256(), h256()); // Execute init code. VM vm(*_gas); From 8b54fc0db0e4795c6e989f4416b6c5385c04f539 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 30 Oct 2014 14:38:19 +0100 Subject: [PATCH 3/6] Full documentation for Account class. --- libethereum/Account.cpp | 2 +- libethereum/Account.h | 112 +++++++++++++++++++++++++++++++++++----- 2 files changed, 101 insertions(+), 13 deletions(-) diff --git a/libethereum/Account.cpp b/libethereum/Account.cpp index dcd97f037..74b6ebe7b 100644 --- a/libethereum/Account.cpp +++ b/libethereum/Account.cpp @@ -26,5 +26,5 @@ using namespace dev; using namespace dev::eth; #pragma GCC diagnostic ignored "-Wunused-variable" -namespace { char dummy; }; +const h256 Account::c_contractConceptionCodeHash; diff --git a/libethereum/Account.h b/libethereum/Account.h index 00344a9e6..154bb90d0 100644 --- a/libethereum/Account.h +++ b/libethereum/Account.h @@ -31,62 +31,150 @@ namespace dev namespace eth { -// TODO: Document fully. - +/** + * Models the state of a single Ethereum account. + * Used to cache a portion of the full Ethereum state. State keeps a mapping of Address's to Accounts. + * + * Aside from storing the nonce and balance, the account may also be "dead" (where isAlive() returns false). + * This allows State to explicitly store the notion of a deleted account in it's cache. kill() can be used + * for this. + * + * For the account's storage, the class operates a cache. baseRoot() specifies the base state of the storage + * given as the Trie root to be looked up in the state database. Alterations beyond this base are specified + * in the overlay, stored in this class and retrieved with storageOverlay(). setStorage allows the overlay + * to be altered. + * + * The code handling explicitly supports a two-stage commit model needed for contract-creation. When creating + * a contract (running the initialisation code), the code of the account is considered empty. The attribute + * of emptiness can be retrieved with codeBearing(). After initialisation one must set the code accordingly; + * the code of the Account can be set with setCode(). To validate a setCode() call, this class records the + * state of being in contract-creation (and thus in a state where setCode may validly be called). It can be + * determined through isFreshCode(). + * + * The code can be retrieved through code(), and its hash through codeHash(). codeHash() is only valid when + * the account is not in the contract-creation phase (i.e. when isFreshCode() returns false). This class + * supports populating code on-demand from the state database. To determine if the code has been prepopulated + * call codeCacheValid(). To populate the code, look it up with codeHash() and populate with noteCode(). + * + * @todo: need to make a noteCodeCommitted(). + * + * The constructor allows you to create an one of a number of "types" of accounts. The default constructor + * makes a dead account (this is ignored by State when writing out the Trie). Another three allow a basic + * or contract account to be specified along with an initial balance. The fina two allow either a basic or + * a contract account to be created with arbitrary values. + * + * Code does + */ class Account { public: - enum NewAccountType { NormalCreation, ContractConception }; + /// Type of account to create. + enum NewAccountType + { + NormalCreation, ///< Normal account. + ContractConception ///< Contract account - we place this object into the contract-creation state (and as such we expect setCode(), but codeHash() won't work). + }; /// Construct a dead Account. Account() {} + /// Construct an alive Account, with given endowment, for either a normal (non-contract) account or for a contract account in the /// conception phase, where the code is not yet known. - Account(u256 _balance, NewAccountType _t): m_isAlive(true), m_balance(_balance), m_codeHash(_t == NormalCreation ? h256() : EmptySHA3) {} + Account(u256 _balance, NewAccountType _t): m_isAlive(true), m_balance(_balance), m_codeHash(_t == NormalCreation ? c_contractConceptionCodeHash : EmptySHA3) {} /// Explicit constructor for wierd cases of construction of a normal account. Account(u256 _nonce, u256 _balance): m_isAlive(true), m_nonce(_nonce), m_balance(_balance) {} + /// Explicit constructor for wierd cases of construction or a contract account. Account(u256 _nonce, u256 _balance, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_nonce(_nonce), m_balance(_balance), m_storageRoot(_contractRoot), m_codeHash(_codeHash) { assert(_contractRoot); } + + /// Kill this account. Useful for the suicide opcode. Following this call, isAlive() returns false. void kill() { m_isAlive = false; m_storageOverlay.clear(); m_codeHash = EmptySHA3; m_storageRoot = EmptyTrie; m_balance = 0; m_nonce = 0; } + + /// @returns true iff this object represents an account in the state. Returns false if this object represents an account + /// that should no longer exist in the trie (an account that never existed or was suicided). bool isAlive() const { return m_isAlive; } + + /// @returns the balance of this account. Can be altered in place. u256& balance() { return m_balance; } + + /// @returns the balance of this account. u256 const& balance() const { return m_balance; } + + /// Increments the balance of this account by the given amount. It's a bigint, so can be negative. void addBalance(bigint _i) { m_balance = (u256)((bigint)m_balance + _i); } + /// @returns the nonce of the account. Can be altered in place. u256& nonce() { return m_nonce; } + + /// @returns the nonce of the account. u256 const& nonce() const { return m_nonce; } + + /// Increment the nonce of the account by one. void incNonce() { m_nonce++; } + + /// @returns the root of the trie (whose nodes are stored in the state db externally to this class) which encodes the + /// base-state of the account's storage (upon which the storage is overlaid). h256 baseRoot() const { assert(m_storageRoot); return m_storageRoot; } - std::map const& storage() const { return m_storageOverlay; } + + /// @returns the storage overlay as a simple map. + std::map const& storageOverlay() const { return m_storageOverlay; } + + /// Set a key/value pair in the account's storage. This actually goes into the overlay, for committing to the trie + /// later. void setStorage(u256 _p, u256 _v) { m_storageOverlay[_p] = _v; } - bool isFreshCode() const { return !m_codeHash; } + + /// @returns true if we are in the contract-conception state and setCode is valid to call. + bool isFreshCode() const { return m_codeHash == c_contractConceptionCodeHash; } + + /// @returns true if we are either in the contract-conception state or if the account's code is not empty. bool codeBearing() const { return m_codeHash != EmptySHA3; } - bool codeCacheValid() const { return m_codeHash == EmptySHA3 || !m_codeHash || m_codeCache.size(); } - h256 codeHash() const { assert(m_codeHash); return m_codeHash; } - bytes const& code() const { assert(m_codeHash == EmptySHA3 || !m_codeHash || m_codeCache.size()); return m_codeCache; } - void setCode(bytesConstRef _code) { assert(!m_codeHash); m_codeCache = _code.toBytes(); } + + /// @returns the hash of the account's code. Must only be called when isFreshCode() returns false. + h256 codeHash() const { assert(!isFreshCode()); return m_codeHash; } + + /// Sets the code of the account. Must only be called when isFreshCode() returns true. + void setCode(bytesConstRef _code) { assert(isFreshCode()); m_codeCache = _code.toBytes(); } + + /// @returns true if the account's code is available through code(). + bool codeCacheValid() const { return m_codeHash == EmptySHA3 || m_codeHash == c_contractConceptionCodeHash || m_codeCache.size(); } + + /// Specify to the object what the actual code is for the account. @a _code must have a SHA3 equal to codeHash() and + /// must only be called when isFreshCode() returns false. void noteCode(bytesConstRef _code) { assert(sha3(_code) == m_codeHash); m_codeCache = _code.toBytes(); } + /// @returns the account's code. Must only be called when codeCacheValid returns true. + bytes const& code() const { assert(codeCacheValid()); return m_codeCache; } + private: + /// Is this account existant? If not, it represents a deleted account. bool m_isAlive = false; + + /// Account's nonce. u256 m_nonce = 0; + + /// Account's balance. u256 m_balance = 0; /// The base storage root. Used with the state DB to give a base to the storage. m_storageOverlay is overlaid on this and takes precedence for all values set. h256 m_storageRoot = EmptyTrie; - /// If 0 then we're in the limbo where we're running the initialisation code. We expect a setCode() at some point later. + /// If c_contractConceptionCodeHash then we're in the limbo where we're running the initialisation code. We expect a setCode() at some point later. /// If EmptySHA3, then m_code, which should be empty, is valid. /// If anything else, then m_code is valid iff it's not empty, otherwise, State::ensureCached() needs to be called with the correct args. h256 m_codeHash = EmptySHA3; - // TODO: change to unordered_map. + /// The map with is overlaid onto whatever storage is implied by the m_storageRoot in the trie. std::map m_storageOverlay; + + /// The associated code for this account. The SHA3 of this should be equal to m_codeHash unless m_codeHash equals c_contractConceptionCodeHash. bytes m_codeCache; + + /// Value for m_codeHash when this account is having its code determined. + static const h256 c_contractConceptionCodeHash; }; } From 1d0e7ee10a8f2e35538b4108591a1f75a98b8cc0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 30 Oct 2014 14:41:22 +0100 Subject: [PATCH 4/6] Minor comments. --- libethereum/Account.h | 47 ++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/libethereum/Account.h b/libethereum/Account.h index 154bb90d0..2e8bbeb88 100644 --- a/libethereum/Account.h +++ b/libethereum/Account.h @@ -62,8 +62,6 @@ namespace eth * makes a dead account (this is ignored by State when writing out the Trie). Another three allow a basic * or contract account to be specified along with an initial balance. The fina two allow either a basic or * a contract account to be created with arbitrary values. - * - * Code does */ class Account { @@ -71,14 +69,18 @@ public: /// Type of account to create. enum NewAccountType { - NormalCreation, ///< Normal account. - ContractConception ///< Contract account - we place this object into the contract-creation state (and as such we expect setCode(), but codeHash() won't work). + /// Normal account. + NormalCreation, + /// Contract account - we place this object into the contract-creation state (and as such we + /// expect setCode(), but codeHash() won't work). + ContractConception }; /// Construct a dead Account. Account() {} - /// Construct an alive Account, with given endowment, for either a normal (non-contract) account or for a contract account in the + /// Construct an alive Account, with given endowment, for either a normal (non-contract) account or for a + /// contract account in the /// conception phase, where the code is not yet known. Account(u256 _balance, NewAccountType _t): m_isAlive(true), m_balance(_balance), m_codeHash(_t == NormalCreation ? c_contractConceptionCodeHash : EmptySHA3) {} /// Explicit constructor for wierd cases of construction of a normal account. @@ -91,8 +93,9 @@ public: /// Kill this account. Useful for the suicide opcode. Following this call, isAlive() returns false. void kill() { m_isAlive = false; m_storageOverlay.clear(); m_codeHash = EmptySHA3; m_storageRoot = EmptyTrie; m_balance = 0; m_nonce = 0; } - /// @returns true iff this object represents an account in the state. Returns false if this object represents an account - /// that should no longer exist in the trie (an account that never existed or was suicided). + /// @returns true iff this object represents an account in the state. Returns false if this object + /// represents an account that should no longer exist in the trie (an account that never existed or was + /// suicided). bool isAlive() const { return m_isAlive; } @@ -115,22 +118,23 @@ public: void incNonce() { m_nonce++; } - /// @returns the root of the trie (whose nodes are stored in the state db externally to this class) which encodes the - /// base-state of the account's storage (upon which the storage is overlaid). + /// @returns the root of the trie (whose nodes are stored in the state db externally to this class) + /// which encodes the base-state of the account's storage (upon which the storage is overlaid). h256 baseRoot() const { assert(m_storageRoot); return m_storageRoot; } /// @returns the storage overlay as a simple map. std::map const& storageOverlay() const { return m_storageOverlay; } - /// Set a key/value pair in the account's storage. This actually goes into the overlay, for committing to the trie - /// later. + /// Set a key/value pair in the account's storage. This actually goes into the overlay, for committing + /// to the trie later. void setStorage(u256 _p, u256 _v) { m_storageOverlay[_p] = _v; } /// @returns true if we are in the contract-conception state and setCode is valid to call. bool isFreshCode() const { return m_codeHash == c_contractConceptionCodeHash; } - /// @returns true if we are either in the contract-conception state or if the account's code is not empty. + /// @returns true if we are either in the contract-conception state or if the account's code is not + /// empty. bool codeBearing() const { return m_codeHash != EmptySHA3; } /// @returns the hash of the account's code. Must only be called when isFreshCode() returns false. @@ -142,8 +146,8 @@ public: /// @returns true if the account's code is available through code(). bool codeCacheValid() const { return m_codeHash == EmptySHA3 || m_codeHash == c_contractConceptionCodeHash || m_codeCache.size(); } - /// Specify to the object what the actual code is for the account. @a _code must have a SHA3 equal to codeHash() and - /// must only be called when isFreshCode() returns false. + /// Specify to the object what the actual code is for the account. @a _code must have a SHA3 equal to + /// codeHash() and must only be called when isFreshCode() returns false. void noteCode(bytesConstRef _code) { assert(sha3(_code) == m_codeHash); m_codeCache = _code.toBytes(); } /// @returns the account's code. Must only be called when codeCacheValid returns true. @@ -159,18 +163,23 @@ private: /// Account's balance. u256 m_balance = 0; - /// The base storage root. Used with the state DB to give a base to the storage. m_storageOverlay is overlaid on this and takes precedence for all values set. + /// The base storage root. Used with the state DB to give a base to the storage. m_storageOverlay is + /// overlaid on this and takes precedence for all values set. h256 m_storageRoot = EmptyTrie; - /// If c_contractConceptionCodeHash then we're in the limbo where we're running the initialisation code. We expect a setCode() at some point later. - /// If EmptySHA3, then m_code, which should be empty, is valid. - /// If anything else, then m_code is valid iff it's not empty, otherwise, State::ensureCached() needs to be called with the correct args. + /** If c_contractConceptionCodeHash then we're in the limbo where we're running the initialisation code. + * We expect a setCode() at some point later. + * If EmptySHA3, then m_code, which should be empty, is valid. + * If anything else, then m_code is valid iff it's not empty, otherwise, State::ensureCached() needs to + * be called with the correct args. + */ h256 m_codeHash = EmptySHA3; /// The map with is overlaid onto whatever storage is implied by the m_storageRoot in the trie. std::map m_storageOverlay; - /// The associated code for this account. The SHA3 of this should be equal to m_codeHash unless m_codeHash equals c_contractConceptionCodeHash. + /// The associated code for this account. The SHA3 of this should be equal to m_codeHash unless m_codeHash + /// equals c_contractConceptionCodeHash. bytes m_codeCache; /// Value for m_codeHash when this account is having its code determined. From 04e718b34ac0fed8beb395fd75e127ecaab75811 Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Fri, 31 Oct 2014 10:17:01 +0100 Subject: [PATCH 5/6] Renamed storageOverlay() to storage() in Account.h --- libethereum/Account.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libethereum/Account.h b/libethereum/Account.h index 2e8bbeb88..3a078408d 100644 --- a/libethereum/Account.h +++ b/libethereum/Account.h @@ -123,13 +123,12 @@ public: h256 baseRoot() const { assert(m_storageRoot); return m_storageRoot; } /// @returns the storage overlay as a simple map. - std::map const& storageOverlay() const { return m_storageOverlay; } + std::map const& storage() const { return m_storageOverlay; } /// Set a key/value pair in the account's storage. This actually goes into the overlay, for committing /// to the trie later. void setStorage(u256 _p, u256 _v) { m_storageOverlay[_p] = _v; } - /// @returns true if we are in the contract-conception state and setCode is valid to call. bool isFreshCode() const { return m_codeHash == c_contractConceptionCodeHash; } From 07e446d8daab985dacb5f6861243b94f49a81d2a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 31 Oct 2014 11:55:59 +0100 Subject: [PATCH 6/6] Rename storage() -> storageOverlay(). --- libethereum/Account.h | 2 +- libethereum/State.cpp | 10 +++++----- libethereum/State.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libethereum/Account.h b/libethereum/Account.h index 3a078408d..ce7004083 100644 --- a/libethereum/Account.h +++ b/libethereum/Account.h @@ -123,7 +123,7 @@ public: h256 baseRoot() const { assert(m_storageRoot); return m_storageRoot; } /// @returns the storage overlay as a simple map. - std::map const& storage() const { return m_storageOverlay; } + std::map const& storageOverlay() const { return m_storageOverlay; } /// Set a key/value pair in the account's storage. This actually goes into the overlay, for committing /// to the trie later. diff --git a/libethereum/State.cpp b/libethereum/State.cpp index a438622fa..cb8906dc3 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -259,7 +259,7 @@ struct CachedAddressState ret[j.first] = RLP(j.second).toInt(); } if (s) - for (auto const& j: s->storage()) + for (auto const& j: s->storageOverlay()) if ((!ret.count(j.first) && j.second) || (ret.count(j.first) && ret.at(j.first) != j.second)) ret[j.first] = j.second; return ret; @@ -1011,8 +1011,8 @@ u256 State::storage(Address _id, u256 _memory) const return 0; // See if it's in the account's storage cache. - auto mit = it->second.storage().find(_memory); - if (mit != it->second.storage().end()) + auto mit = it->second.storageOverlay().find(_memory); + if (mit != it->second.storageOverlay().end()) return mit->second; // Not in the storage cache - go to the DB. @@ -1040,7 +1040,7 @@ map State::storage(Address _id) const } // Then merge cached storage over the top. - for (auto const& i: it->second.storage()) + for (auto const& i: it->second.storageOverlay()) if (i.second) ret[i.first] = i.second; else @@ -1394,7 +1394,7 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, State const& _s) mem[j.first] = RLP(j.second).toInt(), back.insert(j.first); } if (cache) - for (auto const& j: cache->storage()) + for (auto const& j: cache->storageOverlay()) { if ((!mem.count(j.first) && j.second) || (mem.count(j.first) && mem.at(j.first) != j.second)) mem[j.first] = j.second, delta.insert(j.first); diff --git a/libethereum/State.h b/libethereum/State.h index 84371d62a..d966fb385 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -377,7 +377,7 @@ void commit(std::map const& _cache, DB& _db, TrieDB const& _cache, DB& _db, TrieDB storageDB(&_db, i.second.baseRoot()); - for (auto const& j: i.second.storage()) + for (auto const& j: i.second.storageOverlay()) if (j.second) storageDB.insert(j.first, rlp(j.second)); else