diff --git a/alethzero/Context.h b/alethzero/Context.h index 76231d6fd..20c9696f9 100644 --- a/alethzero/Context.h +++ b/alethzero/Context.h @@ -59,10 +59,10 @@ class Context public: virtual ~Context(); - virtual QString pretty(dev::Address _a) const = 0; - virtual QString prettyU256(dev::u256 _n) const = 0; - virtual QString render(dev::Address _a) const = 0; - virtual std::pair fromString(QString const& _a) const = 0; + virtual std::string pretty(dev::Address const& _a) const = 0; + virtual std::string prettyU256(dev::u256 const& _n) const = 0; + virtual std::pair fromString(std::string const& _a) const = 0; virtual std::string renderDiff(dev::eth::StateDiff const& _d) const = 0; + virtual std::string render(dev::Address const& _a) const = 0; }; diff --git a/alethzero/Debugger.cpp b/alethzero/Debugger.cpp index 371630456..a1d246a21 100644 --- a/alethzero/Debugger.cpp +++ b/alethzero/Debugger.cpp @@ -226,7 +226,7 @@ void Debugger::update() QString stack; for (auto i: ws.stack) - stack.prepend("
" + m_context->prettyU256(i) + "
"); + stack.prepend("
" + QString::fromStdString(m_context->prettyU256(i)) + "
"); ui->debugStack->setHtml(stack); ui->debugMemory->setHtml(QString::fromStdString(dev::memDump(ws.memory, 16, true))); assert(m_session.codes.count(ws.code)); @@ -246,7 +246,7 @@ void Debugger::update() ui->debugStateInfo->setText(QString::fromStdString(ss.str())); stringstream s; for (auto const& i: ws.storage) - s << "@" << m_context->prettyU256(i.first).toStdString() << "    " << m_context->prettyU256(i.second).toStdString() << "
"; + s << "@" << m_context->prettyU256(i.first) << "    " << m_context->prettyU256(i.second) << "
"; ui->debugStorage->setHtml(QString::fromStdString(s.str())); } } diff --git a/alethzero/ExportState.cpp b/alethzero/ExportState.cpp index e39b74b76..a8e47ad6a 100644 --- a/alethzero/ExportState.cpp +++ b/alethzero/ExportState.cpp @@ -129,8 +129,8 @@ void ExportStateDialog::fillContracts() ui->contracts->setEnabled(true); for (auto i: ethereum()->addresses(m_block)) { - QString r = m_main->render(i); - (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(r).arg((unsigned)ethereum()->countAt(i)), ethereum()->codeAt(i).empty() ? ui->accounts : ui->contracts)) + string r = m_main->render(i); + (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), ethereum()->codeAt(i).empty() ? ui->accounts : ui->contracts)) ->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size)); } } diff --git a/alethzero/Main.ui b/alethzero/Main.ui index ee46017f5..cdd734941 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -53,23 +53,23 @@ - + - 0 wei + 1 block - + - 0 peers + 0 wei - + - 1 block + 0 peers @@ -160,8 +160,8 @@ - - + + @@ -190,7 +190,6 @@ &View - @@ -218,43 +217,6 @@ - - - QDockWidget::DockWidgetFeatureMask - - - Accounts - - - 2 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::NoFocus - - - QFrame::NoFrame - - - - - - QDockWidget::DockWidgetFeatureMask @@ -595,13 +557,16 @@ QDockWidget::DockWidgetFeatureMask - Contracts + Accounts 2 + + 0 + 0 @@ -614,12 +579,66 @@ 0 + + + + + + Filter... + + + + + + + Basic + + + true + + + + + + + Contracts + + + true + + + true + + + + + + + Only Named + + + true + + + false + + + + + + + Refresh + + + + + Qt::Horizontal - + 0 @@ -633,7 +652,7 @@ QFrame::NoFrame - + 2 @@ -1482,7 +1501,7 @@ font-size: 14pt - &Export State... + &Export State... diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index ff505d5f2..3b89d3398 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -80,29 +80,29 @@ using namespace dev::p2p; using namespace dev::eth; namespace js = json_spirit; -QString Main::fromRaw(h256 _n, unsigned* _inc) +string Main::fromRaw(h256 _n, unsigned* _inc) { if (_n) { string s((char const*)_n.data(), 32); auto l = s.find_first_of('\0'); if (!l) - return QString(); + return string(); if (l != string::npos) { auto p = s.find_first_not_of('\0', l); if (!(p == string::npos || (_inc && p == 31))) - return QString(); + return string(); if (_inc) *_inc = (byte)s[31]; s.resize(l); } for (auto i: s) if (i < 32) - return QString(); - return QString::fromStdString(s); + return string(); + return s; } - return QString(); + return string(); } QString contentsOfQResource(string const& res) @@ -398,7 +398,7 @@ void Main::onNewBlock() // update blockchain dependent views. refreshBlockCount(); refreshBlockChain(); - refreshAccounts(); + ui->refreshAccounts->setEnabled(true); // We must update balances since we can't filter updates to basic accounts. refreshBalances(); @@ -410,7 +410,7 @@ void Main::onNewPending() // update any pending-transaction dependent views. refreshPending(); - refreshAccounts(); + ui->refreshAccounts->setEnabled(true); } void Main::on_forceMining_triggered() @@ -510,33 +510,33 @@ static Public stringToPublic(QString const& _a) return Public(); } -QString Main::pretty(dev::Address _a) const +std::string Main::pretty(dev::Address const& _a) const { auto g_newNameReg = getNameReg(); if (g_newNameReg) { - QString s = QString::fromStdString(toString(abiOut(ethereum()->call(g_newNameReg, abiIn("getName(address)", _a)).output))); - if (s.size()) - return s; + string n = toString(abiOut(ethereum()->call(g_newNameReg, abiIn("name(address)", _a)).output)); + if (!n.empty()) + return n; } - return QString(); + return string(); } -QString Main::render(dev::Address _a) const +std::string Main::render(dev::Address const& _a) const { - QString p = pretty(_a); - QString n; - try { - n = QString::fromStdString(ICAP(_a).encoded()); - } - catch (...) { - n = QString::fromStdString(_a.abridged()); - } - return p.isEmpty() ? n : (p + " " + n); + string p = pretty(_a); + string n; + if (p.size() == 9 && p.find_first_not_of("QWERYUOPASDFGHJKLZXCVBNM1234567890") == string::npos) + p = ICAP(p, "XREG").encoded(); + else + DEV_IGNORE_EXCEPTIONS(n = ICAP(_a).encoded()); + if (n.empty()) + n = _a.abridged(); + return p.empty() ? n : (p + " " + n); } -pair Main::fromString(QString const& _n) const +pair Main::fromString(std::string const& _n) const { if (_n == "(Create Contract)") return make_pair(Address(), bytes()); @@ -544,7 +544,7 @@ pair Main::fromString(QString const& _n) const auto g_newNameReg = getNameReg(); if (g_newNameReg) { - Address a = abiOut
(ethereum()->call(g_newNameReg, abiIn("addr(bytes32)", ::toString32(_n.toStdString()))).output); + Address a = abiOut
(ethereum()->call(g_newNameReg, abiIn("addr(bytes32)", ::toString32(_n))).output); if (a) return make_pair(a, bytes()); } @@ -552,7 +552,7 @@ pair Main::fromString(QString const& _n) const { try { - return make_pair(Address(fromHex(_n.toStdString(), WhenError::Throw)), bytes()); + return make_pair(Address(fromHex(_n, WhenError::Throw)), bytes()); } catch (BadHexCharacter& _e) { @@ -568,7 +568,7 @@ pair Main::fromString(QString const& _n) const } else try { - return ICAP::decoded(_n.toStdString()).address([&](Address const& a, bytes const& b) -> bytes + return ICAP::decoded(_n).address([&](Address const& a, bytes const& b) -> bytes { return ethereum()->call(a, b).output; }, g_newNameReg); @@ -600,7 +600,7 @@ QString Main::lookup(QString const& _a) const return QString("%1.%2.%3.%4").arg((int)ret[28]).arg((int)ret[29]).arg((int)ret[30]).arg((int)ret[31]); // TODO: support IPv6. else if (ret) - return fromRaw(ret); + return QString::fromStdString(fromRaw(ret)); else return _a; } @@ -817,7 +817,7 @@ void Main::on_exportKey_triggered() if (ui->ourAccounts->currentRow() >= 0 && ui->ourAccounts->currentRow() < m_myKeys.size()) { auto k = m_myKeys[ui->ourAccounts->currentRow()]; - QMessageBox::information(this, "Export Account Key", "Secret key to account " + render(k.address()) + " is:\n" + QString::fromStdString(toHex(k.sec().ref()))); + QMessageBox::information(this, "Export Account Key", "Secret key to account " + QString::fromStdString(render(k.address()) + " is:\n" + toHex(k.sec().ref()))); } } @@ -936,7 +936,7 @@ void Main::refreshBalances() for (auto i: m_myKeys) { u256 b = ethereum()->balanceAt(i.address()); - (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(b).c_str()).arg(render(i.address())).arg((unsigned)ethereum()->countAt(i.address())), ui->ourAccounts)) + (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(b).c_str()).arg(QString::fromStdString(render(i.address()))).arg((unsigned)ethereum()->countAt(i.address())), ui->ourAccounts)) ->setData(Qt::UserRole, QByteArray((char const*)i.address().data(), Address::size)); totalBalance += b; @@ -968,24 +968,24 @@ void Main::refreshNetwork() map sessions; for (PeerSessionInfo const& i: ps) ui->peers->addItem(QString("[%8 %7] %3 ms - %1:%2 - %4 %5 %6") - .arg(QString::fromStdString(i.host)) - .arg(i.port) - .arg(chrono::duration_cast(i.lastPing).count()) - .arg(sessions[i.id] = QString::fromStdString(i.clientVersion)) - .arg(QString::fromStdString(toString(i.caps))) - .arg(QString::fromStdString(toString(i.notes))) - .arg(i.socketId) - .arg(QString::fromStdString(i.id.abridged()))); + .arg(QString::fromStdString(i.host)) + .arg(i.port) + .arg(chrono::duration_cast(i.lastPing).count()) + .arg(sessions[i.id] = QString::fromStdString(i.clientVersion)) + .arg(QString::fromStdString(toString(i.caps))) + .arg(QString::fromStdString(toString(i.notes))) + .arg(i.socketId) + .arg(QString::fromStdString(i.id.abridged()))); auto ns = web3()->nodes(); for (p2p::Peer const& i: ns) ui->nodes->insertItem(sessions.count(i.id) ? 0 : ui->nodes->count(), QString("[%1 %3] %2 - ( =%5s | /%4s%6 ) - *%7 $%8") - .arg(QString::fromStdString(i.id.abridged())) - .arg(QString::fromStdString(i.endpoint.address.to_string())) - .arg(i.id == web3()->id() ? "self" : sessions.count(i.id) ? sessions[i.id] : "disconnected") - .arg(i.isOffline() ? " | " + QString::fromStdString(reasonOf(i.lastDisconnect())) + " | " + QString::number(i.failedAttempts()) + "x" : "") - .arg(i.rating()) - ); + .arg(QString::fromStdString(i.id.abridged())) + .arg(QString::fromStdString(i.endpoint.address.to_string())) + .arg(i.id == web3()->id() ? "self" : sessions.count(i.id) ? sessions[i.id] : "disconnected") + .arg(i.isOffline() ? " | " + QString::fromStdString(reasonOf(i.lastDisconnect())) + " | " + QString::number(i.failedAttempts()) + "x" : "") + .arg(i.rating()) + ); } } @@ -994,7 +994,7 @@ void Main::refreshAll() refreshBlockChain(); refreshBlockCount(); refreshPending(); - refreshAccounts(); + ui->refreshAccounts->setEnabled(true); refreshBalances(); } @@ -1007,40 +1007,66 @@ void Main::refreshPending() QString s = t.receiveAddress() ? QString("%2 %5> %3: %1 [%4]") .arg(formatBalance(t.value()).c_str()) - .arg(render(t.safeSender())) - .arg(render(t.receiveAddress())) + .arg(QString::fromStdString(render(t.safeSender()))) + .arg(QString::fromStdString(render(t.receiveAddress()))) .arg((unsigned)t.nonce()) .arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') : QString("%2 +> %3: %1 [%4]") .arg(formatBalance(t.value()).c_str()) - .arg(render(t.safeSender())) - .arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce()))))) + .arg(QString::fromStdString(render(t.safeSender()))) + .arg(QString::fromStdString(render(right160(sha3(rlpList(t.safeSender(), t.nonce())))))) .arg((unsigned)t.nonce()); ui->transactionQueue->addItem(s); } } +void Main::on_accountsFilter_textChanged() +{ + ui->refreshAccounts->setEnabled(true); +} + +void Main::on_showBasic_toggled() +{ + ui->refreshAccounts->setEnabled(true); +} + +void Main::on_showContracts_toggled() +{ + ui->refreshAccounts->setEnabled(true); +} + +void Main::on_onlyNamed_toggled() +{ + ui->refreshAccounts->setEnabled(true); +} + +void Main::on_refreshAccounts_clicked() +{ + refreshAccounts(); +} + void Main::refreshAccounts() { -#if ETH_FATDB + DEV_TIMED_FUNCTION; +#if ETH_FATDB || !ETH_TRUE cwatch << "refreshAccounts()"; ui->accounts->clear(); - ui->contracts->clear(); - for (auto n = 0; n < 2; ++n) - for (auto i: ethereum()->addresses()) - { - auto r = render(i); - if (r.contains('(') == !n) - { - if (n == 0 || ui->showAllAccounts->isChecked()) - (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(r).arg((unsigned)ethereum()->countAt(i)), ui->accounts)) - ->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size)); - if (ethereum()->codeAt(i).size()) - (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(r).arg((unsigned)ethereum()->countAt(i)), ui->contracts)) - ->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size)); - } - } + bool showContract = ui->showContracts->isChecked(); + bool showBasic = ui->showBasic->isChecked(); + bool onlyNamed = ui->onlyNamed->isChecked(); + for (auto const& i: ethereum()->addresses()) + { + bool isContract = (ethereum()->codeHashAt(i) != EmptySHA3); + if (!((showContract && isContract) || (showBasic && !isContract))) + continue; + string r = render(i); + if (onlyNamed && !(r.find('"') != string::npos || r.substr(0, 2) == "XE")) + continue; + (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), ui->accounts)) + ->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size)); + } #endif + ui->refreshAccounts->setEnabled(false); } void Main::refreshBlockCount() @@ -1057,6 +1083,7 @@ void Main::on_turboMining_triggered() void Main::refreshBlockChain() { + DEV_TIMED_FUNCTION; cwatch << "refreshBlockChain()"; // TODO: keep the same thing highlighted. @@ -1105,14 +1132,14 @@ void Main::refreshBlockChain() QString s = t.receiveAddress() ? QString(" %2 %5> %3: %1 [%4]") .arg(formatBalance(t.value()).c_str()) - .arg(render(t.safeSender())) - .arg(render(t.receiveAddress())) + .arg(QString::fromStdString(render(t.safeSender()))) + .arg(QString::fromStdString(render(t.receiveAddress()))) .arg((unsigned)t.nonce()) .arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') : QString(" %2 +> %3: %1 [%4]") .arg(formatBalance(t.value()).c_str()) - .arg(render(t.safeSender())) - .arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce()))))) + .arg(QString::fromStdString(render(t.safeSender()))) + .arg(QString::fromStdString(render(right160(sha3(rlpList(t.safeSender(), t.nonce())))))) .arg((unsigned)t.nonce()); QListWidgetItem* txItem = new QListWidgetItem(s, ui->blocks); auto hba = QByteArray((char const*)h.data(), h.size); @@ -1256,7 +1283,7 @@ string Main::renderDiff(StateDiff const& _d) const s << "
"; AccountDiff ad = i.second; - s << "" << lead(ad.changeType()) << " " << " " << render(i.first).toStdString() << ""; + s << "" << lead(ad.changeType()) << " " << " " << render(i.first) << ""; if (!ad.exist.to()) continue; @@ -1289,7 +1316,7 @@ string Main::renderDiff(StateDiff const& _d) const s << " * "; s << " "; - s << prettyU256(i.first).toStdString(); + s << prettyU256(i.first); /* if (i.first > u256(1) << 246) s << (h256)i.first; else if (i.first > u160(1) << 150) @@ -1298,11 +1325,11 @@ string Main::renderDiff(StateDiff const& _d) const s << hex << i.first; */ if (!i.second.from()) - s << ": " << prettyU256(i.second.to()).toStdString(); + s << ": " << prettyU256(i.second.to()); else if (!i.second.to()) - s << " (" << prettyU256(i.second.from()).toStdString() << ")"; + s << " (" << prettyU256(i.second.from()) << ")"; else - s << ": " << prettyU256(i.second.to()).toStdString() << " (" << prettyU256(i.second.from()).toStdString() << ")"; + s << ": " << prettyU256(i.second.to()) << " (" << prettyU256(i.second.from()) << ")"; } } return s.str(); @@ -1321,11 +1348,11 @@ void Main::on_transactionQueue_currentItemChanged() auto ss = tx.safeSender(); h256 th = sha3(rlpList(ss, tx.nonce())); s << "

" << th << "

"; - s << "From: " << pretty(ss).toStdString() << " " << ss; + s << "From: " << pretty(ss) << " " << ss; if (tx.isCreation()) - s << "
Creates: " << pretty(right160(th)).toStdString() << " " << right160(th); + s << "
Creates: " << pretty(right160(th)) << " " << right160(th); else - s << "
To: " << pretty(tx.receiveAddress()).toStdString() << " " << tx.receiveAddress(); + s << "
To: " << pretty(tx.receiveAddress()) << " " << tx.receiveAddress(); s << "
Value: " << formatBalance(tx.value()) << ""; s << "   #" << tx.nonce() << ""; s << "
Gas price: " << formatBalance(tx.gasPrice()) << ""; @@ -1413,6 +1440,11 @@ void Main::on_injectBlock_triggered() } } +static string htmlEscaped(string const& _s) +{ + return QString::fromStdString(_s).toHtmlEscaped().toStdString(); +} + void Main::on_blocks_currentItemChanged() { ui->info->clear(); @@ -1442,7 +1474,7 @@ void Main::on_blocks_currentItemChanged() s << "
D/TD: " << info.difficulty << "/" << details.totalDifficulty << " = 2^" << log2((double)info.difficulty) << "/2^" << log2((double)details.totalDifficulty) << "
"; s << "   Children: " << details.children.size() << ""; s << "
Gas used/limit: " << info.gasUsed << "/" << info.gasLimit << "" << "
"; - s << "
Beneficiary: " << pretty(info.coinbaseAddress).toHtmlEscaped().toStdString() << " " << info.coinbaseAddress << "" << "
"; + s << "
Beneficiary: " << htmlEscaped(pretty(info.coinbaseAddress)) << " " << info.coinbaseAddress << "" << "
"; s << "
Seed hash: " << info.seedHash() << "" << "
"; s << "
Mix hash: " << info.mixHash << "" << "
"; s << "
Nonce: " << info.nonce << "" << "
"; @@ -1473,7 +1505,7 @@ void Main::on_blocks_currentItemChanged() s << line << "Hash: " << uncle.hash() << "" << ""; s << line << "Parent: " << uncle.parentHash << "" << ""; s << line << "Number: " << uncle.number << "" << ""; - s << line << "Coinbase: " << pretty(uncle.coinbaseAddress).toHtmlEscaped().toStdString() << " " << uncle.coinbaseAddress << "" << ""; + s << line << "Coinbase: " << htmlEscaped(pretty(uncle.coinbaseAddress)) << " " << uncle.coinbaseAddress << "" << ""; s << line << "Seed hash: " << uncle.seedHash() << "" << ""; s << line << "Mix hash: " << uncle.mixHash << "" << ""; s << line << "Nonce: " << uncle.nonce << "" << ""; @@ -1508,11 +1540,11 @@ void Main::on_blocks_currentItemChanged() TransactionReceipt receipt = ethereum()->blockChain().receipts(h).receipts[txi]; s << "

" << th << "

"; s << "

" << h << "[" << txi << "]

"; - s << "
From: " << pretty(ss).toHtmlEscaped().toStdString() << " " << ss << "" << "
"; + s << "
From: " << htmlEscaped(pretty(ss)) << " " << ss << "" << "
"; if (tx.isCreation()) - s << "
Creates: " << pretty(right160(th)).toHtmlEscaped().toStdString() << " " << right160(th) << "
"; + s << "
Creates: " << htmlEscaped(pretty(right160(th))) << " " << right160(th) << "
"; else - s << "
To: " << pretty(tx.receiveAddress()).toHtmlEscaped().toStdString() << " " << tx.receiveAddress() << "
"; + s << "
To: " << htmlEscaped(pretty(tx.receiveAddress())) << " " << tx.receiveAddress() << "
"; s << "
Value: " << formatBalance(tx.value()) << "" << "
"; s << "   #" << tx.nonce() << "" << ""; s << "
Gas price: " << formatBalance(tx.gasPrice()) << "" << "
"; @@ -1590,10 +1622,10 @@ void Main::debugDumpState(int _add) } } -void Main::on_contracts_currentItemChanged() +void Main::on_accounts_currentItemChanged() { - ui->contractInfo->clear(); - if (auto item = ui->contracts->currentItem()) + ui->accountInfo->clear(); + if (auto item = ui->accounts->currentItem()) { auto hba = item->data(Qt::UserRole).toByteArray(); assert(hba.size() == 20); @@ -1604,16 +1636,16 @@ void Main::on_contracts_currentItemChanged() { auto storage = ethereum()->storageAt(address); for (auto const& i: storage) - s << "@" << showbase << hex << prettyU256(i.first).toStdString() << "    " << showbase << hex << prettyU256(i.second).toStdString() << "
"; + s << "@" << showbase << hex << prettyU256(i.first) << "    " << showbase << hex << prettyU256(i.second) << "
"; s << "

Body Code (" << sha3(ethereum()->codeAt(address)).abridged() << ")

" << disassemble(ethereum()->codeAt(address)); s << Div(Mono) << toHex(ethereum()->codeAt(address)) << ""; - ui->contractInfo->appendHtml(QString::fromStdString(s.str())); + ui->accountInfo->appendHtml(QString::fromStdString(s.str())); } catch (dev::InvalidTrie) { - ui->contractInfo->appendHtml("Corrupted trie."); + ui->accountInfo->appendHtml("Corrupted trie."); } - ui->contractInfo->moveCursor(QTextCursor::Start); + ui->accountInfo->moveCursor(QTextCursor::Start); } } @@ -1645,16 +1677,6 @@ void Main::on_accounts_doubleClicked() } } -void Main::on_contracts_doubleClicked() -{ - if (ui->contracts->count()) - { - auto hba = ui->contracts->currentItem()->data(Qt::UserRole).toByteArray(); - auto h = Address((byte const*)hba.data(), Address::ConstructFromPointer); - qApp->clipboard()->setText(QString::fromStdString(toHex(h.asArray()))); - } -} - static shh::FullTopic topicFromText(QString _s) { shh::BuildTopic ret; @@ -1885,7 +1907,12 @@ void Main::on_killAccount_triggered() if (ui->ourAccounts->currentRow() >= 0 && ui->ourAccounts->currentRow() < m_myKeys.size()) { auto k = m_myKeys[ui->ourAccounts->currentRow()]; - if (ethereum()->balanceAt(k.address()) != 0 && QMessageBox::critical(this, "Kill Account?!", "Account " + render(k.address()) + " has " + QString::fromStdString(formatBalance(ethereum()->balanceAt(k.address()))) + " in it. It, and any contract that this account can access, will be lost forever if you continue. Do NOT continue unless you know what you are doing.\nAre you sure you want to continue?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) + if ( + ethereum()->balanceAt(k.address()) != 0 && + QMessageBox::critical(this, "Kill Account?!", + QString::fromStdString("Account " + render(k.address()) + " has " + formatBalance(ethereum()->balanceAt(k.address())) + " in it. It, and any contract that this account can access, will be lost forever if you continue. Do NOT continue unless you know what you are doing.\n" + "Are you sure you want to continue?"), + QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) return; m_myKeys.erase(m_myKeys.begin() + ui->ourAccounts->currentRow()); keysChanged(); @@ -1902,10 +1929,10 @@ void Main::on_go_triggered() web3()->addNode(p2p::NodeId(), Host::pocHost()); } -QString Main::prettyU256(dev::u256 _n) const +std::string Main::prettyU256(dev::u256 const& _n) const { unsigned inc = 0; - QString raw; + string raw; ostringstream s; if (_n > szabo && _n < 1000000 * ether) s << "" << formatBalance(_n) << " (0x" << hex << (uint64_t)_n << ")"; @@ -1916,17 +1943,17 @@ QString Main::prettyU256(dev::u256 _n) const else if ((_n >> 160) == 0) { Address a = right160(_n); - QString n = pretty(a); - if (n.isNull()) + string n = pretty(a); + if (n.empty()) s << "0x" << a << ""; else - s << "" << n.toHtmlEscaped().toStdString() << " (0x" << a.abridged() << ")"; + s << "" << htmlEscaped(n) << " (0x" << a.abridged() << ")"; } else if ((raw = fromRaw((h256)_n, &inc)).size()) - return "\"" + raw.toHtmlEscaped() + "\"" + (inc ? " + " + QString::number(inc) : "") + ""; + return "\"" + htmlEscaped(raw) + "\"" + (inc ? " + " + toString(inc) : "") + ""; else s << "0x" << (h256)_n << ""; - return QString::fromStdString(s.str()); + return s.str(); } void Main::on_post_clicked() diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 2a0c1401d..127b174c6 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -80,10 +80,10 @@ public: bool confirm() const; NatSpecFace* natSpec() { return &m_natSpecDB; } - QString pretty(dev::Address _a) const override; - QString prettyU256(dev::u256 _n) const override; - QString render(dev::Address _a) const override; - std::pair fromString(QString const& _a) const override; + std::string pretty(dev::Address const& _a) const override; + std::string prettyU256(dev::u256 const& _n) const override; + std::string render(dev::Address const& _a) const override; + std::pair fromString(std::string const& _a) const override; std::string renderDiff(dev::eth::StateDiff const& _d) const override; QList owned() const { return m_myIdentities + m_myKeys; } @@ -131,6 +131,13 @@ private slots: void on_importKeyFile_triggered(); void on_exportKey_triggered(); + // Account pane + void on_accountsFilter_textChanged(); + void on_showBasic_toggled(); + void on_showContracts_toggled(); + void on_onlyNamed_toggled(); + void on_refreshAccounts_clicked(); + // Tools void on_newTransaction_triggered(); void on_loadJS_triggered(); @@ -140,8 +147,7 @@ private slots: void ourAccountsRowsMoved(); void on_ourAccounts_doubleClicked(); void on_accounts_doubleClicked(); - void on_contracts_doubleClicked(); - void on_contracts_currentItemChanged(); + void on_accounts_currentItemChanged(); void on_transactionQueue_currentItemChanged(); void on_blockChainFilter_textChanged(); void on_blocks_currentItemChanged(); @@ -254,7 +260,7 @@ private: std::unique_ptr m_httpConnector; std::unique_ptr m_server; - static QString fromRaw(dev::h256 _n, unsigned* _inc = nullptr); + static std::string fromRaw(dev::h256 _n, unsigned* _inc = nullptr); NatspecHandler m_natSpecDB; Transact m_transact; diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp index da588ba3e..161bb4926 100644 --- a/alethzero/OurWebThreeStubServer.cpp +++ b/alethzero/OurWebThreeStubServer.cpp @@ -73,7 +73,7 @@ bool OurWebThreeStubServer::showCreationNotice(TransactionSkeleton const& _t, bo bool OurWebThreeStubServer::showSendNotice(TransactionSkeleton const& _t, bool _toProxy) { - return showAuthenticationPopup("Fund Transfer Transaction", "ÐApp is attempting to send " + formatBalance(_t.value) + " to a recipient " + m_main->pretty(_t.to).toStdString() + (_toProxy ? " (this transaction is not executed directly, but forwarded to another ÐApp)" : "") + + return showAuthenticationPopup("Fund Transfer Transaction", "ÐApp is attempting to send " + formatBalance(_t.value) + " to a recipient " + m_main->pretty(_t.to) + (_toProxy ? " (this transaction is not executed directly, but forwarded to another ÐApp)" : "") + ", with additional network fees of up to " + formatBalance(_t.gas * _t.gasPrice) + ".\n\nMaximum total cost is " + formatBalance(_t.value + _t.gas * _t.gasPrice) + "."); } @@ -81,7 +81,7 @@ bool OurWebThreeStubServer::showUnknownCallNotice(TransactionSkeleton const& _t, { return showAuthenticationPopup("DANGEROUS! Unknown Contract Transaction!", "ÐApp is attempting to call into an unknown contract at address " + - m_main->pretty(_t.to).toStdString() + ".\n\n" + + m_main->pretty(_t.to) + ".\n\n" + (_toProxy ? "This transaction is not executed directly, but forwarded to another ÐApp.\n\n" : "") + "Call involves sending " + formatBalance(_t.value) + " to the recipient, with additional network fees of up to " + @@ -137,7 +137,7 @@ bool OurWebThreeStubServer::validateTransaction(TransactionSkeleton const& _t, b // otherwise it's a transaction to a contract for which we have the natspec return showAuthenticationPopup("Contract Transaction", "ÐApp attempting to conduct contract interaction with " + - m_main->pretty(_t.to).toStdString() + + m_main->pretty(_t.to) + ": " + userNotice + ".\n\n" + (_toProxy ? "This transaction is not executed directly, but forwarded to another ÐApp.\n\n" : "") + (_t.value > 0 ? diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index 6f6e47d16..2041bf39d 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -110,12 +110,12 @@ void Transact::updateDestination() cwatch << "updateDestination()"; QString s; for (auto i: ethereum()->addresses()) - if ((s = m_context->pretty(i)).size()) + if ((s = QString::fromStdString(m_context->pretty(i))).size()) // A namereg address if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1) ui->destination->addItem(s); for (int i = 0; i < ui->destination->count(); ++i) - if (ui->destination->itemText(i) != "(Create Contract)" && !m_context->fromString(ui->destination->itemText(i)).first) + if (ui->destination->itemText(i) != "(Create Contract)" && !m_context->fromString(ui->destination->itemText(i).toStdString()).first) ui->destination->removeItem(i--); } @@ -142,9 +142,9 @@ void Transact::on_destination_currentTextChanged(QString) { if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)") { - auto p = m_context->fromString(ui->destination->currentText()); + auto p = m_context->fromString(ui->destination->currentText().toStdString()); if (p.first) - ui->calculatedName->setText(m_context->render(p.first)); + ui->calculatedName->setText(QString::fromStdString(m_context->render(p.first))); else ui->calculatedName->setText("Unknown Address"); if (!p.second.empty()) @@ -347,7 +347,7 @@ void Transact::rejigData() else { // TODO: cache like m_data. - to = m_context->fromString(ui->destination->currentText()).first; + to = m_context->fromString(ui->destination->currentText().toStdString()).first; er = ethereum()->call(s, value(), to, m_data, gasNeeded, gasPrice()); } gasNeeded = (qint64)(er.gasUsed + er.gasRefunded); @@ -434,7 +434,7 @@ void Transact::on_send_clicked() } else // TODO: cache like m_data. - ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText()).first, m_data, ui->gas->value(), gasPrice()); + ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText().toStdString()).first, m_data, ui->gas->value(), gasPrice()); close(); } @@ -453,7 +453,7 @@ void Transact::on_debug_clicked() State st(ethereum()->postState()); Transaction t = isCreation() ? Transaction(value(), gasPrice(), ui->gas->value(), m_data, st.transactionsFrom(dev::toAddress(s)), s) : - Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText()).first, m_data, st.transactionsFrom(dev::toAddress(s)), s); + Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText().toStdString()).first, m_data, st.transactionsFrom(dev::toAddress(s)), s); Debugger dw(m_context, this); Executive e(st, ethereum()->blockChain(), 0); dw.populate(e, t); diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 3defa57b2..72b5543a8 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -21,6 +21,7 @@ #include "Common.h" #include "Exceptions.h" +#include "Log.h" using namespace std; using namespace dev; @@ -35,5 +36,10 @@ void HasInvariants::checkInvariants() const BOOST_THROW_EXCEPTION(FailedInvariant()); } +TimerHelper::~TimerHelper() +{ + cdebug << "Timer" << id << t.elapsed() << "s"; +} + } diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 03da4c8aa..aa18baba5 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -37,6 +37,7 @@ #include #include #include +#include #pragma warning(push) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" @@ -168,6 +169,21 @@ private: #define DEV_INVARIANT_CHECK (void)0; #endif +class TimerHelper +{ +public: + TimerHelper(char const* _id): id(_id) {} + ~TimerHelper(); + +private: + boost::timer t; + char const* id; +}; + +#define DEV_TIMED(S) for (::std::pair<::dev::TimerHelper, bool> __eth_t(#S, true); __eth_t.second; __eth_t.second = false) +#define DEV_TIMED_SCOPE(S) ::dev::TimerHelper __eth_t(S) +#define DEV_TIMED_FUNCTION DEV_TIMED_SCOPE(__PRETTY_FUNCTION__) + enum class WithExisting: int { Trust = 0, diff --git a/libethcore/ICAP.h b/libethcore/ICAP.h index 07e863d8d..b4229e1f5 100644 --- a/libethcore/ICAP.h +++ b/libethcore/ICAP.h @@ -51,8 +51,6 @@ public: ICAP() = default; /// Construct a direct ICAP object for given target address. Must have a zero first byte. ICAP(Address const& _target): m_type(Direct), m_direct(_target) {} - /// Construct an indirect ICAP object for given target name. - ICAP(std::string const& _target): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_target)), m_asset("ETH") {} /// Construct an indirect ICAP object for given client and institution names. ICAP(std::string const& _client, std::string const& _inst): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_client)), m_institution(boost::algorithm::to_upper_copy(_inst)), m_asset("XET") {} /// Construct an indirect ICAP object for given client, institution and asset names. You generally don't want to use this. diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index e8ab0ff2f..394b0007e 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -36,12 +36,6 @@ using namespace dev; using namespace dev::eth; using namespace p2p; -namespace dev -{ -struct TimerHelper { TimerHelper(char const* _id): id(_id) {} ~TimerHelper() { cdebug << "Timer" << id << t.elapsed() << "s"; } boost::timer t; char const* id; }; -#define DEV_TIMED(S) for (::std::pair<::dev::TimerHelper, bool> __eth_t(#S, true); __eth_t.second; __eth_t.second = false) -} - VersionChecker::VersionChecker(string const& _dbPath): m_path(_dbPath.size() ? _dbPath : Defaults::dbPath()) { @@ -586,7 +580,9 @@ void Client::onChainChanged(ImportRoute const& _ir) for (auto const& t: m_postMine.pending()) { clog(ClientNote) << "Resubmitting post-mine transaction " << t; - m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry); + auto ir = m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry); + if (ir != ImportResult::Success) + onTransactionQueueReady(); } ETH_READ_GUARDED(x_working) DEV_TIMED(post) ETH_WRITE_GUARDED(x_postMine) m_postMine = m_working; @@ -596,6 +592,10 @@ void Client::onChainChanged(ImportRoute const& _ir) onPostStateChanged(); } + // Quick hack for now - the TQ at this point already has the prior pending transactions in it; + // we should resync with it manually until we are stricter about what constitutes "knowing". + onTransactionQueueReady(); + noteChanged(changeds); } diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index eba8dbc67..136239cf3 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -142,6 +142,11 @@ bytes ClientBase::codeAt(Address _a, BlockNumber _block) const return asOf(_block).code(_a); } +h256 ClientBase::codeHashAt(Address _a, BlockNumber _block) const +{ + return asOf(_block).codeHash(_a); +} + map ClientBase::storageAt(Address _a, BlockNumber _block) const { return asOf(_block).storage(_a); diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index 64dc2b6c7..fc0b301ad 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -92,12 +92,14 @@ public: using Interface::countAt; using Interface::stateAt; using Interface::codeAt; + using Interface::codeHashAt; using Interface::storageAt; virtual u256 balanceAt(Address _a, BlockNumber _block) const override; virtual u256 countAt(Address _a, BlockNumber _block) const override; virtual u256 stateAt(Address _a, u256 _l, BlockNumber _block) const override; virtual bytes codeAt(Address _a, BlockNumber _block) const override; + virtual h256 codeHashAt(Address _a, BlockNumber _block) const override; virtual std::map storageAt(Address _a, BlockNumber _block) const override; virtual LocalisedLogEntries logs(unsigned _watchId) const override; diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 6edd97b4c..8fb94bdd0 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -100,12 +100,14 @@ public: u256 countAt(Address _a) const { return countAt(_a, m_default); } u256 stateAt(Address _a, u256 _l) const { return stateAt(_a, _l, m_default); } bytes codeAt(Address _a) const { return codeAt(_a, m_default); } + h256 codeHashAt(Address _a) const { return codeHashAt(_a, m_default); } std::map storageAt(Address _a) const { return storageAt(_a, m_default); } virtual u256 balanceAt(Address _a, BlockNumber _block) const = 0; virtual u256 countAt(Address _a, BlockNumber _block) const = 0; virtual u256 stateAt(Address _a, u256 _l, BlockNumber _block) const = 0; virtual bytes codeAt(Address _a, BlockNumber _block) const = 0; + virtual h256 codeHashAt(Address _a, BlockNumber _block) const = 0; virtual std::map storageAt(Address _a, BlockNumber _block) const = 0; // [LOGS API] diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 1bfdf535a..5aca67a29 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -36,7 +36,6 @@ ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallb h256 h = sha3(_transactionRLP); UpgradableGuard l(m_lock); - // TODO: keep old transactions around and check in State for nonce validity auto ir = check_WITH_LOCK(h, _ik); if (ir != ImportResult::Success) diff --git a/libjsqrc/setup.js b/libjsqrc/setup.js index 78ca2ffad..1423a5cd3 100644 --- a/libjsqrc/setup.js +++ b/libjsqrc/setup.js @@ -21,5 +21,5 @@ */ var web3 = require('web3'); -web3.setProvider(new web3.providers.HttpProvider("http://localhost:8080")); +web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545"));