From 1103fb92212df66193d161cd01c802d50ea5a521 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 6 May 2014 13:37:35 +0100 Subject: [PATCH] Much nicer State debug output. --- libethereum/State.cpp | 83 ++++++++++++++++++++++++++++++++++++++++--- libethereum/State.h | 53 +-------------------------- 2 files changed, 80 insertions(+), 56 deletions(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 4b8828f1c..88ecd10f2 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -684,9 +684,9 @@ u256 State::execute(bytesConstRef _rlp) Executive e(*this); e.setup(_rlp); -// cnote << "Executing " << e.t(); + cnote << "Executing " << e.t(); // cnote << m_state.root() << "\n" << m_state; -// cnote << *this; + cnote << *this; u256 startGasUSed = gasUsed(); if (startGasUSed + e.t().gas > m_currentBlock.gasLimit) @@ -695,11 +695,15 @@ u256 State::execute(bytesConstRef _rlp) e.go(); e.finalize(); + cnote << "Executed."; +// cnote << m_state.root() << "\n" << m_state; + cnote << *this; + commit(); -// cnote << "Executed."; + cnote << "Committed."; // cnote << m_state.root() << "\n" << m_state; -// cnote << *this; + cnote << *this; // Add to the user-originated transactions that we've executed. m_transactions.push_back(TransactionReceipt(e.t(), m_state.root(), startGasUSed + e.gasUsed())); @@ -835,3 +839,74 @@ void State::unapplyRewards(Addresses const& _uncleAddresses) } subBalance(m_currentBlock.coinbaseAddress, r); } + +std::ostream& eth::operator<<(std::ostream& _out, State const& _s) +{ + _out << "--- " << _s.rootHash() << std::endl; + std::set
d; + std::set
dtr; + auto trie = TrieDB(const_cast(&_s.m_db), _s.rootHash()); + for (auto i: trie) + d.insert(i.first), dtr.insert(i.first); + for (auto i: _s.m_cache) + d.insert(i.first); + + for (auto i: d) + { + auto it = _s.m_cache.find(i); + AddressState* cache = it != _s.m_cache.end() ? &it->second : nullptr; + auto rlpString = trie.at(i); + RLP r(dtr.count(i) ? rlpString : ""); + assert(cache || r); + + if (cache && !cache->isAlive()) + _out << "XXX " << i << std::endl; + else + { + string lead = (cache ? r ? " * " : " + " : " "); + if (cache && r && (cache->balance() == r[0].toInt() && cache->nonce() == r[1].toInt())) + lead = " . "; + + stringstream contout; + + if ((!cache || cache->codeBearing()) && (!r || r[3].toHash() != EmptySHA3)) + { + std::map mem; + std::set back; + std::set delta; + std::set cached; + if (r) + { + TrieDB memdb(const_cast(&_s.m_db), r[2].toHash()); // promise we won't alter the overlay! :) + for (auto const& j: memdb) + mem[j.first] = RLP(j.second).toInt(), back.insert(j.first); + } + if (cache) + for (auto const& j: cache->storage()) + if ((!mem.count(j.first) && j.second) || (mem.count(j.first) && mem.at(j.first) != j.second)) + mem[j.first] = j.second, delta.insert(j.first); + else if (j.second) + cached.insert(j.first); + if (delta.size()) + lead = (lead == " . ") ? "*.* " : "*** "; + + contout << " @:"; + if (delta.size()) + contout << "???"; + else + contout << r[2].toHash(); + contout << " $:" << (cache ? cache->isFreshCode() ? h256() : cache->codeHash() : r[3].toHash()); + + for (auto const& j: mem) + if (j.second) + contout << std::endl << (delta.count(j.first) ? back.count(j.first) ? " * " : " + " : cached.count(j.first) ? " . " : " ") << std::hex << std::setw(64) << j.first << ": " << std::setw(0) << j.second ; + else + contout << std::endl << "XXX " << std::hex << std::setw(64) << j.first << ""; + } + else + contout << " [SIMPLE]"; + _out << lead << i << ": " << std::dec << (cache ? cache->balance() : r[0].toInt()) << " #:" << (cache ? cache->nonce() : r[1].toInt()) << contout.str() << std::endl; + } + } + return _out; +} diff --git a/libethereum/State.h b/libethereum/State.h index 5256a1d29..cfce5f543 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -273,58 +273,7 @@ private: friend std::ostream& operator<<(std::ostream& _out, State const& _s); }; -// TODO: Update for latest AddressState/StateTrie changes. -// trie should always be used as base. AddressState just contains overlay. -inline std::ostream& operator<<(std::ostream& _out, State const& _s) -{ - _out << "--- " << _s.rootHash() << std::endl; - std::set
d; - for (auto const& i: TrieDB(const_cast(&_s.m_db), _s.rootHash())) - { - auto it = _s.m_cache.find(i.first); - if (it == _s.m_cache.end()) - { - RLP r(i.second); - _out << "[ ]" << i.first << ": " << std::dec << r[1].toInt() << "@" << r[0].toInt(); - if (r.itemCount() == 4) - { - _out << " *" << r[2].toHash(); - TrieDB memdb(const_cast(&_s.m_db), r[2].toHash()); // promise we won't alter the overlay! :) - std::map mem; - for (auto const& j: memdb) - { - _out << std::endl << " [" << j.first << ":" << toHex(j.second) << "]"; - mem[j.first] = RLP(j.second).toInt(); - } - _out << std::endl << mem; - } - _out << std::endl; - } - else - d.insert(i.first); - } - for (auto i: _s.m_cache) - if (!i.second.isAlive()) - _out << "[XXX " << i.first << std::endl; - else - { - _out << (d.count(i.first) ? "[ ! " : "[ * ") << "]" << i.first << ": " << std::dec << i.second.nonce() << "@" << i.second.balance(); - if (i.second.codeBearing()) - { - _out << " *" << i.second.oldRoot(); - TrieDB memdb(const_cast(&_s.m_db), i.second.oldRoot()); // promise we won't alter the overlay! :) - std::map mem; - for (auto const& j: memdb) - { - _out << std::endl << " [" << j.first << ":" << toHex(j.second) << "]"; - mem[j.first] = RLP(j.second).toInt(); - } - _out << std::endl << mem; - } - _out << std::endl; - } - return _out; -} +std::ostream& operator<<(std::ostream& _out, State const& _s); template void commit(std::map const& _cache, DB& _db, TrieDB& _state)