From b12d91e726ae5d1742e6d828c2cb5b694ffdf8a3 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 29 May 2014 20:30:56 +0200 Subject: [PATCH] Fix for unless/when. --- libethereum/AddressState.h | 4 +- libethereum/State.cpp | 22 +++++------ libethereum/State.h | 2 +- libethsupport/CommonData.cpp | 4 +- libethsupport/TrieDB.cpp | 11 ++++++ libethsupport/TrieDB.h | 41 +++++++++++++------- libethsupport/vector_ref.h | 2 +- liblll/CodeFragment.cpp | 3 +- test/main.cpp | 54 +++++++++++++++++++++----- test/trie.cpp | 75 +++++++++++++----------------------- 10 files changed, 127 insertions(+), 91 deletions(-) diff --git a/libethereum/AddressState.h b/libethereum/AddressState.h index 5bfb6b0ab..939ebf1ff 100644 --- a/libethereum/AddressState.h +++ b/libethereum/AddressState.h @@ -33,7 +33,7 @@ class AddressState { public: AddressState(): m_isAlive(false), m_balance(0), m_nonce(0) {} - AddressState(u256 _balance, u256 _nonce, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_balance(_balance), m_nonce(_nonce), m_storageRoot(_contractRoot), m_codeHash(_codeHash) {} + AddressState(u256 _nonce, u256 _balance, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_balance(_balance), m_nonce(_nonce), m_storageRoot(_contractRoot), m_codeHash(_codeHash) {} void kill() { m_isAlive = false; m_storageOverlay.clear(); m_codeHash = EmptySHA3; m_storageRoot = h256(); m_balance = 0; m_nonce = 0; } bool isAlive() const { return m_isAlive; } @@ -61,8 +61,8 @@ public: private: bool m_isAlive; bool m_gotCode; - u256 m_balance; u256 m_nonce; + u256 m_balance; /// The base storage root. Used with the state DB to give a base to the storage. m_storageOverlay is overlaid on this and takes precedence for all values set. h256 m_storageRoot; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 40b587d8d..e9de095ee 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -115,12 +115,12 @@ struct CachedAddressState u256 balance() const { - return r ? s ? s->balance() : r[0].toInt() : 0; + return r ? s ? s->balance() : r[1].toInt() : 0; } u256 nonce() const { - return r ? s ? s->nonce() : r[1].toInt() : 0; + return r ? s ? s->nonce() : r[0].toInt() : 0; } bytes code() const @@ -323,7 +323,7 @@ map State::addresses() const 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)[0].toInt(); + ret[i.first] = RLP(i.second)[1].toInt(); return ret; } @@ -1098,7 +1098,7 @@ std::ostream& eth::operator<<(std::ostream& _out, State const& _s) else { string lead = (cache ? r ? " * " : " + " : " "); - if (cache && r && (cache->balance() == r[0].toInt() && cache->nonce() == r[1].toInt())) + if (cache && r && cache->nonce() == r[0].toInt() && cache->balance() == r[1].toInt()) lead = " . "; stringstream contout; @@ -1142,7 +1142,7 @@ std::ostream& eth::operator<<(std::ostream& _out, State const& _s) } else contout << " [SIMPLE]"; - _out << lead << i << ": " << std::dec << (cache ? cache->balance() : r[0].toInt()) << " #:" << (cache ? cache->nonce() : r[1].toInt()) << contout.str() << std::endl; + _out << lead << i << ": " << std::dec << (cache ? cache->nonce() : r[0].toInt()) << " #:" << (cache ? cache->balance() : r[1].toInt()) << contout.str() << std::endl; } } return _out; @@ -1167,18 +1167,18 @@ std::ostream& eth::operator<<(std::ostream& _out, AccountDiff const& _s) if (!_s.exist.to()) return _out; - if (_s.balance) - { - _out << std::dec << _s.balance.to() << " "; - if (_s.balance.from()) - _out << "(" << std::showpos << (((bigint)_s.balance.to()) - ((bigint)_s.balance.from())) << std::noshowpos << ") "; - } if (_s.nonce) { _out << std::dec << "#" << _s.nonce.to() << " "; if (_s.nonce.from()) _out << "(" << std::showpos << (((bigint)_s.nonce.to()) - ((bigint)_s.nonce.from())) << std::noshowpos << ") "; } + if (_s.balance) + { + _out << std::dec << _s.balance.to() << " "; + if (_s.balance.from()) + _out << "(" << std::showpos << (((bigint)_s.balance.to()) - ((bigint)_s.balance.from())) << std::noshowpos << ") "; + } if (_s.code) _out << "$" << std::hex << _s.code.to() << " (" << _s.code.from() << ") "; for (pair> const& i: _s.storage) diff --git a/libethereum/State.h b/libethereum/State.h index eac800447..787b615d8 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -338,7 +338,7 @@ void commit(std::map const& _cache, DB& _db, TrieDB(4, 10)(s_eng), ' '); - char const n[] = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890"; + std::string ret(std::uniform_int_distribution(1, 5)(s_eng), ' '); + char const n[] = "qwertyuiop";//asdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890"; std::uniform_int_distribution d(0, sizeof(n) - 2); for (char& c: ret) c = n[d(s_eng)]; diff --git a/libethsupport/TrieDB.cpp b/libethsupport/TrieDB.cpp index d3a8e3710..0c9ca6206 100644 --- a/libethsupport/TrieDB.cpp +++ b/libethsupport/TrieDB.cpp @@ -29,6 +29,17 @@ namespace eth const h256 c_shaNull = sha3(rlp("")); +std::map BasicMap::get() const +{ + if (!m_enforceRefs) + return m_over; + std::map ret; + for (auto const& i: m_refCount) + if (i.second) + ret.insert(*m_over.find(i.first)); + return ret; +} + std::string BasicMap::lookup(h256 _h) const { auto it = m_over.find(_h); diff --git a/libethsupport/TrieDB.h b/libethsupport/TrieDB.h index ab42fec17..5fda2bc03 100644 --- a/libethsupport/TrieDB.h +++ b/libethsupport/TrieDB.h @@ -43,7 +43,7 @@ public: BasicMap() {} void clear() { m_over.clear(); } - std::map const& get() const { return m_over; } + std::map get() const; std::string lookup(h256 _h) const; bool exists(h256 _h) const; @@ -160,48 +160,60 @@ public: void debugPrint() {} - void descendKey(h256 _k, std::set& _keyMask) const + void descendKey(h256 _k, std::set& _keyMask, bool _wasExt) const { _keyMask.erase(_k); - if (_k == m_root && _k == EmptySHA3) // root allowed to be empty + if (_k == m_root && _k == c_shaNull) // root allowed to be empty return; - descend(RLP(node(_k)), _keyMask); + descendList(RLP(node(_k)), _keyMask, _wasExt); // if not, it must be a list } - void descendEntry(RLP const& _r, std::set& _keyMask) const + void descendEntry(RLP const& _r, std::set& _keyMask, bool _wasExt) const { if (_r.isData() && _r.size() == 32) - descendKey(_r.toHash(), _keyMask); + descendKey(_r.toHash(), _keyMask, _wasExt); else if (_r.isList()) - descend(_r, _keyMask); + descendList(_r, _keyMask, _wasExt); else throw InvalidTrie(); } - void descend(RLP const& _r, std::set& _keyMask) const + void descendList(RLP const& _r, std::set& _keyMask, bool _wasExt) const { - if (_r.isList() && _r.size() == 2) + if (_r.isList() && _r.itemCount() == 2 && !_wasExt) { if (!isLeaf(_r)) // don't go down leaves - descendEntry(_r[1], _keyMask); + descendEntry(_r[1], _keyMask, true); } - else if (_r.isList() && _r.size() == 17) + else if (_r.isList() && _r.itemCount() == 17) { for (unsigned i = 0; i < 16; ++i) if (!_r[i].isEmpty()) // 16 branches are allowed to be empty - descendEntry(_r[i], _keyMask); + descendEntry(_r[i], _keyMask, false); } else throw InvalidTrie(); } - std::set check() const + std::set leftOvers() const { std::set k = m_db->keys(); - descendKey(m_root, k); + descendKey(m_root, k, false); return k; } + bool check() const + { + try + { + return leftOvers().empty(); + } + catch (...) + { + return false; + } + } + std::string at(bytesConstRef _key) const; void insert(bytesConstRef _key, bytesConstRef _value); void remove(bytesConstRef _key); @@ -886,6 +898,7 @@ template bytes GenericTrieDB::branch(RLP const& _orig) // ::operator<<(std::cout << "branch ", _orig) << std::endl; assert(_orig.isList() && _orig.itemCount() == 2); + killNode(_orig); auto k = keyOf(_orig); RLPStream r(17); diff --git a/libethsupport/vector_ref.h b/libethsupport/vector_ref.h index fde47e661..66f479f8c 100644 --- a/libethsupport/vector_ref.h +++ b/libethsupport/vector_ref.h @@ -33,7 +33,7 @@ public: bool contentsEqual(std::vector const& _c) const { return _c.size() == m_count && !memcmp(_c.data(), m_data, m_count); } std::vector toVector() const { return std::vector(m_data, m_data + m_count); } std::vector toBytes() const { return std::vector((unsigned char const*)m_data, m_data + m_count * sizeof(_T)); } - std::string toString() const { return std::string((char const*)m_data, ((char const*)m_data) + m_count); } + std::string toString() const { return std::string((char const*)m_data, ((char const*)m_data) + m_count * sizeof(_T)); } template operator vector_ref<_T2>() const { assert(m_count * sizeof(_T) / sizeof(_T2) * sizeof(_T2) / sizeof(_T) == m_count); return vector_ref<_T2>((_T2*)m_data, m_count * sizeof(_T) / sizeof(_T2)); } _T* data() const { return m_data; } diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 299cda5f6..f30fba956 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -385,7 +385,8 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) auto end = m_asm.appendJumpI(); m_asm.onePath(); m_asm.otherPath(); - m_asm << code[1].m_asm << end.tag(); + m_asm.append(code[1].m_asm, 0); + m_asm << end.tag(); m_asm.donePaths(); } else if (us == "WHILE") diff --git a/test/main.cpp b/test/main.cpp index 42e673446..225f1762e 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -45,11 +45,12 @@ BOOST_AUTO_TEST_CASE(basic_tests) cdebug << "Stress-testing Trie..."; { BasicMap m; - EnforceRefs e(m, true); - GenericTrieDB d(&m); + BasicMap dm; + EnforceRefs e(dm, true); + GenericTrieDB d(&dm); d.init(); // initialise as empty tree. MemTrie t; - assert(d.check().empty()); + BOOST_REQUIRE(d.check()); for (int a = 0; a < 100; ++a) { StringMap m; @@ -57,22 +58,55 @@ BOOST_AUTO_TEST_CASE(basic_tests) { auto k = randomWord(); auto v = toString(i); - m.insert(make_pair(k, v)); + cdebug << k << v; + m[k] = v; t.insert(k, v); d.insert(k, v); - assert(hash256(m) == t.hash256()); - assert(hash256(m) == d.root()); - assert(d.check().empty()); + BOOST_REQUIRE_EQUAL(hash256(m), t.hash256()); + BOOST_REQUIRE_EQUAL(hash256(m), d.root()); + BOOST_REQUIRE(d.check()); } while (!m.empty()) { auto k = m.begin()->first; + auto v = m.begin()->second; + cdebug << k << m.size(); d.remove(k); t.remove(k); m.erase(k); - assert(hash256(m) == t.hash256()); - assert(hash256(m) == d.root()); - assert(d.check().empty()); + if (!d.check()) + { + cwarn << m; + for (auto i: d) + cwarn << i.first.toString() << i.second.toString(); + + BasicMap dm2; + EnforceRefs e2(dm2, true); + GenericTrieDB d2(&dm2); + d2.init(); // initialise as empty tree. + for (auto i: d) + d2.insert(i.first, i.second); + + cwarn << "Good:" << d2.root(); + for (auto i: dm2.get()) + cwarn << i.first.abridged() << ": " << RLP(i.second); + cwarn << "Broken:" << d.root(); // Leaves an extension -> extension (3c1... -> 742...) + for (auto i: dm.get()) + cwarn << i.first.abridged() << ": " << RLP(i.second); + + d2.insert(k, v); + cwarn << "Pres:" << d2.root(); + for (auto i: dm2.get()) + cwarn << i.first.abridged() << ": " << RLP(i.second); + g_logVerbosity = 99; + d2.remove(k); + g_logVerbosity = 4; + + cwarn << "Good?" << d2.root(); + } + BOOST_REQUIRE(d.check()); + BOOST_REQUIRE_EQUAL(hash256(m), t.hash256()); + BOOST_REQUIRE_EQUAL(hash256(m), d.root()); } } } diff --git a/test/trie.cpp b/test/trie.cpp index f3ff3ef4a..4ac432010 100644 --- a/test/trie.cpp +++ b/test/trie.cpp @@ -49,7 +49,6 @@ namespace eth BOOST_AUTO_TEST_CASE(trie_tests) { cnote << "Testing Trie..."; - js::mValue v; string s = asString(contents("../../../tests/trietest.json")); BOOST_REQUIRE_MESSAGE( s.length() > 0, "Contents of 'trietest.json' is empty. Have you cloned the 'tests' repo branch develop?"); @@ -57,7 +56,7 @@ BOOST_AUTO_TEST_CASE(trie_tests) for (auto& i: v.get_obj()) { js::mObject& o = i.second.get_obj(); - cnote << i.first; +// cnote << i.first; vector> ss; for (auto& i: o["in"].get_obj()) ss.push_back(make_pair(i.first, i.second.get_str())); @@ -67,9 +66,14 @@ BOOST_AUTO_TEST_CASE(trie_tests) BasicMap m; GenericTrieDB t(&m); t.init(); + BOOST_REQUIRE(t.check()); for (auto const& k: ss) + { +// cdebug << k.first << k.second; t.insert(k.first, k.second); - BOOST_REQUIRE(!o["root"].is_null()); + BOOST_REQUIRE(t.check()); + } + BOOST_REQUIRE(!o["root"].is_null()); BOOST_CHECK(o["root"].get_str() == toHex(t.root().asArray()) ); } } @@ -81,8 +85,9 @@ inline h256 stringMapHash256(StringMap const& _s) return hash256(_s); } -int trieTest() +BOOST_AUTO_TEST_CASE(moreTrieTests) { + cnote << "Testing Trie more..."; #if 0 // More tests... { @@ -153,6 +158,7 @@ int trieTest() cout << RLP(t.rlp()) << endl; cout << toHex(t.rlp()) << endl; } +#endif { BasicMap m; GenericTrieDB d(&m); @@ -166,20 +172,21 @@ int trieTest() t.insert(a, b); s[a] = b; - cout << endl << "-------------------------------" << endl; + /*cout << endl << "-------------------------------" << endl; cout << a << " -> " << b << endl; cout << d; cout << m; cout << d.root() << endl; - cout << hash256(s) << endl; + cout << hash256(s) << endl;*/ - assert(t.hash256() == hash256(s)); - assert(d.root() == hash256(s)); + BOOST_REQUIRE(d.check()); + BOOST_REQUIRE_EQUAL(t.hash256(), hash256(s)); + BOOST_REQUIRE_EQUAL(d.root(), hash256(s)); for (auto const& i: s) { (void)i; - assert(t.at(i.first) == i.second); - assert(d.at(i.first) == i.second); + BOOST_REQUIRE_EQUAL(t.at(i.first), i.second); + BOOST_REQUIRE_EQUAL(d.at(i.first), i.second); } }; @@ -189,22 +196,23 @@ int trieTest() t.remove(a); d.remove(string(a)); - cout << endl << "-------------------------------" << endl; + /*cout << endl << "-------------------------------" << endl; cout << "X " << a << endl; cout << d; cout << m; cout << d.root() << endl; - cout << hash256(s) << endl; + cout << hash256(s) << endl;*/ - assert(t.at(a).empty()); - assert(d.at(string(a)).empty()); - assert(t.hash256() == hash256(s)); - assert(d.root() == hash256(s)); + BOOST_REQUIRE(d.check()); + BOOST_REQUIRE(t.at(a).empty()); + BOOST_REQUIRE(d.at(string(a)).empty()); + BOOST_REQUIRE_EQUAL(t.hash256(), hash256(s)); + BOOST_REQUIRE_EQUAL(d.root(), hash256(s)); for (auto const& i: s) { (void)i; - assert(t.at(i.first) == i.second); - assert(d.at(i.first) == i.second); + BOOST_REQUIRE_EQUAL(t.at(i.first), i.second); + BOOST_REQUIRE_EQUAL(d.at(i.first), i.second); } }; @@ -219,36 +227,5 @@ int trieTest() remove("doge"); remove("doe"); } -#endif - { - BasicMap m; - GenericTrieDB d(&m); - d.init(); // initialise as empty tree. - MemTrie t; - for (int a = 0; a < 20; ++a) - { - StringMap m; - for (int i = 0; i < 20; ++i) - { - auto k = randomWord(); - auto v = toString(i); - m.insert(make_pair(k, v)); - t.insert(k, v); - d.insert(k, v); - assert(hash256(m) == t.hash256()); - assert(hash256(m) == d.root()); - } - while (!m.empty()) - { - auto k = m.begin()->first; - d.remove(k); - t.remove(k); - m.erase(k); - assert(hash256(m) == t.hash256()); - assert(hash256(m) == d.root()); - } - } - } - return 0; }