Browse Source

Accounts all the same "type".

cl-refactor
Gav Wood 11 years ago
parent
commit
5f6e533169
  1. 2
      libethcore/FixedHash.cpp
  2. 2
      libethcore/FixedHash.h
  3. 4
      libethereum/AddressState.cpp
  4. 43
      libethereum/AddressState.h
  5. 27
      libethereum/State.cpp
  6. 31
      libethereum/State.h

2
libethcore/FixedHash.cpp

@ -25,6 +25,8 @@
using namespace std; using namespace std;
using namespace eth; using namespace eth;
h256 eth::EmptySHA3 = sha3(bytesConstRef());
std::string eth::sha3(std::string const& _input, bool _hex) std::string eth::sha3(std::string const& _input, bool _hex)
{ {
if (!_hex) if (!_hex)

2
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. /// 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)); } inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); }
extern h256 EmptySHA3;
} }
namespace std namespace std

4
libethereum/AddressState.cpp

@ -25,9 +25,9 @@ using namespace std;
using namespace eth; using namespace eth;
AddressState::AddressState(u256 _balance, u256 _nonce, bytesConstRef _code): AddressState::AddressState(u256 _balance, u256 _nonce, bytesConstRef _code):
m_type(AddressType::Contract), m_isAlive(true),
m_isComplete(true),
m_balance(_balance), m_balance(_balance),
m_nonce(_nonce), m_nonce(_nonce),
m_isComplete(true),
m_code(_code.toBytes()) m_code(_code.toBytes())
{} {}

43
libethereum/AddressState.h

