diff --git a/CMakeLists.txt b/CMakeLists.txt index 2afe78bb8..5ff81e153 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 1da3f95d6..49c6ed2bf 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/Common.cpp b/libethcore/Common.cpp index a9095c5cd..f47bb002b 100644 --- a/libethcore/Common.cpp +++ b/libethcore/Common.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 eedf324fb..00a735291 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();