Browse Source

State integration test.

Fixes to the FatTrie.
cl-refactor
Gav Wood 10 years ago
parent
commit
ae1cb7f1ff
  1. 3
      CMakeLists.txt
  2. 4
      libdevcore/FixedHash.h
  3. 6
      libdevcrypto/MemoryDB.h
  4. 16
      libdevcrypto/OverlayDB.cpp
  5. 2
      libdevcrypto/TrieDB.h
  6. 2
      libethcore/CommonEth.cpp
  7. 38
      libethereum/State.h
  8. 62
      test/trie.cpp

3
CMakeLists.txt

@ -20,6 +20,7 @@ function(createDefaultCacheConfig)
set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on") set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on")
set(EVMJIT OFF CACHE BOOL "Build a just-in-time compiler for EVM code (requires LLVM)") set(EVMJIT OFF CACHE BOOL "Build a just-in-time compiler for EVM code (requires LLVM)")
set(FATDB OFF CACHE BOOL "Build with ability to list entries in the Trie. Doubles DB size, slows everything down, but good for looking at state diffs and trie contents.") set(FATDB OFF CACHE BOOL "Build with ability to list entries in the Trie. Doubles DB size, slows everything down, but good for looking at state diffs and trie contents.")
set(JUSTTESTS OFF CACHE BOOL "Build only for tests.")
endfunction() endfunction()
@ -49,7 +50,7 @@ function(configureProject)
add_definitions(-DETH_FATDB) add_definitions(-DETH_FATDB)
endif() endif()
if (HEADLESS) if (HEADLESS OR JUSTTESTS)
add_definitions(-DETH_HEADLESS) add_definitions(-DETH_HEADLESS)
endif() endif()
endfunction() endfunction()

4
libdevcore/FixedHash.h

@ -65,10 +65,10 @@ public:
FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); } FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); }
/// Explicitly construct, copying from a byte array. /// Explicitly construct, copying from a byte array.
explicit FixedHash(bytes const& _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else if (_t != FailIfDifferent) { m_data.fill(0); auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } explicit FixedHash(bytes const& _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } }
/// Explicitly construct, copying from a byte array. /// Explicitly construct, copying from a byte array.
explicit FixedHash(bytesConstRef _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else if (_t != FailIfDifferent) { m_data.fill(0); auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } explicit FixedHash(bytesConstRef _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } }
/// Explicitly construct, copying from a bytes in memory with given pointer. /// Explicitly construct, copying from a bytes in memory with given pointer.
explicit FixedHash(byte const* _bs, ConstructFromPointerType) { memcpy(m_data.data(), _bs, N); } explicit FixedHash(byte const* _bs, ConstructFromPointerType) { memcpy(m_data.data(), _bs, N); }

6
libdevcrypto/MemoryDB.h

@ -51,8 +51,8 @@ public:
bool kill(h256 _h); bool kill(h256 _h);
void purge(); void purge();
bytes lookupAux(h256 _h) const { return asBytes(lookup(h256(sha3(_h).ref().cropped(16), h256::AlignRight))); } bytes lookupAux(h256 _h) const { auto h = aux(_h); return m_aux.count(h) ? m_aux.at(h) : bytes(); }
void insertAux(h256 _h, bytesConstRef _v) { return insert(h256(sha3(_h).ref().cropped(16), h256::AlignRight), _v); } void insertAux(h256 _h, bytesConstRef _v) { m_auxKey = aux(_h); m_aux[m_auxKey] = _v.toBytes(); }
std::set<h256> keys() const; std::set<h256> keys() const;
@ -61,7 +61,7 @@ protected:
std::map<h256, std::string> m_over; std::map<h256, std::string> m_over;
std::map<h256, unsigned> m_refCount; std::map<h256, unsigned> m_refCount;
std::set<h256> m_auxActive; h256 m_auxKey;
std::map<h256, bytes> m_aux; std::map<h256, bytes> m_aux;
mutable bool m_enforceRefs = false; mutable bool m_enforceRefs = false;

16
libdevcrypto/OverlayDB.cpp

@ -52,16 +52,8 @@ void OverlayDB::commit()
if (m_refCount[i.first]) if (m_refCount[i.first])
m_db->Put(m_writeOptions, ldb::Slice((char const*)i.first.data(), i.first.size), ldb::Slice(i.second.data(), i.second.size())); m_db->Put(m_writeOptions, ldb::Slice((char const*)i.first.data(), i.first.size), ldb::Slice(i.second.data(), i.second.size()));
} }
for (auto const& i: m_auxActive) if (m_auxKey && m_aux.count(m_auxKey))
if (m_aux.count(i)) m_db->Put(m_writeOptions, m_auxKey.ref(), bytesConstRef(&m_aux[m_auxKey]));
{
m_db->Put(m_writeOptions, i.ref(), bytesConstRef(&m_aux[i]));
cdebug << "Committing aux: " << i;
m_aux.erase(i);
}
cdebug << "Discarding " << keysOf(m_aux);
m_auxActive.clear();
m_aux.clear();
m_over.clear(); m_over.clear();
m_refCount.clear(); m_refCount.clear();
} }
@ -73,9 +65,7 @@ bytes OverlayDB::lookupAux(h256 _h) const
if (!ret.empty()) if (!ret.empty())
return ret; return ret;
std::string v; std::string v;
m_db->Get(m_readOptions, aux(_h).ref(), &v); m_db->Get(m_readOptions, _h.ref(), &v);
if (v.empty())
cwarn << "Aux not found: " << _h;
return asBytes(v); return asBytes(v);
} }

