Browse Source

Contract state introspection.

cl-refactor
Gav Wood 11 years ago
parent
commit
976a84c7e5
  1. 2
      CMakeLists.txt
  2. 89
      alethzero/Main.ui
  3. 89
      alethzero/MainWin.cpp
  4. 1
      alethzero/MainWin.h
  5. 8
      libethereum/State.cpp
  6. 6
      libethereum/State.h

2
CMakeLists.txt

@ -5,7 +5,7 @@ set(CMAKE_AUTOMOC ON)
cmake_policy(SET CMP0015 NEW)
set(ETH_VERSION 0.3.1)
set(ETH_VERSION 0.3.2)
set(ETH_BUILD_TYPE ${CMAKE_BUILD_TYPE})
# Default HEADLESS to 0.

89
alethzero/Main.ui

@ -25,37 +25,63 @@
<number>0</number>
</property>
<item>
<widget class="QSplitter" name="splitter_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QSplitter" name="splitter_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Vertical</enum>
</property>
<widget class="QListWidget" name="blocks">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
<widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QListWidget" name="blocks">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QPlainTextEdit" name="info">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</widget>
<widget class="QPlainTextEdit" name="info">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
<widget class="QSplitter" name="splitter_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QListWidget" name="contracts">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QPlainTextEdit" name="contractInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</widget>
</widget>
</item>
@ -476,6 +502,17 @@
</layout>
</widget>
</widget>
<widget class="QToolBar" name="toolBar_2">
<property name="windowTitle">
<string>toolBar_2</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<action name="quit">
<property name="text">
<string>&amp;Quit</string>

89
alethzero/MainWin.cpp

