diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9affafc0e..23c418da3 100644
--- a/CMakeLists.txt
+++ b/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.
diff --git a/alethzero/Main.ui b/alethzero/Main.ui
index 3a49fa839..50a6b0d24 100644
--- a/alethzero/Main.ui
+++ b/alethzero/Main.ui
@@ -25,37 +25,63 @@
0
-
-
-
-
- 0
- 0
-
-
+
- Qt::Horizontal
+ Qt::Vertical
-
-
-
- 0
- 0
-
-
-
- QFrame::NoFrame
+
+
+ Qt::Horizontal
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 2
+ 0
+
+
+
+ QFrame::NoFrame
+
+
-
-
-
- 2
- 0
-
-
-
- QFrame::NoFrame
+
+
+ Qt::Horizontal
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 2
+ 0
+
+
+
+ QFrame::NoFrame
+
+
@@ -476,6 +502,17 @@
+
+
+ toolBar_2
+
+
+ TopToolBarArea
+
+
+ false
+
+
&Quit
diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 6ad4b5d87..11297a78b 100644
--- a/alethzero/MainWin.cpp
+++ b/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 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 << " ...
@" << showbase << hex << i.first << " ";
+ }
+ else if (!next)
+ {
+ s << "@" << showbase << hex << i.first << " ";
+ }
+ 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())
diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h
index e1cb44e65..a2d1199fd 100644
--- a/alethzero/MainWin.h
+++ b/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(); }
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index 7bebc5ec5..8badddcb6 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -605,6 +605,14 @@ u256 State::contractMemory(Address _id, u256 _memory) const
return RLP(memdb.at(_memory)).toInt(); // TODO: CHECK: check if this is actually an RLP decode
}
+map 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.
diff --git a/libethereum/State.h b/libethereum/State.h
index 63520da70..af7166eb5 100644
--- a/libethereum/State.h
+++ b/libethereum/State.h
@@ -60,6 +60,8 @@ struct FeeStructure
template class UnitTest {};
+static const std::map 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 if no contract exists at that address.
+ std::map const& contractMemory(Address _contract) const;
+
/// Note that the given address is sending a transaction and thus increment the associated ticker.
void noteSending(Address _id);