2
libdevcrypto/TrieDB.h

@ -408,7 +408,7 @@ public:
Super::setRoot(h256(Super::db()->lookupAux(m_secure.root()))); Super::setRoot(h256(Super::db()->lookupAux(m_secure.root())));
} }
h256 root() const { return m_secure.root(); } h256 root() const { const_cast<FatGenericTrieDB*>(this)->syncRoot(); return m_secure.root(); }
void insert(bytesConstRef _key, bytesConstRef _value) { Super::insert(_key, _value); m_secure.insert(_key, _value); syncRoot(); } void insert(bytesConstRef _key, bytesConstRef _value) { Super::insert(_key, _value); m_secure.insert(_key, _value); syncRoot(); }
void remove(bytesConstRef _key) { Super::remove(_key); m_secure.remove(_key); syncRoot(); } void remove(bytesConstRef _key) { Super::remove(_key); m_secure.remove(_key); syncRoot(); }

2
libethcore/CommonEth.cpp

@ -33,7 +33,7 @@ namespace eth
{ {
const unsigned c_protocolVersion = 55; const unsigned c_protocolVersion = 55;
const unsigned c_databaseVersion = 5 + const unsigned c_databaseVersion = 6 +
#if ETH_FATDB #if ETH_FATDB
1000 1000
#else #else

38
libethereum/State.h

@ -334,14 +334,36 @@ void commit(std::map<Address, Account> const& _cache, DB& _db, SecureTrieDB<Addr
_state.remove(i.first); _state.remove(i.first);
else else
{ {
SecureTrieDB<h256, DB> storageDB(&_db, i.second.baseRoot()); RLPStream s(4);
for (auto const& j: i.second.storageOverlay()) s << i.second.nonce() << i.second.balance();
if (j.second)
storageDB.insert(j.first, rlp(j.second)); if (i.second.storageOverlay().empty())
else {
storageDB.remove(j.first); assert(i.second.baseRoot());
assert(storageDB.root()); s.append(i.second.baseRoot());
s.append(storageDB.root()); }
else
{
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));
else
storageDB.remove(j.first);
assert(storageDB.root());
s.append(storageDB.root());
}
if (i.second.isFreshCode())
{
h256 ch = sha3(i.second.code());
_db.insert(ch, &i.second.code());
s << ch;
}
else
s << i.second.codeHash();
_state.insert(i.first, &s.out());
} }
} }
} }

62
test/trie.cpp

@ -74,68 +74,6 @@ BOOST_AUTO_TEST_CASE(fat_trie)
} }
} }
BOOST_AUTO_TEST_CASE(hex_encoded_securetrie_test)
{
string testPath = test::getTestPath();
testPath += "/TrieTests";
cnote << "Testing Secure Trie...";
js::mValue v;
string s = asString(contents(testPath + "/hex_encoded_securetrie_test.json"));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'hex_encoded_securetrie_test.json' is empty. Have you cloned the 'tests' repo branch develop?");
js::read_string(s, v);
for (auto& i: v.get_obj())
{
cnote << i.first;
js::mObject& o = i.second.get_obj();
vector<pair<string, string>> ss;
for (auto i: o["in"].get_obj())
{
ss.push_back(make_pair(i.first, i.second.get_str()));
if (!ss.back().first.find("0x"))
ss.back().first = asString(fromHex(ss.back().first.substr(2)));
if (!ss.back().second.find("0x"))
ss.back().second = asString(fromHex(ss.back().second.substr(2)));
}
for (unsigned j = 0; j < min(1000000000u, dev::test::fac((unsigned)ss.size())); ++j)
{
next_permutation(ss.begin(), ss.end());
MemoryDB m;
GenericTrieDB<MemoryDB> t(&m);
MemoryDB hm;
HashedGenericTrieDB<MemoryDB> ht(&hm);
MemoryDB fm;
FatGenericTrieDB<MemoryDB> ft(&fm);
t.init();
ht.init();
ft.init();
BOOST_REQUIRE(t.check(true));
BOOST_REQUIRE(ht.check(true));
BOOST_REQUIRE(ft.check(true));
for (auto const& k: ss)
{
t.insert(k.first, k.second);
ht.insert(k.first, k.second);
ft.insert(k.first, k.second);
BOOST_REQUIRE(t.check(true));
BOOST_REQUIRE(ht.check(true));
BOOST_REQUIRE(ft.check(true));
for (auto i = ft.begin(), j = t.begin(); i != ft.end() && j != t.end(); ++i, ++j)
{
BOOST_CHECK_EQUAL(i == ft.end(), j == t.end());
BOOST_REQUIRE((*i).first.toBytes() == (*j).first.toBytes());
BOOST_REQUIRE((*i).second.toBytes() == (*j).second.toBytes());
}
BOOST_CHECK_EQUAL(ht.root(), ft.root());
}
BOOST_REQUIRE(!o["root"].is_null());
BOOST_CHECK_EQUAL(o["root"].get_str(), "0x" + toHex(ht.root().asArray()));
BOOST_CHECK_EQUAL(o["root"].get_str(), "0x" + toHex(ft.root().asArray()));
}
}
}
BOOST_AUTO_TEST_CASE(trie_test_anyorder) BOOST_AUTO_TEST_CASE(trie_test_anyorder)
{ {
string testPath = test::getTestPath(); string testPath = test::getTestPath();

Loading…
Cancel
Save