@ -147,20 +147,33 @@ void Main::refresh()
auto acs = m_client->state().addresses();
ui->accounts->clear();
ui->contracts->clear();
for (auto i: acs)
{
(new QListWidgetItem(QString("%1 [%3] @ %2").arg(formatBalance(i.second).c_str()).arg(i.first.abridged().c_str()).arg((unsigned)m_client->state().transactionsFrom(i.first)), ui->accounts))
->setData(Qt::UserRole, QByteArray((char const*)i.first.data(), Address::size));
if (m_client->state().isContractAddress(i.first))
(new QListWidgetItem(QString("%1 [%3] @ %2").arg(formatBalance(i.second).c_str()).arg(i.first.abridged().c_str()).arg((unsigned)m_client->state().transactionsFrom(i.first)), ui->contracts))
->setData(Qt::UserRole, QByteArray((char const*)i.first.data(), Address::size));
}
ui->transactionQueue->clear();
for (pair<h256, Transaction> const& i: m_client->pending())
{
ui->transactionQueue->addItem(QString("%1 [%4] @ %2 <- %3")
.arg(formatBalance(i.second.value).c_str())
.arg(i.second.receiveAddress.abridged().c_str())
.arg(i.second.safeSender().abridged().c_str())
.arg((unsigned)i.second.nonce));
Transaction t = i.second;
QString s = t.receiveAddress ?
QString("%1 [%4] %2 %5> %3")
.arg(formatBalance(t.value).c_str())
.arg(t.safeSender().abridged().c_str())
.arg(t.receiveAddress.abridged().c_str())
.arg((unsigned)t.nonce)
.arg(m_client->state().isContractAddress(t.receiveAddress) ? '*' : '-') :
QString("%1 [%4] %2 +> %3")
.arg(formatBalance(t.value).c_str())
.arg(t.safeSender().abridged().c_str())
.arg(right160(t.sha3()).abridged().c_str())
.arg((unsigned)t.nonce);
ui->transactionQueue->addItem(s);
}
ui->blocks->clear();
@ -174,11 +187,19 @@ void Main::refresh()
for (auto const& i: RLP(bc.block(h))[1])
{
Transaction t(i.data());
QListWidgetItem* txItem = new QListWidgetItem(QString("%1 [%4] @ %2 <- %3")
.arg(formatBalance(t.value).c_str())
.arg(t.receiveAddress.abridged().c_str())
.arg(t.safeSender().abridged().c_str())
.arg((unsigned)t.nonce), ui->blocks);
QString s = t.receiveAddress ?
QString(" %1 [%4] %2 %5> %3")
.arg(formatBalance(t.value).c_str())
.arg(t.safeSender().abridged().c_str())
.arg(t.receiveAddress.abridged().c_str())
.arg((unsigned)t.nonce)
.arg(m_client->state().isContractAddress(t.receiveAddress) ? '*' : '-') :
QString(" %1 [%4] %2 +> %3")
.arg(formatBalance(t.value).c_str())
.arg(t.safeSender().abridged().c_str())
.arg(right160(t.sha3()).abridged().c_str())
.arg((unsigned)t.nonce);
QListWidgetItem* txItem = new QListWidgetItem(s, ui->blocks);
txItem->setData(Qt::UserRole, QByteArray((char const*)h.data(), h.size));
txItem->setData(Qt::UserRole + 1, n);
n++;
@ -264,6 +285,54 @@ void Main::on_blocks_currentItemChanged()
m_client->unlock();
}
void Main::on_contracts_currentItemChanged()
{
ui->contractInfo->clear();
m_client->lock();
if (auto item = ui->contracts->currentItem())
{
auto hba = item->data(Qt::UserRole).toByteArray();
assert(hba.size() == 20);
auto h = h160((byte const*)hba.data(), h160::ConstructFromPointer);
stringstream s;
auto mem = m_client->state().contractMemory(h);
u256 next = 0;
unsigned numerics = 0;
for (auto i: mem)
{
if (next < i.first)
{
unsigned j;
for (j = 0; j <= numerics && next + j < i.first; ++j)
s << (j < numerics ? " 0" : " STOP");
numerics -= (j - 1);
s << " ...<br/>@" << showbase << hex << i.first << "&nbsp;&nbsp;&nbsp;&nbsp;";
}
else if (!next)
{
s << "@" << showbase << hex << i.first << "&nbsp;&nbsp;&nbsp;&nbsp;";
}
auto iit = c_instructionInfo.find((Instruction)(unsigned)i.second);
if (numerics || iit == c_instructionInfo.end() || (u256)(unsigned)iit->first != i.second) // not an instruction or expecting an argument...
{
if (numerics)
numerics--;
s << " 0x" << hex << i.second;
}
else
{
auto const& ii = iit->second;
s << " " << ii.name;
numerics = ii.additional;
}
next = i.first + 1;
}
ui->contractInfo->appendHtml(QString::fromStdString(s.str()));
}
m_client->unlock();
}
void Main::on_idealPeers_valueChanged()
{
if (m_client->peerServer())

1
alethzero/MainWin.h

@ -39,6 +39,7 @@ private slots:
void on_valueUnits_currentIndexChanged() { updateFee(); }
void on_log_doubleClicked();
void on_blocks_currentItemChanged();
void on_contracts_currentItemChanged();
void on_about_triggered();
void on_quit_triggered() { close(); }

8
libethereum/State.cpp

@ -605,6 +605,14 @@ u256 State::contractMemory(Address _id, u256 _memory) const
return RLP(memdb.at(_memory)).toInt<u256>(); // TODO: CHECK: check if this is actually an RLP decode
}
map<u256, u256> const& State::contractMemory(Address _contract) const
{
if (!isContractAddress(_contract))
return EmptyMapU256U256;
ensureCached(_contract, true, true);
return m_cache[_contract].memory();
}
void State::execute(bytesConstRef _rlp)
{
// Entry point for a user-executed transaction.

6
libethereum/State.h

@ -60,6 +60,8 @@ struct FeeStructure
template <unsigned T> class UnitTest {};
static const std::map<u256, u256> EmptyMapU256U256;
/**
* @brief Model of the current state of the ledger.
* Maintains current ledger (m_current) as a fast hash-map. This is hashed only when required (i.e. to create or verify a block).
@ -154,6 +156,10 @@ public:
/// @returns 0 if no contract exists at that address.
u256 contractMemory(Address _contract, u256 _memory) const;
/// Get the memory of a contract.
/// @returns std::map<u256, u256> if no contract exists at that address.
std::map<u256, u256> const& contractMemory(Address _contract) const;
/// Note that the given address is sending a transaction and thus increment the associated ticker.
void noteSending(Address _id);

Loading…
Cancel
Save