From 5f6e533169bcb050c93ad3757c4ab5b289bd30c7 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 23 Apr 2014 21:49:14 +0100 Subject: [PATCH] Accounts all the same "type". --- libethcore/FixedHash.cpp | 2 ++ libethcore/FixedHash.h | 2 ++ libethereum/AddressState.cpp | 4 +-- libethereum/AddressState.h | 43 ++++++++++++++++----------------- libethereum/State.cpp | 27 +++++++++------------ libethereum/State.h | 47 +++++++++++++++++++----------------- 6 files changed, 64 insertions(+), 61 deletions(-) diff --git a/libethcore/FixedHash.cpp b/libethcore/FixedHash.cpp index bcb9af804..bc23d22c8 100644 --- a/libethcore/FixedHash.cpp +++ b/libethcore/FixedHash.cpp @@ -25,6 +25,8 @@ using namespace std; using namespace eth; +h256 eth::EmptySHA3 = sha3(bytesConstRef()); + std::string eth::sha3(std::string const& _input, bool _hex) { if (!_hex) diff --git a/libethcore/FixedHash.h b/libethcore/FixedHash.h index ab5b7ac78..762f39090 100644 --- a/libethcore/FixedHash.h +++ b/libethcore/FixedHash.h @@ -212,6 +212,8 @@ inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef((bytes*)&_inpu /// Calculate SHA3-256 hash of the given input (presented as a binary-filled string), returning as a 256-bit hash. inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); } +extern h256 EmptySHA3; + } namespace std diff --git a/libethereum/AddressState.cpp b/libethereum/AddressState.cpp index 97000521f..156902db8 100644 --- a/libethereum/AddressState.cpp +++ b/libethereum/AddressState.cpp @@ -25,9 +25,9 @@ using namespace std; using namespace eth; AddressState::AddressState(u256 _balance, u256 _nonce, bytesConstRef _code): - m_type(AddressType::Contract), + m_isAlive(true), + m_isComplete(true), m_balance(_balance), m_nonce(_nonce), - m_isComplete(true), m_code(_code.toBytes()) {} diff --git a/libethereum/AddressState.h b/libethereum/AddressState.h index 9adbbb32c..fef7341d9 100644 --- a/libethereum/AddressState.h +++ b/libethereum/AddressState.h @@ -27,49 +27,48 @@ namespace eth { -enum class AddressType -{ - Dead, - Normal, - Contract -}; +// TODO: Don't pre-cache all of storage. class AddressState { public: - AddressState(): m_type(AddressType::Dead), m_balance(0), m_nonce(0), m_isComplete(false) {} - AddressState(u256 _balance, u256 _nonce, AddressType _type = AddressType::Normal): m_type(_type), m_balance(_balance), m_nonce(_nonce), m_isComplete(true) {} - AddressState(u256 _balance, u256 _nonce, h256 _contractRoot, h256 _codeHash): m_type(AddressType::Contract), m_balance(_balance), m_nonce(_nonce), m_isComplete(false), m_contractRoot(_contractRoot), m_codeHash(_codeHash) {} + AddressState(): m_isAlive(false), m_isComplete(false), m_balance(0), m_nonce(0) {} + AddressState(u256 _balance, u256 _nonce, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_isComplete(_codeHash == EmptySHA3 && !_contractRoot), m_balance(_balance), m_nonce(_nonce), m_storageRoot(_contractRoot), m_codeHash(_codeHash) {} AddressState(u256 _balance, u256 _nonce, bytesConstRef _code); - void incNonce() { m_nonce++; } - void addBalance(bigint _i) { m_balance = (u256)((bigint)m_balance + _i); } - void kill() { m_type = AddressType::Dead; m_memory.clear(); m_contractRoot = h256(); m_balance = 0; m_nonce = 0; } + void kill() { m_isAlive = false; m_storage.clear(); m_codeHash = EmptySHA3; m_storageRoot = h256(); m_balance = 0; m_nonce = 0; } + bool isAlive() const { return m_isAlive; } - AddressType type() const { return m_type; } u256& balance() { return m_balance; } u256 const& balance() const { return m_balance; } + void addBalance(bigint _i) { m_balance = (u256)((bigint)m_balance + _i); } + u256& nonce() { return m_nonce; } u256 const& nonce() const { return m_nonce; } + void incNonce() { m_nonce++; } + bool isComplete() const { return m_isComplete; } - std::map& setIsComplete(bytesConstRef _code) { assert(m_type == AddressType::Contract); m_isComplete = true; m_contractRoot = h256(); m_code = _code.toBytes(); return m_memory; } - h256 oldRoot() const { assert(!isComplete()); return m_contractRoot; } + std::map& setIsComplete(bytesConstRef _code) { m_isComplete = true; m_storageRoot = h256(); m_code = _code.toBytes(); return m_storage; } + + h256 oldRoot() const { assert(!isComplete()); return m_storageRoot; } + std::map& memory() { return m_storage; } + std::map const& memory() const { assert(isComplete()); return m_storage; } + h256 codeHash() const { assert(m_codeHash); return m_codeHash; } - std::map& memory() { assert(m_type == AddressType::Contract && isComplete()); return m_memory; } - std::map const& memory() const { assert(m_type == AddressType::Contract && isComplete()); return m_memory; } - bytes const& code() const { assert(m_type == AddressType::Contract && isComplete()); return m_code; } + bytes const& code() const { assert(isComplete()); return m_code; } bool freshCode() const { return !m_codeHash && m_isComplete; } void setCode(bytesConstRef _code) { assert(freshCode()); m_code = _code.toBytes(); } private: - AddressType m_type; + bool m_isAlive; + bool m_isComplete; + bool m_gotCode; u256 m_balance; u256 m_nonce; - bool m_isComplete; - h256 m_contractRoot; + h256 m_storageRoot; h256 m_codeHash; // if 0 and m_isComplete, has been created and needs to be inserted. // TODO: change to unordered_map. - std::map m_memory; + std::map m_storage; bytes m_code; }; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 73cd4684c..aa239736b 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -42,10 +42,10 @@ std::map const& eth::genesisState() if (s_ret.empty()) { // Initialise. - s_ret[Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075"))] = AddressState(u256(1) << 200, 0, AddressType::Normal); - s_ret[Address(fromHex("e6716f9544a56c530d868e4bfbacb172315bdead"))] = AddressState(u256(1) << 200, 0, AddressType::Normal); - s_ret[Address(fromHex("1e12515ce3e0f817a4ddef9ca55788a1d66bd2df"))] = AddressState(u256(1) << 200, 0, AddressType::Normal); - s_ret[Address(fromHex("1a26338f0d905e295fccb71fa9ea849ffa12aaf4"))] = AddressState(u256(1) << 200, 0, AddressType::Normal); + s_ret[Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075"))] = AddressState(u256(1) << 200, 0, h256(), EmptySHA3); + s_ret[Address(fromHex("e6716f9544a56c530d868e4bfbacb172315bdead"))] = AddressState(u256(1) << 200, 0, h256(), EmptySHA3); + s_ret[Address(fromHex("1e12515ce3e0f817a4ddef9ca55788a1d66bd2df"))] = AddressState(u256(1) << 200, 0, h256(), EmptySHA3); + s_ret[Address(fromHex("1a26338f0d905e295fccb71fa9ea849ffa12aaf4"))] = AddressState(u256(1) << 200, 0, h256(), EmptySHA3); } return s_ret; } @@ -133,9 +133,7 @@ void State::ensureCached(std::map& _cache, Address _a, bo RLP state(stateBack); AddressState s; if (state.isNull()) - s = AddressState(0, 0); - else if (state.itemCount() == 2) - s = AddressState(state[0].toInt(), state[1].toInt()); + s = AddressState(0, 0, h256(), EmptySHA3); else s = AddressState(state[0].toInt(), state[1].toInt(), state[2].toHash(), state[3].toHash()); bool ok; @@ -144,9 +142,8 @@ void State::ensureCached(std::map& _cache, Address _a, bo if (_requireMemory && !it->second.isComplete()) { // Populate memory. - assert(it->second.type() == AddressType::Contract); TrieDB memdb(const_cast(&m_db), it->second.oldRoot()); // promise we won't alter the overlay! :) - map& mem = it->second.setIsComplete(bytesConstRef(m_db.lookup(it->second.codeHash()))); + map& mem = it->second.setIsComplete(it->second.codeHash() == EmptySHA3 ? bytesConstRef() : bytesConstRef(m_db.lookup(it->second.codeHash()))); for (auto const& i: memdb) mem[i.first] = RLP(i.second).toInt(); } @@ -226,7 +223,7 @@ map State::addresses() const { map ret; for (auto i: m_cache) - if (i.second.type() != AddressType::Dead) + if (i.second.isAlive()) ret[i.first] = i.second.balance(); for (auto const& i: m_state) if (m_cache.find(i.first) == m_cache.end()) @@ -505,7 +502,7 @@ bool State::isNormalAddress(Address _id) const auto it = m_cache.find(_id); if (it == m_cache.end()) return false; - return it->second.type() == AddressType::Normal; + return it->second.codeHash() == EmptySHA3; } bool State::isContractAddress(Address _id) const @@ -514,7 +511,7 @@ bool State::isContractAddress(Address _id) const auto it = m_cache.find(_id); if (it == m_cache.end()) return false; - return it->second.type() == AddressType::Contract; + return it->second.codeHash() != EmptySHA3; } u256 State::balance(Address _id) const @@ -531,7 +528,7 @@ void State::noteSending(Address _id) ensureCached(_id, false, false); auto it = m_cache.find(_id); if (it == m_cache.end()) - m_cache[_id] = AddressState(0, 1); + m_cache[_id] = AddressState(0, 1, h256(), EmptySHA3); else it->second.incNonce(); } @@ -541,7 +538,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, 0); + m_cache[_id] = AddressState(_amount, 0, h256(), EmptySHA3); else it->second.addBalance(_amount); } @@ -570,7 +567,7 @@ u256 State::contractStorage(Address _id, u256 _memory) const { ensureCached(_id, false, false); auto it = m_cache.find(_id); - if (it == m_cache.end() || it->second.type() != AddressType::Contract) + if (it == m_cache.end() || it->second.codeHash() == EmptySHA3) return 0; else if (it->second.isComplete()) { diff --git a/libethereum/State.h b/libethereum/State.h index 1895a6684..961a398b9 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -354,8 +354,8 @@ inline std::ostream& operator<<(std::ostream& _out, State const& _s) if (it == _s.m_cache.end()) { RLP r(i.second); - _out << "[ " << (r.itemCount() == 3 ? "CONTRACT] " : " NORMAL] ") << i.first << ": " << std::dec << r[1].toInt() << "@" << r[0].toInt(); - if (r.itemCount() == 3) + _out << "[ ]" << i.first << ": " << std::dec << r[1].toInt() << "@" << r[0].toInt(); + if (r.itemCount() == 4) { _out << " *" << r[2].toHash(); TrieDB memdb(const_cast(&_s.m_db), r[2].toHash()); // promise we won't alter the overlay! :) @@ -373,12 +373,12 @@ inline std::ostream& operator<<(std::ostream& _out, State const& _s) d.insert(i.first); } for (auto i: _s.m_cache) - if (i.second.type() == AddressType::Dead) + if (!i.second.isAlive()) _out << "[XXX " << i.first << std::endl; else { - _out << (d.count(i.first) ? "[ ! " : "[ * ") << (i.second.type() == AddressType::Contract ? "CONTRACT] " : " NORMAL] ") << i.first << ": " << std::dec << i.second.nonce() << "@" << i.second.balance(); - if (i.second.type() == AddressType::Contract) + _out << (d.count(i.first) ? "[ ! " : "[ * ") << "]" << i.first << ": " << std::dec << i.second.nonce() << "@" << i.second.balance(); + if (i.second.codeHash() != EmptySHA3) { if (i.second.isComplete()) { @@ -406,34 +406,37 @@ template void commit(std::map const& _cache, DB& _db, TrieDB& _state) { for (auto const& i: _cache) - if (i.second.type() == AddressType::Dead) + if (!i.second.isAlive()) _state.remove(i.first); else { - RLPStream s(i.second.type() == AddressType::Contract ? 3 : 2); + RLPStream s(4); s << i.second.balance() << i.second.nonce(); - if (i.second.type() == AddressType::Contract) + + if (i.second.isComplete()) { - if (i.second.isComplete()) + if (i.second.memory().empty()) + s << h256(); + else { - TrieDB memdb(&_db); - memdb.init(); + TrieDB storageDB(&_db); + storageDB.init(); for (auto const& j: i.second.memory()) if (j.second) - memdb.insert(j.first, rlp(j.second)); - s << memdb.root(); - if (i.second.freshCode()) - { - h256 ch = sha3(i.second.code()); - _db.insert(ch, &i.second.code()); - s << ch; - } - else - s << i.second.codeHash(); + storageDB.insert(j.first, rlp(j.second)); + s << storageDB.root(); + } + if (i.second.freshCode()) + { + h256 ch = sha3(i.second.code()); + _db.insert(ch, &i.second.code()); + s << ch; } else - s << i.second.oldRoot() << i.second.codeHash(); + s << i.second.codeHash(); } + else + s << i.second.oldRoot() << i.second.codeHash(); _state.insert(i.first, &s.out()); } }