Browse Source

New SecureTrie.

cl-refactor
Gav Wood 10 years ago
parent
commit
0b3ecf4b76
  1. 48
      libdevcrypto/TrieDB.h
  2. 2
      libethcore/CommonEth.cpp
  3. 6
      libethereum/CachedAddressState.cpp
  4. 3
      libethereum/CachedAddressState.h
  5. 2
      libethereum/CanonBlockChain.cpp
  6. 63
      libethereum/State.cpp
  7. 9
      libethereum/State.h
  8. 2
      mix/MixClient.cpp

48
libdevcrypto/TrieDB.h

@ -325,6 +325,54 @@ std::ostream& operator<<(std::ostream& _out, TrieDB<KeyType, DB> const& _db)
return _out;
}
template <class DB>
class SecureGenericTrieDB: private TrieDB<h256, DB>
{
using Super = TrieDB<h256, DB>;
public:
SecureGenericTrieDB(DB* _db): Super(_db) {}
SecureGenericTrieDB(DB* _db, h256 _root): Super(_db, _root) {}
using Super::open;
using Super::init;
using Super::setRoot;
using Super::haveRoot;
/// True if the trie is uninitialised (i.e. that the DB doesn't contain the root node).
using Super::isNull;
/// True if the trie is initialised but empty (i.e. that the DB contains the root node which is empty).
using Super::isEmpty;
using Super::root;
using Super::leftOvers;
using Super::check;
std::string at(bytesConstRef _key) const { return Super::at(sha3(_key)); }
void insert(bytesConstRef _key, bytesConstRef _value) { Super::insert(sha3(_key), _value); }
void remove(bytesConstRef _key) { Super::remove(sha3(_key)); }
bool contains(bytesConstRef _key) { return Super::contains(sha3(_key)); }
};
template <class KeyType, class DB>
class SecureTrieDB: public SecureGenericTrieDB<DB>
{
using Super = SecureGenericTrieDB<DB>;
public:
SecureTrieDB(DB* _db): Super(_db) {}
SecureTrieDB(DB* _db, h256 _root): Super(_db, _root) {}
std::string operator[](KeyType _k) const { return at(_k); }
bool contains(KeyType _k) const { return Super::contains(bytesConstRef((byte const*)&_k, sizeof(KeyType))); }
std::string at(KeyType _k) const { return Super::at(bytesConstRef((byte const*)&_k, sizeof(KeyType))); }
void insert(KeyType _k, bytesConstRef _value) { Super::insert(bytesConstRef((byte const*)&_k, sizeof(KeyType)), _value); }
void insert(KeyType _k, bytes const& _value) { insert(_k, bytesConstRef(&_value)); }
void remove(KeyType _k) { Super::remove(bytesConstRef((byte const*)&_k, sizeof(KeyType))); }
};
}
// Template implementations...

2
libethcore/CommonEth.cpp

