Browse Source

Pending transaction inspection.

cl-refactor
Gav Wood 11 years ago
parent
commit
618571babd
  1. 21
      alethzero/Main.ui
  2. 79
      alethzero/MainWin.cpp
  3. 1
      alethzero/MainWin.h
  4. 5
      libethcore/TrieDB.h
  5. 24
      libethereum/State.cpp
  6. 8
      libethereum/State.h

21
alethzero/Main.ui

@ -370,7 +370,7 @@
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>0</number>
</property>
@ -387,13 +387,20 @@
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="transactionQueue">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
<widget class="QSplitter" name="splitter_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QListWidget" name="transactionQueue">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QTextBrowser" name="pendingInfo">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</widget>
</item>
</layout>

79
alethzero/MainWin.cpp

@ -58,6 +58,7 @@ using eth::simpleDebugOut;
using eth::toLog2;
using eth::toString;
using eth::units;
using eth::operator<<;
// vars
using eth::g_logPost;
@ -407,7 +408,7 @@ eth::State const& Main::state() const
void Main::refresh(bool _override)
{
m_client->lock();
eth::ClientGuard g(m_client.get());
auto const& st = state();
bool c = m_client->changed();
@ -516,7 +517,78 @@ void Main::refresh(bool _override)
ui->balance->setText(QString::fromStdString(toString(totalGavCoinBalance) + " GAV | " + formatBalance(totalBalance)));
}
m_client->unlock();
}
void Main::on_transactionQueue_currentItemChanged()
{
ui->pendingInfo->clear();
eth::ClientGuard g(m_client.get());
stringstream s;
int i = ui->transactionQueue->currentRow();
if (i >= 0)
{
eth::StateDiff d = m_client->postState().fromPending(i).diff(m_client->postState().fromPending(i + 1));
auto indent = "<code style=\"white-space: pre\"> </code>";
unsigned ii = 0;
for (auto const& i: d.accounts)
{
if (ii)
s << "<hr/>";
ii++;
eth::AccountDiff const& ad = i.second;
s << "<code style=\"white-space: pre; font-weight: bold\">" << ad.lead() << " </code>" << " <b>" << render(i.first).toStdString() << "</b>";
if (!ad.exist.to())
continue;
if (ad.balance)
{
s << "<br/>" << indent << "Balance " << std::dec << formatBalance(ad.balance.to());
s << " <b>" << std::showpos << (((eth::bigint)ad.balance.to()) - ((eth::bigint)ad.balance.from())) << std::noshowpos << "</b>";
}
if (ad.nonce)
{
s << "<br/>" << indent << "Count #" << std::dec << ad.nonce.to();
s << " <b>" << std::showpos << (((eth::bigint)ad.nonce.to()) - ((eth::bigint)ad.nonce.from())) << std::noshowpos << "</b>";
}
if (ad.code)
{
s << "<br/>" << indent << "Code " << std::hex << ad.code.to();
if (ad.code.from().size())
s << " (" << ad.code.from() << ")";
}
for (pair<u256, eth::Diff<u256>> const& i: ad.storage)
{
s << "<br/><code style=\"white-space: pre\">";
if (!i.second.from())
s << " + ";
else if (!i.second.to())
s << "XXX";
else
s << " * ";
s << " </code>";
if (i.first > u256(1) << 246)
s << (h256)i.first;
else if (i.first > u160(1) << 150)
s << (h160)(u160)i.first;
else
s << std::hex << i.first;
if (!i.second.from())
s << ": " << std::hex << i.second.to();
else if (!i.second.to())
s << " (" << std::hex << i.second.from() << ")";
else
s << ": " << std::hex << i.second.to() << " (" << i.second.from() << ")";
}
}
}
ui->pendingInfo->setHtml(QString::fromStdString(s.str()));
}
void Main::ourAccountsRowsMoved()
@ -536,7 +608,7 @@ void Main::ourAccountsRowsMoved()
void Main::on_blocks_currentItemChanged()
{
ui->info->clear();
m_client->lock();
eth::ClientGuard g(m_client.get());
if (auto item = ui->blocks->currentItem())
{
auto hba = item->data(Qt::UserRole).toByteArray();
@ -597,7 +669,6 @@ void Main::on_blocks_currentItemChanged()
ui->info->appendHtml(QString::fromStdString(s.str()));
}
m_client->unlock();
}
void Main::on_contracts_currentItemChanged()

