From ae1cb7f1ffb0d2c016ea677c08a3e0483ed98ac8 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 1 Mar 2015 22:54:05 +0100 Subject: [PATCH] State integration test. Fixes to the FatTrie. --- CMakeLists.txt | 3 +- libdevcore/FixedHash.h | 4 +-- libdevcrypto/MemoryDB.h | 6 ++-- libdevcrypto/OverlayDB.cpp | 16 ++-------- libdevcrypto/TrieDB.h | 2 +- libethcore/CommonEth.cpp | 2 +- libethereum/State.h | 38 ++++++++++++++++++----- test/trie.cpp | 62 -------------------------------------- 8 files changed, 42 insertions(+), 91 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e86ded470..ba25e74ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ function(createDefaultCacheConfig) 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(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() @@ -49,7 +50,7 @@ function(configureProject) add_definitions(-DETH_FATDB) endif() - if (HEADLESS) + if (HEADLESS OR JUSTTESTS) add_definitions(-DETH_HEADLESS) endif() endfunction() diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index dceb1d70a..eec988d76 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -65,10 +65,10 @@ public: FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); } /// 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(_b.size(), N)); else if (_t != FailIfDifferent) { m_data.fill(0); auto c = std::min(_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(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min(_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. - explicit FixedHash(bytesConstRef _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min(_b.size(), N)); else if (_t != FailIfDifferent) { m_data.fill(0); auto c = std::min(_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(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min(_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. explicit FixedHash(byte const* _bs, ConstructFromPointerType) { memcpy(m_data.data(), _bs, N); } diff --git a/libdevcrypto/MemoryDB.h b/libdevcrypto/MemoryDB.h index 2f4233f01..ecda3b6ec 100644 --- a/libdevcrypto/MemoryDB.h +++ b/libdevcrypto/MemoryDB.h @@ -51,8 +51,8 @@ public: bool kill(h256 _h); void purge(); - bytes lookupAux(h256 _h) const { return asBytes(lookup(h256(sha3(_h).ref().cropped(16), h256::AlignRight))); } - void insertAux(h256 _h, bytesConstRef _v) { return insert(h256(sha3(_h).ref().cropped(16), h256::AlignRight), _v); } + 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) { m_auxKey = aux(_h); m_aux[m_auxKey] = _v.toBytes(); } std::set keys() const; @@ -61,7 +61,7 @@ protected: std::map m_over; std::map m_refCount; - std::set m_auxActive; + h256 m_auxKey; std::map m_aux; mutable bool m_enforceRefs = false; diff --git a/libdevcrypto/OverlayDB.cpp b/libdevcrypto/OverlayDB.cpp index ffe996bb6..4f237becb 100644 --- a/libdevcrypto/OverlayDB.cpp +++ b/libdevcrypto/OverlayDB.cpp @@ -52,16 +52,8 @@ void OverlayDB::commit() 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())); } - for (auto const& i: m_auxActive) - if (m_aux.count(i)) - { - 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(); + if (m_auxKey && m_aux.count(m_auxKey)) + m_db->Put(m_writeOptions, m_auxKey.ref(), bytesConstRef(&m_aux[m_auxKey])); m_over.clear(); m_refCount.clear(); } @@ -73,9 +65,7 @@ bytes OverlayDB::lookupAux(h256 _h) const if (!ret.empty()) return ret; std::string v; - m_db->Get(m_readOptions, aux(_h).ref(), &v); - if (v.empty()) - cwarn << "Aux not found: " << _h; + m_db->Get(m_readOptions, _h.ref(), &v); return asBytes(v); } diff --git a/libdevcrypto/TrieDB.h b/libdevcrypto/TrieDB.h index e00e03f44..f32170cd4 100644 --- a/libdevcrypto/TrieDB.h +++ b/libdevcrypto/TrieDB.h @@ -408,7 +408,7 @@ public: Super::setRoot(h256(Super::db()->lookupAux(m_secure.root()))); } - h256 root() const { return m_secure.root(); } + h256 root() const { const_cast(this)->syncRoot(); return m_secure.root(); } 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(); } diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp index eba10e321..ad41780e9 100644 --- a/libethcore/CommonEth.cpp +++ b/libethcore/CommonEth.cpp @@ -33,7 +33,7 @@ namespace eth { const unsigned c_protocolVersion = 55; -const unsigned c_databaseVersion = 5 + +const unsigned c_databaseVersion = 6 + #if ETH_FATDB 1000 #else diff --git a/libethereum/State.h b/libethereum/State.h index 7c3cec2a6..a496a4a03 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -334,14 +334,36 @@ void commit(std::map const& _cache, DB& _db, SecureTrieDB 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()); + RLPStream s(4); + s << i.second.nonce() << i.second.balance(); + + if (i.second.storageOverlay().empty()) + { + assert(i.second.baseRoot()); + s.append(i.second.baseRoot()); + } + else + { + SecureTrieDB 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()); } } } diff --git a/test/trie.cpp b/test/trie.cpp index 9e59dd316..84d0e846f 100644 --- a/test/trie.cpp +++ b/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> 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 t(&m); - MemoryDB hm; - HashedGenericTrieDB ht(&hm); - MemoryDB fm; - FatGenericTrieDB 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) { string testPath = test::getTestPath();