Browse Source

New SecureTrie.

cl-refactor
Gav Wood 10 years ago
parent
commit
bb0f5358bf
  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; 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... // Template implementations...

2
libethcore/CommonEth.cpp

@ -32,7 +32,7 @@ namespace dev
namespace eth namespace eth
{ {
const unsigned c_protocolVersion = 54; const unsigned c_protocolVersion = 55;
const unsigned c_databaseVersion = 5; const unsigned c_databaseVersion = 5;
vector<pair<u256, string>> const& units() 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; std::map<u256, u256> ret;
if (m_r) if (m_r)
{ {
TrieDB<h256, OverlayDB> memdb(const_cast<OverlayDB*>(m_o), m_r[2].toHash<h256>()); // promise we won't alter the overlay! :) 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) // for (auto const& j: memdb)
ret[j.first] = RLP(j.second).toInt<u256>(); // ret[j.first] = RLP(j.second).toInt<u256>();
} }
if (m_s) if (m_s)
for (auto const& j: m_s->storageOverlay()) for (auto const& j: m_s->storageOverlay())

3
libethereum/CachedAddressState.h

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

2
libethereum/CanonBlockChain.cpp

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

63
libethereum/State.cpp

@ -169,18 +169,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 State::diff(State const& _c) const
{ {
StateDiff ret; StateDiff ret;
@ -189,13 +177,14 @@ StateDiff State::diff(State const& _c) const
std::set<Address> trieAds; std::set<Address> trieAds;
std::set<Address> trieAdsD; std::set<Address> trieAdsD;
auto trie = TrieDB<Address, OverlayDB>(const_cast<OverlayDB*>(&m_db), rootHash()); auto trie = SecureTrieDB<Address, OverlayDB>(const_cast<OverlayDB*>(&m_db), rootHash());
auto trieD = TrieDB<Address, OverlayDB>(const_cast<OverlayDB*>(&_c.m_db), _c.rootHash()); auto trieD = SecureTrieDB<Address, OverlayDB>(const_cast<OverlayDB*>(&_c.m_db), _c.rootHash());
for (auto i: trie) // TODO: fix
ads.insert(i.first), trieAds.insert(i.first); // for (auto i: trie)
for (auto i: trieD) // ads.insert(i.first), trieAds.insert(i.first);
ads.insert(i.first), trieAdsD.insert(i.first); // for (auto i: trieD)
// ads.insert(i.first), trieAdsD.insert(i.first);
for (auto i: m_cache) for (auto i: m_cache)
ads.insert(i.first); ads.insert(i.first);
for (auto i: _c.m_cache) for (auto i: _c.m_cache)
@ -357,9 +346,10 @@ map<Address, u256> State::addresses() const
for (auto i: m_cache) for (auto i: m_cache)
if (i.second.isAlive()) if (i.second.isAlive())
ret[i.first] = i.second.balance(); ret[i.first] = i.second.balance();
for (auto const& i: m_state) // TODO: fix.
if (m_cache.find(i.first) == m_cache.end()) // for (auto const& i: m_state)
ret[i.first] = RLP(i.second)[1].toInt<u256>(); // if (m_cache.find(i.first) == m_cache.end())
// ret[i.first] = RLP(i.second)[1].toInt<u256>();
return ret; return ret;
} }
@ -592,9 +582,10 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
{ {
cwarn << "Bad state root!"; cwarn << "Bad state root!";
cnote << "Given to be:" << m_currentBlock.stateRoot; 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 << "Calculated to be:" << rootHash();
cnote << m_state; // cnote << m_state;
cnote << *this; cnote << *this;
// Rollback the trie. // Rollback the trie.
m_db.rollback(); m_db.rollback();
@ -939,7 +930,7 @@ u256 State::storage(Address _id, u256 _memory) const
return mit->second; return mit->second;
// Not in the storage cache - go to the DB. // 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); string payload = memdb.at(_memory);
u256 ret = payload.size() ? RLP(payload).toInt<u256>() : 0; u256 ret = payload.size() ? RLP(payload).toInt<u256>() : 0;
it->second.setStorage(_memory, ret); it->second.setStorage(_memory, ret);
@ -957,9 +948,10 @@ map<u256, u256> State::storage(Address _id) const
// Pull out all values from trie storage. // Pull out all values from trie storage.
if (it->second.baseRoot()) if (it->second.baseRoot())
{ {
TrieDB<h256, OverlayDB> memdb(const_cast<OverlayDB*>(&m_db), it->second.baseRoot()); // promise we won't alter the overlay! :) // TODO: fix
for (auto const& i: memdb) // SecureTrieDB<h256, OverlayDB> memdb(const_cast<OverlayDB*>(&m_db), it->second.baseRoot()); // promise we won't alter the overlay! :)
ret[i.first] = RLP(i.second).toInt<u256>(); // for (auto const& i: memdb)
// ret[i.first] = RLP(i.second).toInt<u256>();
} }
// Then merge cached storage over the top. // Then merge cached storage over the top.
@ -1010,24 +1002,24 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const
cwarn << "LEFTOVERS" << (e ? "[enforced" : "[unenforced") << "refs]"; cwarn << "LEFTOVERS" << (e ? "[enforced" : "[unenforced") << "refs]";
cnote << "Left:" << lo; cnote << "Left:" << lo;
cnote << "Keys:" << m_db.keys(); cnote << "Keys:" << m_db.keys();
m_state.debugStructure(cerr); // m_state.debugStructure(cerr);
return false; return false;
} }
// TODO: Enable once fixed. // TODO: Enable once fixed.
for (auto const& i: m_state) /* for (auto const& i: m_state)
{ {
RLP r(i.second); 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; } for (auto const& j: storageDB) { (void)j; }
if (!e && r[3].toHash<h256>() != EmptySHA3 && m_db.lookup(r[3].toHash<h256>()).empty()) if (!e && r[3].toHash<h256>() != EmptySHA3 && m_db.lookup(r[3].toHash<h256>()).empty())
return false; return false;
} }*/
} }
catch (InvalidTrie const&) catch (InvalidTrie const&)
{ {
cwarn << "BAD TRIE" << (e ? "[enforced" : "[unenforced") << "refs]"; cwarn << "BAD TRIE" << (e ? "[enforced" : "[unenforced") << "refs]";
cnote << m_db.keys(); cnote << m_db.keys();
m_state.debugStructure(cerr); // m_state.debugStructure(cerr);
return false; return false;
} }
return true; return true;
@ -1194,9 +1186,10 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, State const& _s)
std::set<u256> cached; std::set<u256> cached;
if (r) if (r)
{ {
TrieDB<h256, OverlayDB> memdb(const_cast<OverlayDB*>(&_s.m_db), r[2].toHash<h256>()); // promise we won't alter the overlay! :) SecureTrieDB<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) // TODO: fix
mem[j.first] = RLP(j.second).toInt<u256>(), back.insert(j.first); // for (auto const& j: memdb)
// mem[j.first] = RLP(j.second).toInt<u256>(), back.insert(j.first);
} }
if (cache) if (cache)
for (auto const& j: cache->storageOverlay()) 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. /// @returns the set containing all addresses currently in use in Ethereum.
std::map<Address, u256> addresses() const; 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. /// Get the header information on the present block.
BlockInfo const& info() const { return m_currentBlock; } BlockInfo const& info() const { return m_currentBlock; }
@ -299,7 +296,7 @@ private:
void paranoia(std::string const& _when, bool _enforceRefs = false) const; void paranoia(std::string const& _when, bool _enforceRefs = false) const;
OverlayDB m_db; ///< Our overlay for the state tree. 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. Transactions m_transactions; ///< The current list of transactions that we've included in the state.
TransactionReceipts m_receipts; ///< The corresponding list of transaction receipts. 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. 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); std::ostream& operator<<(std::ostream& _out, State const& _s);
template <class DB> 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) for (auto const& i: _cache)
if (!i.second.isAlive()) if (!i.second.isAlive())
@ -345,7 +342,7 @@ void commit(std::map<Address, Account> const& _cache, DB& _db, TrieDB<Address, D
} }
else else
{ {
TrieDB<h256, DB> storageDB(&_db, i.second.baseRoot()); SecureTrieDB<h256, DB> storageDB(&_db, i.second.baseRoot());
for (auto const& j: i.second.storageOverlay()) for (auto const& j: i.second.storageOverlay())
if (j.second) if (j.second)
storageDB.insert(j.first, rlp(j.second)); storageDB.insert(j.first, rlp(j.second));

2
mix/MixClient.cpp

@ -81,7 +81,7 @@ void MixClient::resetState(std::map<Secret, u256> _accounts)
m_watches.clear(); m_watches.clear();
m_stateDB = OverlayDB(); m_stateDB = OverlayDB();
TrieDB<Address, MemoryDB> accountState(&m_stateDB); SecureTrieDB<Address, MemoryDB> accountState(&m_stateDB);
accountState.init(); accountState.init();
std::map<Address, Account> genesisState; std::map<Address, Account> genesisState;

Loading…
Cancel
Save