@ -32,7 +32,7 @@ namespace dev
namespace eth
{
const unsigned c_protocolVersion = 54;
const unsigned c_protocolVersion = 55;
const unsigned c_databaseVersion = 5;
vector<pair<u256, string>> const& units()

6
libethereum/CachedAddressState.cpp

@ -56,9 +56,9 @@ std::map<u256, u256> CachedAddressState::storage() const
std::map<u256, u256> ret;
if (m_r)
{
TrieDB<h256, OverlayDB> memdb(const_cast<OverlayDB*>(m_o), m_r[2].toHash<h256>()); // promise we won't alter the overlay! :)
for (auto const& j: memdb)
ret[j.first] = RLP(j.second).toInt<u256>();
SecureTrieDB<h256, OverlayDB> memdb(const_cast<OverlayDB*>(m_o), m_r[2].toHash<h256>()); // promise we won't alter the overlay! :)
// for (auto const& j: memdb)
// ret[j.first] = RLP(j.second).toInt<u256>();
}
if (m_s)
for (auto const& j: m_s->storageOverlay())

3
libethereum/CachedAddressState.h

@ -45,7 +45,10 @@ public:
u256 balance() const;
u256 nonce() const;
bytes code() const;
// TODO: DEPRECATE.
std::map<u256, u256> storage() const;
AccountDiff diff(CachedAddressState const& _c);
private:

2
libethereum/CanonBlockChain.cpp

@ -76,7 +76,7 @@ bytes CanonBlockChain::createGenesisBlock()
h256 stateRoot;
{
MemoryDB db;
TrieDB<Address, MemoryDB> state(&db);
SecureTrieDB<Address, MemoryDB> state(&db);
state.init();
dev::eth::commit(genesisState(), db, state);
stateRoot = state.root();

63
libethereum/State.cpp

@ -168,18 +168,6 @@ State::~State()
{
}
Address State::nextActiveAddress(Address _a) const
{
auto it = m_state.lower_bound(_a);
if ((*it).first == _a)
++it;
if (it == m_state.end())
// exchange comments if we want to wraparound
// it = m_state.begin();
return Address();
return (*it).first;
}
StateDiff State::diff(State const& _c) const
{
StateDiff ret;
@ -188,13 +176,14 @@ StateDiff State::diff(State const& _c) const
std::set<Address> trieAds;
std::set<Address> trieAdsD;
auto trie = TrieDB<Address, OverlayDB>(const_cast<OverlayDB*>(&m_db), rootHash());
auto trieD = TrieDB<Address, OverlayDB>(const_cast<OverlayDB*>(&_c.m_db), _c.rootHash());
auto trie = SecureTrieDB<Address, OverlayDB>(const_cast<OverlayDB*>(&m_db), rootHash());
auto trieD = SecureTrieDB<Address, OverlayDB>(const_cast<OverlayDB*>(&_c.m_db), _c.rootHash());
for (auto i: trie)
ads.insert(i.first), trieAds.insert(i.first);
for (auto i: trieD)
ads.insert(i.first), trieAdsD.insert(i.first);
// TODO: fix
// for (auto i: trie)
// ads.insert(i.first), trieAds.insert(i.first);
// for (auto i: trieD)
// ads.insert(i.first), trieAdsD.insert(i.first);
for (auto i: m_cache)
ads.insert(i.first);
for (auto i: _c.m_cache)
@ -356,9 +345,10 @@ map<Address, u256> State::addresses() const
for (auto i: m_cache)
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())
ret[i.first] = RLP(i.second)[1].toInt<u256>();
// TODO: fix.
// for (auto const& i: m_state)
// if (m_cache.find(i.first) == m_cache.end())
// ret[i.first] = RLP(i.second)[1].toInt<u256>();
return ret;
}
@ -591,9 +581,10 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
{
cwarn << "Bad state root!";
cnote << "Given to be:" << m_currentBlock.stateRoot;
cnote << TrieDB<Address, OverlayDB>(&m_db, m_currentBlock.stateRoot);
// TODO: Fix
// cnote << SecureTrieDB<Address, OverlayDB>(&m_db, m_currentBlock.stateRoot);
cnote << "Calculated to be:" << rootHash();
cnote << m_state;
// cnote << m_state;
cnote << *this;
// Rollback the trie.
m_db.rollback();
@ -932,7 +923,7 @@ u256 State::storage(Address _id, u256 _memory) const
return mit->second;
// Not in the storage cache - go to the DB.
TrieDB<h256, OverlayDB> memdb(const_cast<OverlayDB*>(&m_db), it->second.baseRoot()); // promise we won't change the overlay! :)
SecureTrieDB<h256, OverlayDB> memdb(const_cast<OverlayDB*>(&m_db), it->second.baseRoot()); // promise we won't change the overlay! :)
string payload = memdb.at(_memory);
u256 ret = payload.size() ? RLP(payload).toInt<u256>() : 0;
it->second.setStorage(_memory, ret);
@ -950,9 +941,10 @@ map<u256, u256> State::storage(Address _id) const
// Pull out all values from trie storage.
if (it->second.baseRoot())
{
TrieDB<h256, OverlayDB> memdb(const_cast<OverlayDB*>(&m_db), it->second.baseRoot()); // promise we won't alter the overlay! :)
for (auto const& i: memdb)
ret[i.first] = RLP(i.second).toInt<u256>();
// TODO: fix
// SecureTrieDB<h256, OverlayDB> memdb(const_cast<OverlayDB*>(&m_db), it->second.baseRoot()); // promise we won't alter the overlay! :)
// for (auto const& i: memdb)
// ret[i.first] = RLP(i.second).toInt<u256>();
}
// Then merge cached storage over the top.
@ -1003,24 +995,24 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const
cwarn << "LEFTOVERS" << (e ? "[enforced" : "[unenforced") << "refs]";
cnote << "Left:" << lo;
cnote << "Keys:" << m_db.keys();
m_state.debugStructure(cerr);
// m_state.debugStructure(cerr);
return false;
}
// TODO: Enable once fixed.
for (auto const& i: m_state)
/* for (auto const& i: m_state)
{
RLP r(i.second);
TrieDB<h256, OverlayDB> storageDB(const_cast<OverlayDB*>(&m_db), r[2].toHash<h256>()); // promise not to alter OverlayDB.
SecureTrieDB<h256, OverlayDB> storageDB(const_cast<OverlayDB*>(&m_db), r[2].toHash<h256>()); // promise not to alter OverlayDB.
for (auto const& j: storageDB) { (void)j; }
if (!e && r[3].toHash<h256>() != EmptySHA3 && m_db.lookup(r[3].toHash<h256>()).empty())
return false;
}
}*/
}
catch (InvalidTrie const&)
{
cwarn << "BAD TRIE" << (e ? "[enforced" : "[unenforced") << "refs]";
cnote << m_db.keys();
m_state.debugStructure(cerr);
// m_state.debugStructure(cerr);
return false;
}
return true;
@ -1187,9 +1179,10 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, State const& _s)
std::set<u256> cached;
if (r)
{
TrieDB<h256, OverlayDB> memdb(const_cast<OverlayDB*>(&_s.m_db), r[2].toHash<h256>()); // promise we won't alter the overlay! :)
for (auto const& j: memdb)
mem[j.first] = RLP(j.second).toInt<u256>(), back.insert(j.first);
SecureTrieDB<h256, OverlayDB> memdb(const_cast<OverlayDB*>(&_s.m_db), r[2].toHash<h256>()); // promise we won't alter the overlay! :)
// TODO: fix
// for (auto const& j: memdb)
// mem[j.first] = RLP(j.second).toInt<u256>(), back.insert(j.first);
}
if (cache)
for (auto const& j: cache->storageOverlay())

