diff --git a/libethereum/AddressState.h b/libethereum/AddressState.h index 939ebf1ff..5bfb6b0ab 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 _nonce, u256 _balance, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_balance(_balance), m_nonce(_nonce), m_storageRoot(_contractRoot), m_codeHash(_codeHash) {} + AddressState(u256 _balance, u256 _nonce, 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_nonce; u256 m_balance; + u256 m_nonce; /// 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 e9de095ee..40b587d8d 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -115,12 +115,12 @@ struct CachedAddressState u256 balance() const { - return r ? s ? s->balance() : r[1].toInt() : 0; + return r ? s ? s->balance() : r[0].toInt() : 0; } u256 nonce() const { - return r ? s ? s->nonce() : r[0].toInt() : 0; + return r ? s ? s->nonce() : r[1].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)[1].toInt(); + ret[i.first] = RLP(i.second)[0].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->nonce() == r[0].toInt() && cache->balance() == r[1].toInt()) + if (cache && r && (cache->balance() == r[0].toInt() && cache->nonce() == 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->nonce() : r[0].toInt()) << " #:" << (cache ? cache->balance() : r[1].toInt()) << contout.str() << std::endl; + _out << lead << i << ": " << std::dec << (cache ? cache->balance() : r[0].toInt()) << " #:" << (cache ? cache->nonce() : 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.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.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.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 787b615d8..eac800447 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -338,7 +338,7 @@ void commit(std::map const& _cache, DB& _db, TrieDB(1, 5)(s_eng), ' '); - char const n[] = "qwertyuiop";//asdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890"; + std::string ret(std::uniform_int_distribution(4, 10)(s_eng), ' '); + char const n[] = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890"; 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 0c9ca6206..d3a8e3710 100644 --- a/libethsupport/TrieDB.cpp +++ b/libethsupport/TrieDB.cpp @@ -29,17 +29,6 @@ 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 5fda2bc03..ab42fec17 100644 --- a/libethsupport/TrieDB.h +++ b/libethsupport/TrieDB.h @@ -43,7 +43,7 @@ public: BasicMap() {} void clear() { m_over.clear(); } - std::map get() const; + std::map const& get() const { return m_over; } std::string lookup(h256 _h) const; bool exists(h256 _h) const; @@ -160,60 +160,48 @@ public: void debugPrint() {} - void descendKey(h256 _k, std::set& _keyMask, bool _wasExt) const + void descendKey(h256 _k, std::set& _keyMask) const { _keyMask.erase(_k); - if (_k == m_root && _k == c_shaNull) // root allowed to be empty + if (_k == m_root && _k == EmptySHA3) // root allowed to be empty return; - descendList(RLP(node(_k)), _keyMask, _wasExt); // if not, it must be a list + descend(RLP(node(_k)), _keyMask); } - void descendEntry(RLP const& _r, std::set& _keyMask, bool _wasExt) const + void descendEntry(RLP const& _r, std::set& _keyMask) const { if (_r.isData() && _r.size() == 32) - descendKey(_r.toHash(), _keyMask, _wasExt); + descendKey(_r.toHash(), _keyMask); else if (_r.isList()) - descendList(_r, _keyMask, _wasExt); + descend(_r, _keyMask); else throw InvalidTrie(); } - void descendList(RLP const& _r, std::set& _keyMask, bool _wasExt) const + void descend(RLP const& _r, std::set& _keyMask) const { - if (_r.isList() && _r.itemCount() == 2 && !_wasExt) + if (_r.isList() && _r.size() == 2) { if (!isLeaf(_r)) // don't go down leaves - descendEntry(_r[1], _keyMask, true); + descendEntry(_r[1], _keyMask); } - else if (_r.isList() && _r.itemCount() == 17) + else if (_r.isList() && _r.size() == 17) { for (unsigned i = 0; i < 16; ++i) if (!_r[i].isEmpty()) // 16 branches are allowed to be empty - descendEntry(_r[i], _keyMask, false); + descendEntry(_r[i], _keyMask); } else throw InvalidTrie(); } - std::set leftOvers() const + std::set check() const { std::set k = m_db->keys(); - descendKey(m_root, k, false); + descendKey(m_root, k); 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); @@ -898,7 +886,6 @@ 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 66f479f8c..fde47e661 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 * sizeof(_T)); } + std::string toString() const { return std::string((char const*)m_data, ((char const*)m_data) + m_count); } 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 f30fba956..299cda5f6 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -385,8 +385,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) auto end = m_asm.appendJumpI(); m_asm.onePath(); m_asm.otherPath(); - m_asm.append(code[1].m_asm, 0); - m_asm << end.tag(); + m_asm << code[1].m_asm << end.tag(); m_asm.donePaths(); } else if (us == "WHILE") diff --git a/test/main.cpp b/test/main.cpp index 225f1762e..42e673446 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -45,12 +45,11 @@ BOOST_AUTO_TEST_CASE(basic_tests) cdebug << "Stress-testing Trie..."; { BasicMap m; - BasicMap dm; - EnforceRefs e(dm, true); - GenericTrieDB d(&dm); + EnforceRefs e(m, true); + GenericTrieDB d(&m); d.init(); // initialise as empty tree. MemTrie t; - BOOST_REQUIRE(d.check()); + assert(d.check().empty()); for (int a = 0; a < 100; ++a) { StringMap m; @@ -58,55 +57,22 @@ BOOST_AUTO_TEST_CASE(basic_tests) { auto k = randomWord(); auto v = toString(i); - cdebug << k << v; - m[k] = v; + m.insert(make_pair(k, v)); t.insert(k, v); d.insert(k, v); - BOOST_REQUIRE_EQUAL(hash256(m), t.hash256()); - BOOST_REQUIRE_EQUAL(hash256(m), d.root()); - BOOST_REQUIRE(d.check()); + assert(hash256(m) == t.hash256()); + assert(hash256(m) == d.root()); + assert(d.check().empty()); } 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); - 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()); + assert(hash256(m) == t.hash256()); + assert(hash256(m) == d.root()); + assert(d.check().empty()); } } } diff --git a/test/trie.cpp b/test/trie.cpp index 4ac432010..f3ff3ef4a 100644 --- a/test/trie.cpp +++ b/test/trie.cpp @@ -49,6 +49,7 @@ 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?"); @@ -56,7 +57,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())); @@ -66,14 +67,9 @@ 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(t.check()); - } - BOOST_REQUIRE(!o["root"].is_null()); + BOOST_REQUIRE(!o["root"].is_null()); BOOST_CHECK(o["root"].get_str() == toHex(t.root().asArray()) ); } } @@ -85,9 +81,8 @@ inline h256 stringMapHash256(StringMap const& _s) return hash256(_s); } -BOOST_AUTO_TEST_CASE(moreTrieTests) +int trieTest() { - cnote << "Testing Trie more..."; #if 0 // More tests... { @@ -158,7 +153,6 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) cout << RLP(t.rlp()) << endl; cout << toHex(t.rlp()) << endl; } -#endif { BasicMap m; GenericTrieDB d(&m); @@ -172,21 +166,20 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) 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; - BOOST_REQUIRE(d.check()); - BOOST_REQUIRE_EQUAL(t.hash256(), hash256(s)); - BOOST_REQUIRE_EQUAL(d.root(), hash256(s)); + assert(t.hash256() == hash256(s)); + assert(d.root() == hash256(s)); for (auto const& i: s) { (void)i; - BOOST_REQUIRE_EQUAL(t.at(i.first), i.second); - BOOST_REQUIRE_EQUAL(d.at(i.first), i.second); + assert(t.at(i.first) == i.second); + assert(d.at(i.first) == i.second); } }; @@ -196,23 +189,22 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) 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; - 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)); + assert(t.at(a).empty()); + assert(d.at(string(a)).empty()); + assert(t.hash256() == hash256(s)); + assert(d.root() == hash256(s)); for (auto const& i: s) { (void)i; - BOOST_REQUIRE_EQUAL(t.at(i.first), i.second); - BOOST_REQUIRE_EQUAL(d.at(i.first), i.second); + assert(t.at(i.first) == i.second); + assert(d.at(i.first) == i.second); } }; @@ -227,5 +219,36 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) 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; }