Browse Source

Assembler & disassembler.

Additional info in block chain.
cl-refactor
Gav Wood 11 years ago
parent
commit
39c7e8f2ee
  1. 2
      CMakeLists.txt
  2. 23
      alethzero/Main.ui
  3. 94
      alethzero/MainWin.cpp
  4. 1
      alethzero/MainWin.h
  5. 10
      libethereum/Client.cpp
  6. 2
      libethereum/Client.h
  7. 2
      libethereum/Common.h
  8. 25
      libethereum/Instruction.cpp
  9. 68
      libethereum/Instruction.h
  10. 4
      libethereum/State.cpp
  11. 12
      libethereum/Transaction.cpp
  12. 11
      libethereum/Transaction.h

2
CMakeLists.txt

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

23
alethzero/Main.ui

@ -20,18 +20,25 @@
<bool>true</bool>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>4</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="transactions">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
<widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QListWidget" name="blocks">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QPlainTextEdit" name="info">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</widget>
</item>
<item>
@ -51,7 +58,7 @@
</widget>
</item>
<item>
<widget class="QLabel" name="blockChain">
<widget class="QLabel" name="blockCount">
<property name="text">
<string>1 block</string>
</property>

94
alethzero/MainWin.cpp

@ -53,7 +53,7 @@ Main::Main(QWidget *parent) :
initUnits(ui->valueUnits);
statusBar()->addPermanentWidget(ui->balance);
statusBar()->addPermanentWidget(ui->peerCount);
statusBar()->addPermanentWidget(ui->blockChain);
statusBar()->addPermanentWidget(ui->blockCount);
}
Main::~Main()
@ -126,7 +126,7 @@ void Main::readSettings()
void Main::refresh()
{
m_client->lock();
//if (m_client->changed())
if (m_client->changed())
{
ui->peerCount->setText(QString::fromStdString(toString(m_client->peerCount())) + " peer(s)");
ui->peers->clear();
@ -135,37 +135,42 @@ void Main::refresh()
auto d = m_client->blockChain().details();
auto diff = BlockInfo(m_client->blockChain().block()).difficulty;
ui->blockChain->setText(QString("#%1 @%3 T%2").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)));
ui->blockCount->setText(QString("#%1 @%3 T%2").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)));
auto acs = m_client->state().addresses();
ui->accounts->clear();
for (auto i: acs)
ui->accounts->addItem(QString("%1 @ %2").arg(formatBalance(i.second).c_str()).arg(asHex(i.first.asArray()).c_str()));
ui->accounts->addItem(QString("%1 @ %2").arg(formatBalance(i.second).c_str()).arg(i.first.abridged().c_str()));
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(asHex(i.second.receiveAddress.asArray()).c_str())
.arg(asHex(i.second.sender().asArray()).c_str())
.arg(i.second.receiveAddress.abridged().c_str())
.arg(i.second.safeSender().abridged().c_str())
.arg((unsigned)i.second.nonce));
}
ui->transactions->clear();
ui->blocks->clear();
auto const& bc = m_client->blockChain();
for (auto h = bc.currentHash(); h != bc.genesisHash(); h = bc.details(h).parent)
{
auto d = bc.details(h);
ui->transactions->addItem(QString("# %1 ==== %2").arg(d.number).arg(asHex(h.asArray()).c_str()));
QListWidgetItem* blockItem = new QListWidgetItem(QString("# %1 ==== %2").arg(d.number).arg(h.abridged().c_str()), ui->blocks);
blockItem->setData(Qt::UserRole, QByteArray((char const*)h.data(), h.size));
int n = 0;
for (auto const& i: RLP(bc.block(h))[1])
{
Transaction t(i.data());
ui->transactions->addItem(QString("%1 [%4] @ %2 <- %3")
.arg(formatBalance(t.value).c_str())
.arg(asHex(t.receiveAddress.asArray()).c_str())
.arg(asHex(t.sender().asArray()).c_str())
.arg((unsigned)t.nonce));
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);
txItem->setData(Qt::UserRole, QByteArray((char const*)h.data(), h.size));
txItem->setData(Qt::UserRole + 1, n);
n++;
}
}
}
@ -175,13 +180,74 @@ void Main::refresh()
for (auto i: m_myKeys)
{
u256 b = m_client->state().balance(i.address());
ui->ourAccounts->addItem(QString("%1 @ %2").arg(formatBalance(b).c_str()).arg(asHex(i.address().asArray()).c_str()));
ui->ourAccounts->addItem(QString("%1 @ %2").arg(formatBalance(b).c_str()).arg(i.address().abridged().c_str()));
totalBalance += b;
}
ui->balance->setText(QString::fromStdString(formatBalance(totalBalance)));
m_client->unlock();
}
void Main::on_blocks_currentItemChanged()
{
ui->info->clear();
m_client->lock();
if (auto item = ui->blocks->currentItem())
{
auto hba = item->data(Qt::UserRole).toByteArray();
assert(hba.size() == 32);
auto h = h256((byte const*)hba.data(), h256::ConstructFromPointer);
auto details = m_client->blockChain().details(h);
auto blockData = m_client->blockChain().block(h);
auto block = RLP(blockData);
BlockInfo info(blockData);
stringstream s;
if (item->data(Qt::UserRole + 1).isNull())
{
char timestamp[64];
time_t rawTime = (time_t)(uint64_t)info.timestamp;
strftime(timestamp, 64, "%c", localtime(&rawTime));
s << "<b>" << timestamp << "</b>: " << h;
s << "&nbsp;&emsp;&nbsp;#<b>" << details.number << "</b>";
s << "&nbsp;&emsp;&nbsp;D/TD: <b>2^" << log2((double)info.difficulty) << "</b>/<b>2^" << log2((double)details.totalDifficulty) << "</b><br/>";
s << "<br/>Coinbase: <b>" << info.coinbaseAddress << "</b>";
s << "&nbsp;&emsp;&nbsp;TXs: <b>" << block[1].itemCount() << "</b>";
s << "&nbsp;&emsp;&nbsp;Children: <b>" << details.children.size() << "</b>";
s << "<br/>State: <b>" << info.stateRoot << "</b>";
s << "<br/>nonce: <b>" << info.nonce << "</b>";
s << "<br/>Transactions: <b>" << block[1].itemCount() << "</b> @<b>" << info.sha3Transactions << "</b>";
s << "<br/>Uncles: <b>" << block[2].itemCount() << "</b> @<b>" << info.sha3Uncles << "</b>";
}
else
{
unsigned txi = item->data(Qt::UserRole + 1).toInt();
Transaction tx(block[1][txi].data());
h256 th = tx.sha3();
s << "<b>" << th << "</b><br/>";
s << h << "[<b>" << txi << "</b>]";
s << "<br/>From: <b>" << tx.safeSender() << "</b>";
if (tx.receiveAddress)
s << "&nbsp;&emsp;&nbsp;To: <b>" << tx.receiveAddress << "</b>";
else
s << "&nbsp;&emsp;&nbsp;Creates: <b>" << right160(th) << "</b>";
s << "<br/>Value: <b>" << formatBalance(tx.value) << "</b>";
s << "&nbsp;&emsp;&nbsp;#<b>" << tx.nonce << "</b>";
if (tx.data.size())
{
s << "<br/>Data:&nbsp;&emsp;&nbsp;";
// for (auto i: tx.data)
// s << "0x<b>" << hex << i << "</b>&emsp;";
s << "</br>" << disassemble(tx.data);
}
}
ui->info->appendHtml(QString::fromStdString(s.str()));
}
m_client->unlock();
}
void Main::on_idealPeers_valueChanged()
{
if (m_client->peerServer())

1
alethzero/MainWin.h

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

10
libethereum/Client.cpp

@ -96,7 +96,7 @@ void Client::stopMining()
void Client::transact(Secret _secret, Address _dest, u256 _amount, u256s _data)
{
lock_guard<mutex> l(m_lock);
lock_guard<recursive_mutex> l(m_lock);
Transaction t;
t.nonce = m_postMine.transactionsFrom(toAddress(_secret));
t.receiveAddress = _dest;
@ -119,7 +119,7 @@ void Client::work()
{
m_net->process();
lock_guard<mutex> l(m_lock);
lock_guard<recursive_mutex> l(m_lock);
if (m_net->sync(m_bc, m_tq, m_stateDB))
changed = true;
}
@ -132,7 +132,7 @@ void Client::work()
// all blocks.
// Resynchronise state with block chain & trans
{
lock_guard<mutex> l(m_lock);
lock_guard<recursive_mutex> l(m_lock);
if (m_preMine.sync(m_bc) || m_postMine.address() != m_preMine.address())
{
if (m_doMine)
@ -154,7 +154,7 @@ void Client::work()
{
if (m_restartMining)
{
lock_guard<mutex> l(m_lock);
lock_guard<recursive_mutex> l(m_lock);
m_postMine.commitToMine(m_bc);
}
@ -169,7 +169,7 @@ void Client::work()
if (mineInfo.completed)
{
// Import block.
lock_guard<mutex> l(m_lock);
lock_guard<recursive_mutex> l(m_lock);
m_bc.attemptImport(m_postMine.blockData(), m_stateDB);
m_mineProgress.best = 0;
m_changed = true;

2
libethereum/Client.h

@ -140,7 +140,7 @@ private:
std::thread* m_work; ///< The work thread.
std::mutex m_lock;
std::recursive_mutex m_lock;
enum { Active = 0, Deleting, Deleted } m_workState = Active;
bool m_doMine = false; ///< Are we supposed to be mining?
MineProgress m_mineProgress;

2
libethereum/Common.h

@ -118,7 +118,7 @@ public:
FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; }
FixedHash& operator~() { for (auto i = 0; i < N; ++i) m_data[i] = ~m_data[i]; return *this; }
std::string abridged() const { return asHex(ref().cropped(0, 4)); }
std::string abridged() const { return asHex(ref().cropped(0, 4)) + ".."; }
byte& operator[](unsigned _i) { return m_data[_i]; }
byte operator[](unsigned _i) const { return m_data[_i]; }

25
libethereum/Instruction.cpp

@ -52,7 +52,30 @@ u256s eth::assemble(std::string const& _code)
else
cwarn << "Unknown assembler token" << t;
}
}
return ret;
}
string eth::disassemble(u256s const& _mem)
{
stringstream ret;
uint numerics = 0;
for (auto it = _mem.begin(); it != _mem.end(); ++it)
{
u256 n = *it;
auto iit = c_instructionInfo.find((Instruction)(uint)n);
if (numerics || iit == c_instructionInfo.end() || (u256)(uint)iit->first != n) // not an instruction or expecting an argument...
{
if (numerics)
numerics--;
ret << " 0x" << hex << n;
}
else
{
auto const& ii = iit->second;
ret << " " << ii.name;
numerics = ii.additional;
}
}
return ret.str();
}

68
libethereum/Instruction.h

@ -33,8 +33,8 @@ enum class Instruction: uint8_t
{
STOP = 0x00, ///< halts execution
ADD,
SUB,
MUL,
SUB,
DIV,
SDIV,
MOD,
@ -47,6 +47,7 @@ enum class Instruction: uint8_t
GE,
EQ,
NOT,
MYADDRESS, ///< pushes the transaction sender
TXSENDER, ///< pushes the transaction sender
TXVALUE , ///< pushes the transaction value
TXDATAN, ///< pushes the number of data items
@ -83,6 +84,69 @@ enum class Instruction: uint8_t
SUICIDE = 0x3f
};
struct InstructionInfo
{
std::string name;
int additional;
int args;
int ret;
};
static const std::map<Instruction, InstructionInfo> c_instructionInfo =
{
{ Instruction::STOP, { "STOP", 0, 0, 0 } },
{ Instruction::ADD, { "ADD", 0, 2, 1 } },
{ Instruction::SUB, { "SUB", 0, 2, 1 } },
{ Instruction::MUL, { "MUL", 0, 2, 1 } },
{ Instruction::DIV, { "DIV", 0, 2, 1 } },
{ Instruction::SDIV, { "SDIV", 0, 2, 1 } },
{ Instruction::MOD, { "MOD", 0, 2, 1 } },
{ Instruction::SMOD, { "SMOD", 0, 2, 1 } },
{ Instruction::EXP, { "EXP", 0, 2, 1 } },
{ Instruction::NEG, { "NEG", 0, 1, 1 } },
{ Instruction::LT, { "LT", 0, 2, 1 } },
{ Instruction::LE, { "LE", 0, 2, 1 } },
{ Instruction::GT, { "GT", 0, 2, 1 } },
{ Instruction::GE, { "GE", 0, 2, 1 } },
{ Instruction::EQ, { "EQ", 0, 2, 1 } },
{ Instruction::NOT, { "NOT", 0, 1, 1 } },
{ Instruction::MYADDRESS, { "MYADDRESS", 0, 0, 1 } },
{ Instruction::TXSENDER, { "TXSENDER", 0, 0, 1 } },
{ Instruction::TXVALUE, { "TXVALUE", 0, 0, 1 } },
{ Instruction::TXDATAN, { "TXDATAN", 0, 0, 1 } },
{ Instruction::TXDATA, { "TXDATA", 0, 1, 1 } },
{ Instruction::BLK_PREVHASH, { "BLK_PREVHASH", 0, 0, 1 } },
{ Instruction::BLK_COINBASE, { "BLK_COINBASE", 0, 0, 1 } },
{ Instruction::BLK_TIMESTAMP, { "BLK_TIMESTAMP", 0, 0, 1 } },
{ Instruction::BLK_NUMBER, { "BLK_NUMBER", 0, 0, 1 } },
{ Instruction::BLK_DIFFICULTY, { "BLK_DIFFICULTY", 0, 0, 1 } },
{ Instruction::BLK_NONCE, { "BLK_NONCE", 0, 0, 1 } },
{ Instruction::BASEFEE, { "BASEFEE", 0, 0, 1 } },
{ Instruction::SHA256, { "SHA256", 0, -1, 1 } },
{ Instruction::RIPEMD160, { "RIPEMD160", 0, -1, 1 } },
{ Instruction::ECMUL, { "ECMUL", 0, 3, 1 } },
{ Instruction::ECADD, { "ECADD", 0, 4, 1 } },
{ Instruction::ECSIGN, { "ECSIGN", 0, 2, 1 } },
{ Instruction::ECRECOVER, { "ECRECOVER", 0, 4, 1 } },
{ Instruction::ECVALID, { "ECVALID", 0, 2, 1 } },
{ Instruction::SHA3, { "SHA3", 0, -1, 1 } },
{ Instruction::PUSH, { "PUSH", 1, 0, 1 } },
{ Instruction::POP, { "POP", 0, 1, 0 } },
{ Instruction::DUP, { "DUP", 0, 1, 2 } },
{ Instruction::SWAP, { "SWAP", 0, 2, 2 } },
{ Instruction::MLOAD, { "MLOAD", 0, 1, 1 } },
{ Instruction::MSTORE, { "MSTORE", 0, 2, 0 } },
{ Instruction::SLOAD, { "SLOAD", 0, 1, 1 } },
{ Instruction::SSTORE, { "SSTORE", 0, 2, 0 } },
{ Instruction::JMP, { "JMP", 0, 1, 0 } },
{ Instruction::JMPI, { "JMPI", 0, 2, 0 } },
{ Instruction::IND, { "IND", 0, 0, 1 } },
{ Instruction::EXTRO, { "EXTRO", 0, 2, 1 } },
{ Instruction::BALANCE, { "BALANCE", 0, 1, 1 } },
{ Instruction::MKTX, { "MKTX", 0, 4, 0 } },
{ Instruction::SUICIDE, { "SUICIDE", 0, 1, 0} }
};
static const std::map<std::string, Instruction> c_instructions =
{
{ "STOP", Instruction::STOP },
@ -101,6 +165,7 @@ static const std::map<std::string, Instruction> c_instructions =
{ "GE", Instruction::GE },
{ "EQ", Instruction::EQ },
{ "NOT", Instruction::NOT },
{ "MYADDRESS", Instruction::MYADDRESS },
{ "TXSENDER", Instruction::TXSENDER },
{ "TXVALUE", Instruction::TXVALUE },
{ "TXDATAN", Instruction::TXDATAN },
@ -138,5 +203,6 @@ static const std::map<std::string, Instruction> c_instructions =
};
u256s assemble(std::string const& _code);
std::string disassemble(u256s const& _mem);
}

4
libethereum/State.cpp

@ -897,9 +897,9 @@ void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256s
stack.back() = stack.back() ? 0 : 1;
stack.pop_back();
break;
/*case Instruction::MYADDRESS:
case Instruction::MYADDRESS:
stack.push_back((u160)_myAddress);
break;*/
break;
case Instruction::TXSENDER:
stack.push_back((u160)_txSender);
break;

12
libethereum/Transaction.cpp

@ -40,6 +40,18 @@ Transaction::Transaction(bytesConstRef _rlpData)
vrs = Signature{ rlp[4].toInt<byte>(), rlp[5].toInt<u256>(), rlp[6].toInt<u256>() };
}
Address Transaction::safeSender() const noexcept
{
try
{
return sender();
}
catch (...)
{
return Address();
}
}
Address Transaction::sender() const
{
secp256k1_start();

11
libethereum/Transaction.h

@ -47,6 +47,7 @@ struct Transaction
u256s data;
Signature vrs;
Address safeSender() const noexcept;
Address sender() const;
void sign(Secret _priv);
@ -63,11 +64,17 @@ using Transactions = std::vector<Transaction>;
inline std::ostream& operator<<(std::ostream& _out, Transaction const& _t)
{
_out << "{" << _t.receiveAddress << "/" << _t.nonce << "*" << _t.value;
_out << "{";
if (_t.receiveAddress)
_out << _t.receiveAddress.abridged();
else
_out << "[CREATE]";
_out << "/" << _t.nonce << "*" << _t.value;
Address s;
try
{
_out << "<-" << _t.sender();
_out << "<-" << _t.sender().abridged();
}
catch (...) {}
_out << "}";

Loading…
Cancel
Save