9
libethereum/State.h

@ -94,9 +94,6 @@ public:
/// @returns the set containing all addresses currently in use in Ethereum.
std::map<Address, u256> addresses() const;
/// @returns the address b such that b > @a _a .
Address nextActiveAddress(Address _a) const;
/// Get the header information on the present block.
BlockInfo const& info() const { return m_currentBlock; }
@ -299,7 +296,7 @@ private:
void paranoia(std::string const& _when, bool _enforceRefs = false) const;
OverlayDB m_db; ///< Our overlay for the state tree.
TrieDB<Address, OverlayDB> m_state; ///< Our state tree, as an OverlayDB DB.
SecureTrieDB<Address, OverlayDB> m_state; ///< Our state tree, as an OverlayDB DB.
Transactions m_transactions; ///< The current list of transactions that we've included in the state.
TransactionReceipts m_receipts; ///< The corresponding list of transaction receipts.
std::set<h256> m_transactionSet; ///< The set of transaction hashes that we've included in the state.
@ -328,7 +325,7 @@ private:
std::ostream& operator<<(std::ostream& _out, State const& _s);
template <class DB>
void commit(std::map<Address, Account> const& _cache, DB& _db, TrieDB<Address, DB>& _state)
void commit(std::map<Address, Account> const& _cache, DB& _db, SecureTrieDB<Address, DB>& _state)
{
for (auto const& i: _cache)
if (!i.second.isAlive())
@ -345,7 +342,7 @@ void commit(std::map<Address, Account> const& _cache, DB& _db, TrieDB<Address, D
}
else
{
TrieDB<h256, DB> storageDB(&_db, i.second.baseRoot());
SecureTrieDB<h256, DB> storageDB(&_db, i.second.baseRoot());
for (auto const& j: i.second.storageOverlay())
if (j.second)
storageDB.insert(j.first, rlp(j.second));

2
mix/MixClient.cpp

@ -79,7 +79,7 @@ void MixClient::resetState(u256 _balance)
m_watches.clear();
m_stateDB = OverlayDB();
TrieDB<Address, MemoryDB> accountState(&m_stateDB);
SecureTrieDB<Address, MemoryDB> accountState(&m_stateDB);
accountState.init();
std::map<Address, Account> genesisState = { std::make_pair(KeyPair(c_userAccountSecret).address(), Account(_balance, Account::NormalCreation)) };
dev::eth::commit(genesisState, static_cast<MemoryDB&>(m_stateDB), accountState);

Loading…
Cancel
Save