@ -27,49 +27,48 @@
namespace eth namespace eth
{ {
enum class AddressType // TODO: Don't pre-cache all of storage.
{
Dead,
Normal,
Contract
};
class AddressState class AddressState
{ {
public: public:
AddressState(): m_type(AddressType::Dead), m_balance(0), m_nonce(0), m_isComplete(false) {} AddressState(): m_isAlive(false), m_isComplete(false), m_balance(0), m_nonce(0) {}
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_isAlive(true), m_isComplete(_codeHash == EmptySHA3 && !_contractRoot), m_balance(_balance), m_nonce(_nonce), m_storageRoot(_contractRoot), m_codeHash(_codeHash) {}
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(u256 _balance, u256 _nonce, bytesConstRef _code); AddressState(u256 _balance, u256 _nonce, bytesConstRef _code);
void incNonce() { m_nonce++; } void kill() { m_isAlive = false; m_storage.clear(); m_codeHash = EmptySHA3; m_storageRoot = h256(); m_balance = 0; m_nonce = 0; }
void addBalance(bigint _i) { m_balance = (u256)((bigint)m_balance + _i); } bool isAlive() const { return m_isAlive; }
void kill() { m_type = AddressType::Dead; m_memory.clear(); m_contractRoot = h256(); m_balance = 0; m_nonce = 0; }
AddressType type() const { return m_type; }
u256& balance() { return m_balance; } u256& balance() { return m_balance; }
u256 const& balance() const { 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& nonce() { return m_nonce; }
u256 const& nonce() const { return m_nonce; } u256 const& nonce() const { return m_nonce; }
void incNonce() { m_nonce++; }
bool isComplete() const { return m_isComplete; } bool isComplete() const { return m_isComplete; }
std::map<u256, u256>& setIsComplete(bytesConstRef _code) { assert(m_type == AddressType::Contract); m_isComplete = true; m_contractRoot = h256(); m_code = _code.toBytes(); return m_memory; } std::map<u256, u256>& setIsComplete(bytesConstRef _code) { m_isComplete = true; m_storageRoot = h256(); m_code = _code.toBytes(); return m_storage; }
h256 oldRoot() const { assert(!isComplete()); return m_contractRoot; }
h256 oldRoot() const { assert(!isComplete()); return m_storageRoot; }
std::map<u256, u256>& memory() { return m_storage; }
std::map<u256, u256> const& memory() const { assert(isComplete()); return m_storage; }
h256 codeHash() const { assert(m_codeHash); return m_codeHash; } h256 codeHash() const { assert(m_codeHash); return m_codeHash; }
std::map<u256, u256>& memory() { assert(m_type == AddressType::Contract && isComplete()); return m_memory; } bytes const& code() const { assert(isComplete()); return m_code; }
std::map<u256, u256> 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; }
bool freshCode() const { return !m_codeHash && m_isComplete; } bool freshCode() const { return !m_codeHash && m_isComplete; }
void setCode(bytesConstRef _code) { assert(freshCode()); m_code = _code.toBytes(); } void setCode(bytesConstRef _code) { assert(freshCode()); m_code = _code.toBytes(); }
private: private:
AddressType m_type; bool m_isAlive;
bool m_isComplete;
bool m_gotCode;
u256 m_balance; u256 m_balance;
u256 m_nonce; u256 m_nonce;
bool m_isComplete; h256 m_storageRoot;
h256 m_contractRoot;
h256 m_codeHash; // if 0 and m_isComplete, has been created and needs to be inserted. h256 m_codeHash; // if 0 and m_isComplete, has been created and needs to be inserted.
// TODO: change to unordered_map. // TODO: change to unordered_map.
std::map<u256, u256> m_memory; std::map<u256, u256> m_storage;
bytes m_code; bytes m_code;
}; };

27
libethereum/State.cpp

@ -42,10 +42,10 @@ std::map<Address, AddressState> const& eth::genesisState()
if (s_ret.empty()) if (s_ret.empty())
{ {
// Initialise. // Initialise.
s_ret[Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075"))] = 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, AddressType::Normal); s_ret[Address(fromHex("e6716f9544a56c530d868e4bfbacb172315bdead"))] = AddressState(u256(1) << 200, 0, h256(), EmptySHA3);
s_ret[Address(fromHex("1e12515ce3e0f817a4ddef9ca55788a1d66bd2df"))] = AddressState(u256(1) << 200, 0, AddressType::Normal); s_ret[Address(fromHex("1e12515ce3e0f817a4ddef9ca55788a1d66bd2df"))] = AddressState(u256(1) << 200, 0, h256(), EmptySHA3);
s_ret[Address(fromHex("1a26338f0d905e295fccb71fa9ea849ffa12aaf4"))] = AddressState(u256(1) << 200, 0, AddressType::Normal); s_ret[Address(fromHex("1a26338f0d905e295fccb71fa9ea849ffa12aaf4"))] = AddressState(u256(1) << 200, 0, h256(), EmptySHA3);
} }
return s_ret; return s_ret;
} }
@ -133,9 +133,7 @@ void State::ensureCached(std::map<Address, AddressState>& _cache, Address _a, bo
RLP state(stateBack); RLP state(stateBack);
AddressState s; AddressState s;
if (state.isNull()) if (state.isNull())
s = AddressState(0, 0); s = AddressState(0, 0, h256(), EmptySHA3);
else if (state.itemCount() == 2)
s = AddressState(state[0].toInt<u256>(), state[1].toInt<u256>());
else else
s = AddressState(state[0].toInt<u256>(), state[1].toInt<u256>(), state[2].toHash<h256>(), state[3].toHash<h256>()); s = AddressState(state[0].toInt<u256>(), state[1].toInt<u256>(), state[2].toHash<h256>(), state[3].toHash<h256>());
bool ok; bool ok;
@ -144,9 +142,8 @@ void State::ensureCached(std::map<Address, AddressState>& _cache, Address _a, bo
if (_requireMemory && !it->second.isComplete()) if (_requireMemory && !it->second.isComplete())
{ {
// Populate memory. // Populate memory.
assert(it->second.type() == AddressType::Contract);
TrieDB<h256, Overlay> memdb(const_cast<Overlay*>(&m_db), it->second.oldRoot()); // promise we won't alter the overlay! :) TrieDB<h256, Overlay> memdb(const_cast<Overlay*>(&m_db), it->second.oldRoot()); // promise we won't alter the overlay! :)
map<u256, u256>& mem = it->second.setIsComplete(bytesConstRef(m_db.lookup(it->second.codeHash()))); map<u256, u256>& mem = it->second.setIsComplete(it->second.codeHash() == EmptySHA3 ? bytesConstRef() : bytesConstRef(m_db.lookup(it->second.codeHash())));
for (auto const& i: memdb) for (auto const& i: memdb)
mem[i.first] = RLP(i.second).toInt<u256>(); mem[i.first] = RLP(i.second).toInt<u256>();
} }
@ -226,7 +223,7 @@ map<Address, u256> State::addresses() const
{ {
map<Address, u256> ret; map<Address, u256> ret;
for (auto i: m_cache) for (auto i: m_cache)
if (i.second.type() != AddressType::Dead) if (i.second.isAlive())
ret[i.first] = i.second.balance(); ret[i.first] = i.second.balance();
for (auto const& i: m_state) for (auto const& i: m_state)
if (m_cache.find(i.first) == m_cache.end()) 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); auto it = m_cache.find(_id);
if (it == m_cache.end()) if (it == m_cache.end())
return false; return false;
return it->second.type() == AddressType::Normal; return it->second.codeHash() == EmptySHA3;
} }
bool State::isContractAddress(Address _id) const bool State::isContractAddress(Address _id) const
@ -514,7 +511,7 @@ bool State::isContractAddress(Address _id) const
auto it = m_cache.find(_id); auto it = m_cache.find(_id);
if (it == m_cache.end()) if (it == m_cache.end())
return false; return false;
return it->second.type() == AddressType::Contract; return it->second.codeHash() != EmptySHA3;
} }
u256 State::balance(Address _id) const u256 State::balance(Address _id) const
@ -531,7 +528,7 @@ void State::noteSending(Address _id)
ensureCached(_id, false, false); ensureCached(_id, false, false);
auto it = m_cache.find(_id); auto it = m_cache.find(_id);
if (it == m_cache.end()) if (it == m_cache.end())
m_cache[_id] = AddressState(0, 1); m_cache[_id] = AddressState(0, 1, h256(), EmptySHA3);
else else
it->second.incNonce(); it->second.incNonce();
} }
@ -541,7 +538,7 @@ void State::addBalance(Address _id, u256 _amount)
ensureCached(_id, false, false); ensureCached(_id, false, false);
auto it = m_cache.find(_id); auto it = m_cache.find(_id);
if (it == m_cache.end()) if (it == m_cache.end())
m_cache[_id] = AddressState(_amount, 0); m_cache[_id] = AddressState(_amount, 0, h256(), EmptySHA3);
else else
it->second.addBalance(_amount); it->second.addBalance(_amount);
} }
@ -570,7 +567,7 @@ u256 State::contractStorage(Address _id, u256 _memory) const
{ {
ensureCached(_id, false, false); ensureCached(_id, false, false);
auto it = m_cache.find(_id); 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; return 0;
else if (it->second.isComplete()) else if (it->second.isComplete())
{ {

31
libethereum/State.h

@ -354,8 +354,8 @@ inline std::ostream& operator<<(std::ostream& _out, State const& _s)
if (it == _s.m_cache.end()) if (it == _s.m_cache.end())
{ {
RLP r(i.second); RLP r(i.second);
_out << "[ " << (r.itemCount() == 3 ? "CONTRACT] " : " NORMAL] ") << i.first << ": " << std::dec << r[1].toInt<u256>() << "@" << r[0].toInt<u256>(); _out << "[ ]" << i.first << ": " << std::dec << r[1].toInt<u256>() << "@" << r[0].toInt<u256>();
if (r.itemCount() == 3) if (r.itemCount() == 4)
{ {
_out << " *" << r[2].toHash<h256>(); _out << " *" << r[2].toHash<h256>();
TrieDB<h256, Overlay> memdb(const_cast<Overlay*>(&_s.m_db), r[2].toHash<h256>()); // promise we won't alter the overlay! :) TrieDB<h256, Overlay> memdb(const_cast<Overlay*>(&_s.m_db), r[2].toHash<h256>()); // 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); d.insert(i.first);
} }
for (auto i: _s.m_cache) for (auto i: _s.m_cache)
if (i.second.type() == AddressType::Dead) if (!i.second.isAlive())
_out << "[XXX " << i.first << std::endl; _out << "[XXX " << i.first << std::endl;
else else
{ {
_out << (d.count(i.first) ? "[ ! " : "[ * ") << (i.second.type() == AddressType::Contract ? "CONTRACT] " : " NORMAL] ") << i.first << ": " << std::dec << i.second.nonce() << "@" << i.second.balance(); _out << (d.count(i.first) ? "[ ! " : "[ * ") << "]" << i.first << ": " << std::dec << i.second.nonce() << "@" << i.second.balance();
if (i.second.type() == AddressType::Contract) if (i.second.codeHash() != EmptySHA3)
{ {
if (i.second.isComplete()) if (i.second.isComplete())
{ {
@ -406,22 +406,26 @@ template <class DB>
void commit(std::map<Address, AddressState> const& _cache, DB& _db, TrieDB<Address, DB>& _state) void commit(std::map<Address, AddressState> const& _cache, DB& _db, TrieDB<Address, DB>& _state)
{ {
for (auto const& i: _cache) for (auto const& i: _cache)
if (i.second.type() == AddressType::Dead) if (!i.second.isAlive())
_state.remove(i.first); _state.remove(i.first);
else else
{ {
RLPStream s(i.second.type() == AddressType::Contract ? 3 : 2); RLPStream s(4);
s << i.second.balance() << i.second.nonce(); s << i.second.balance() << i.second.nonce();
if (i.second.type() == AddressType::Contract)
{
if (i.second.isComplete()) if (i.second.isComplete())
{ {
TrieDB<h256, DB> memdb(&_db); if (i.second.memory().empty())
memdb.init(); s << h256();
else
{
TrieDB<h256, DB> storageDB(&_db);
storageDB.init();
for (auto const& j: i.second.memory()) for (auto const& j: i.second.memory())
if (j.second) if (j.second)
memdb.insert(j.first, rlp(j.second)); storageDB.insert(j.first, rlp(j.second));
s << memdb.root(); s << storageDB.root();
}
if (i.second.freshCode()) if (i.second.freshCode())
{ {
h256 ch = sha3(i.second.code()); h256 ch = sha3(i.second.code());
@ -433,7 +437,6 @@ void commit(std::map<Address, AddressState> const& _cache, DB& _db, TrieDB<Addre
} }
else else
s << i.second.oldRoot() << i.second.codeHash(); s << i.second.oldRoot() << i.second.codeHash();
}
_state.insert(i.first, &s.out()); _state.insert(i.first, &s.out());
} }
} }

Loading…
Cancel
Save