1
alethzero/MainWin.h

@ -65,6 +65,7 @@ private slots:
void on_blocks_currentItemChanged();
void on_contracts_doubleClicked();
void on_contracts_currentItemChanged();
void on_transactionQueue_currentItemChanged();
void on_about_triggered();
void on_nameReg_textChanged();
void on_preview_triggered() { refresh(true); }

5
libethcore/TrieDB.h

@ -41,7 +41,8 @@ public:
std::string lookup(h256 _h) const { auto it = m_over.find(_h); if (it != m_over.end()) return it->second; return std::string(); }
void insert(h256 _h, bytesConstRef _v) { m_over[_h] = _v.toString(); m_refCount[_h]++; }
void kill(h256 _h) { if (!--m_refCount[_h]) m_over.erase(_h); }
void kill(h256 _h) { --m_refCount[_h]; }
void purge() { for (auto const& i: m_refCount) if (!i.second) m_over.erase(i.first); }
protected:
std::map<h256, std::string> m_over;
@ -68,7 +69,7 @@ public:
ldb::DB* db() const { return m_db.get(); }
void setDB(ldb::DB* _db, bool _clearOverlay = true) { m_db = std::shared_ptr<ldb::DB>(_db); if (_clearOverlay) m_over.clear(); }
void commit() { if (m_db) { for (auto const& i: m_over) m_db->Put(m_writeOptions, ldb::Slice((char const*)i.first.data(), i.first.size), ldb::Slice(i.second.data(), i.second.size())); m_over.clear(); m_refCount.clear(); } }
void commit() { if (m_db) { for (auto const& i: m_over) 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())); m_over.clear(); m_refCount.clear(); } }
void rollback() { m_over.clear(); m_refCount.clear(); }
std::string lookup(h256 _h) const { std::string ret = BasicMap::lookup(_h); if (ret.empty() && m_db) m_db->Get(m_readOptions, ldb::Slice((char const*)_h.data(), 32), &ret); return ret; }

24
libethereum/State.cpp

@ -925,6 +925,23 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas,
return newAddress;
}
State State::fromPending(unsigned _i) const
{
State ret = *this;
ret.uncommitToMine();
_i = min<unsigned>(_i, m_transactions.size());
if (!_i)
ret.m_state.setRoot(m_previousBlock.stateRoot);
else
ret.m_state.setRoot(m_transactions[_i - 1].stateRoot);
while (ret.m_transactions.size() > _i)
{
ret.m_transactionSet.erase(ret.m_transactions.back().transaction.sha3());
ret.m_transactions.pop_back();
}
return ret;
}
void State::applyRewards(Addresses const& _uncleAddresses)
{
u256 r = m_blockReward;
@ -1021,6 +1038,13 @@ std::ostream& eth::operator<<(std::ostream& _out, State const& _s)
return _out;
}
AccountChange AccountDiff::changeType() const
{
bool bn = (balance || nonce);
bool sc = (!storage.empty() || code);
return exist ? exist.from() ? AccountChange::Deletion : AccountChange::Creation : (bn && sc) ? AccountChange::All : bn ? AccountChange::Intrinsic: sc ? AccountChange::CodeStorage : AccountChange::None;
}
char const* AccountDiff::lead() const
{
bool bn = (balance || nonce);

8
libethereum/State.h

@ -81,10 +81,13 @@ private:
T m_to;
};
enum class AccountChange { None, Creation, Deletion, Intrinsic, CodeStorage, All };
struct AccountDiff
{
inline bool changed() const { return storage.size() || code || nonce || balance || exist; }
char const* lead() const;
AccountChange changeType() const;
Diff<bool> exist;
Diff<u256> balance;
@ -219,6 +222,11 @@ public:
/// Get the list of pending transactions.
Transactions pending() const { Transactions ret; for (auto const& t: m_transactions) ret.push_back(t.transaction); return ret; }
/// Get the State immediately after the given number of pending transactions have been applied.
/// If (_i == 0) returns the initial state of the block.
/// If (_i == pending().size()) returns the final state of the block, prior to rewards.
State fromPending(unsigned _i) const;
/// Execute all transactions within a given block.
/// @returns the additional total difficulty.
/// If the _grandParent is passed, it will check the validity of each of the uncles.

Loading…
Cancel
Save