() == 0)
s << "Sealing client: " << htmlEscaped(r[1].toString()) << "" << "
";
}
catch (...) {}
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: " << htmlEscaped(pretty(info.beneficiary())) << " " << info.beneficiary() << "" << "
";
s << "Seed hash: " << info.seedHash() << "" << "
";
s << "Mix hash: " << info.mixHash() << "" << "
";
s << "Nonce: " << info.nonce() << "" << "
";
s << "Hash w/o nonce: " << info.hashWithout() << "" << "
";
s << "Difficulty: " << info.difficulty() << "" << "
";
if (info.number())
{
auto e = EthashAux::eval(info.seedHash(), info.hashWithout(), info.nonce());
s << "Proof-of-Work: " << e.value << " <= " << (h256)u256((bigint(1) << 256) / info.difficulty()) << " (mixhash: " << e.mixHash.abridged() << ")" << "
";
s << "Parent: " << info.parentHash() << "" << "
";
}
else
{
s << "Proof-of-Work: Phil has nothing to prove
";
s << "Parent: It was a virgin birth
";
}
// s << "Bloom:
" << details.bloom << "";
s << "
State root: " << ETH_HTML_SPAN(ETH_HTML_MONO) << info.stateRoot().hex() << "
";
s << "
Extra data: " << ETH_HTML_SPAN(ETH_HTML_MONO) << toHex(info.extraData()) << "
";
if (!!info.logBloom())
s << "
Log Bloom: " << info.logBloom() << "
";
else
s << "
Log Bloom: Uneventful
";
s << "
Transactions: " << block[1].itemCount() << " @" << info.transactionsRoot() << "" << "
";
s << "
Uncles: " << block[2].itemCount() << " @" << info.sha3Uncles() << "" << "
";
for (auto u: block[2])
{
Ethash::BlockHeader uncle(u.data(), CheckNothing, h256(), HeaderData);
char const* line = "
";
s << line << "Hash: " << uncle.hash() << "" << "
";
s << line << "Parent:
" << uncle.parentHash() << "" << "
";
s << line << "Number: " << uncle.number() << "" << "";
s << line << "Coinbase: " << htmlEscaped(pretty(uncle.beneficiary())) << " " << uncle.beneficiary() << "" << "";
s << line << "Seed hash: " << uncle.seedHash() << "" << "";
s << line << "Mix hash: " << uncle.mixHash() << "" << "";
s << line << "Nonce: " << uncle.nonce() << "" << "";
s << line << "Hash w/o nonce: " << uncle.headerHash(WithoutProof) << "" << "";
s << line << "Difficulty: " << uncle.difficulty() << "" << "";
auto e = EthashAux::eval(uncle.seedHash(), uncle.hashWithout(), uncle.nonce());
s << line << "Proof-of-Work: " << e.value << " <= " << (h256)u256((bigint(1) << 256) / uncle.difficulty()) << " (mixhash: " << e.mixHash.abridged() << ")" << "";
}
if (info.parentHash())
s << "Pre: " << BlockInfo(ethereum()->blockChain().block(info.parentHash())).stateRoot() << "" << "
";
else
s << "Pre: Nothing is before Phil" << "
";
s << "Receipts: @" << info.receiptsRoot() << ":" << "
";
BlockReceipts receipts = ethereum()->blockChain().receipts(h);
unsigned ii = 0;
for (auto const& i: block[1])
{
s << "" << sha3(i.data()).abridged() << ": " << receipts.receipts[ii].stateRoot() << " [" << receipts.receipts[ii].gasUsed() << " used]" << "
";
++ii;
}
s << "Post: " << info.stateRoot() << "" << "
";
s << "Dump: " ETH_HTML_SPAN(ETH_HTML_MONO) << toHex(block[0].data()) << "" << "
";
s << "Receipts-Hex: " ETH_HTML_SPAN(ETH_HTML_MONO) << toHex(receipts.rlp()) << "
";
}
else
{
unsigned txi = item->data(Qt::UserRole + 1).toInt();
Transaction tx(block[1][txi].data(), CheckTransaction::Everything);
auto ss = tx.safeSender();
h256 th = sha3(rlpList(ss, tx.nonce()));
TransactionReceipt receipt = ethereum()->blockChain().receipts(h).receipts[txi];
s << "" << th << "
";
s << "" << h << "[" << txi << "]
";
s << "From: " << htmlEscaped(pretty(ss)) << " " << ss << "" << "
";
if (tx.isCreation())
s << "Creates: " << htmlEscaped(pretty(right160(th))) << " " << right160(th) << "
";
else
s << "To: " << htmlEscaped(pretty(tx.receiveAddress())) << " " << tx.receiveAddress() << "
";
s << "Value: " << formatBalance(tx.value()) << "" << "
";
s << " #" << tx.nonce() << "" << "";
s << "Gas price: " << formatBalance(tx.gasPrice()) << "" << "
";
s << "Gas: " << tx.gas() << "" << "
";
s << "V: " << hex << nouppercase << (int)tx.signature().v << " + 27" << "
";
s << "R: " << hex << nouppercase << tx.signature().r << "" << "
";
s << "S: " << hex << nouppercase << tx.signature().s << "" << "
";
s << "Msg: " << tx.sha3(eth::WithoutSignature) << "" << "
";
if (!tx.data().empty())
{
if (tx.isCreation())
s << "Code
" << disassemble(tx.data());
else
s << "Data
" << dev::memDump(tx.data(), 16, true);
}
s << "Hex: " ETH_HTML_SPAN(ETH_HTML_MONO) << toHex(block[1][txi].data()) << "
";
s << "
";
if (!!receipt.bloom())
s << "Log Bloom: " << receipt.bloom() << "
";
else
s << "Log Bloom: Uneventful
";
s << "Gas Used: " << receipt.gasUsed() << "
";
s << "End State: " << receipt.stateRoot().abridged() << "
";
auto r = receipt.rlp();
s << "Receipt: " << toString(RLP(r)) << "
";
s << "Receipt-Hex: " ETH_HTML_SPAN(ETH_HTML_MONO) << toHex(receipt.rlp()) << "
";
s << "Diff
" << renderDiff(ethereum()->diff(txi, h));
ui->debugCurrent->setEnabled(true);
ui->debugDumpState->setEnabled(true);
ui->debugDumpStatePre->setEnabled(true);
}
ui->info->appendHtml(QString::fromStdString(s.str()));
ui->info->moveCursor(QTextCursor::Start);
}
}
void Main::on_debugCurrent_triggered()
{
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);
if (!item->data(Qt::UserRole + 1).isNull())
{
unsigned txi = item->data(Qt::UserRole + 1).toInt();
bytes t = ethereum()->blockChain().transaction(h, txi);
State s(ethereum()->state(txi, h));
BlockInfo bi(ethereum()->blockChain().info(h));
Executive e(s, ethereum()->blockChain(), EnvInfo(bi));
Debugger dw(this, this);
dw.populate(e, Transaction(t, CheckTransaction::Everything));
dw.exec();
}
}
}
void Main::on_debugPending_triggered()
{
int txi = ui->transactionQueue->currentRow();
if (txi == -1)
return;
Block b = ethereum()->postState();
bytes t = b.pending()[txi].rlp();
State s(ethereum()->state(txi));
BlockInfo bi(b.info());
Executive e(s, ethereum()->blockChain(), EnvInfo(bi));
Debugger dw(this, this);
dw.populate(e, Transaction(t, CheckTransaction::Everything));
dw.exec();
}
std::string minHex(h256 const& _h)
{
unsigned i = 0;
for (; i < 31 && !_h[i]; ++i) {}
return toHex(_h.ref().cropped(i));
}
void Main::on_dumpBlockState_triggered()
{
#if ETH_FATDB || !ETH_TRUE
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);
QString fn = QFileDialog::getSaveFileName(this, "Select file to output state dump");
ofstream f(fn.toStdString());
if (f.is_open())
{
f << "{" << endl;
// js::mObject s;
State state = ethereum()->block(h).state();
int fi = 0;
for (pair const& i: state.addresses())
{
f << (fi++ ? "," : "") << "\"" << i.first.hex() << "\": { ";
f << "\"balance\": \"" << toString(i.second) << "\", ";
if (state.codeHash(i.first) != EmptySHA3)
{
f << "\"codeHash\": \"" << state.codeHash(i.first).hex() << "\", ";
f << "\"storage\": {";
int fj = 0;
for (pair const& j: state.storage(i.first))
f << (fj++ ? "," : "") << "\"" << minHex(j.first) << "\":\"" << minHex(j.second) << "\"";
f << "}, ";
}
f << "\"nonce\": \"" << toString(state.transactionsFrom(i.first)) << "\"";
f << "}" << endl; // end account
if (!(fi % 100))
f << flush;
}
f << "}";
}
}
#endif
}
void Main::debugDumpState(int _add)
{
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);
if (!item->data(Qt::UserRole + 1).isNull())
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output state dump");
ofstream f(fn.toStdString());
if (f.is_open())
{
unsigned txi = item->data(Qt::UserRole + 1).toInt();
f << ethereum()->state(txi + _add, h) << endl;
}
}
}
}
void Main::on_idealPeers_valueChanged(int)
{
m_webThree->setIdealPeerCount(ui->idealPeers->value());
}
void Main::on_ourAccounts_doubleClicked()
{
auto hba = ui->ourAccounts->currentItem()->data(Qt::UserRole).toByteArray();
auto h = Address((byte const*)hba.data(), Address::ConstructFromPointer);
qApp->clipboard()->setText(QString::fromStdString(ICAP(h).encoded()) + " (" + QString::fromStdString(h.hex()) + ")");
}
/*void Main::on_log_doubleClicked()
{
ui->log->setPlainText("");
m_logHistory.clear();
}*/
void Main::on_clearPending_triggered()
{
writeSettings();
ui->mine->setChecked(false);
ui->net->setChecked(false);
web3()->stopNetwork();
ethereum()->clearPending();
readSettings(true);
installWatches();
refreshAll();
}
void Main::on_retryUnknown_triggered()
{
ethereum()->retryUnknown();
}
void Main::on_killBlockchain_triggered()
{
writeSettings();
ui->mine->setChecked(false);
ui->net->setChecked(false);
web3()->stopNetwork();
ethereum()->killChain();
readSettings(true);
installWatches();
refreshAll();
}
void Main::on_net_triggered()
{
ui->port->setEnabled(!ui->net->isChecked());
ui->clientName->setEnabled(!ui->net->isChecked());
web3()->setClientVersion(WebThreeDirect::composeClientVersion("AlethZero", ui->clientName->text().toStdString()));
if (ui->net->isChecked())
{
web3()->setIdealPeerCount(ui->idealPeers->value());
web3()->setNetworkPreferences(netPrefs(), ui->dropPeers->isChecked());
ethereum()->setNetworkId((h256)(u256)(int)c_network);
web3()->startNetwork();
ui->downloadView->setEthereum(ethereum());
ui->enode->setText(QString::fromStdString(web3()->enode()));
}
else
{
ui->downloadView->setEthereum(nullptr);
writeSettings();
web3()->stopNetwork();
}
}
void Main::on_connect_triggered()
{
if (!ui->net->isChecked())
{
ui->net->setChecked(true);
on_net_triggered();
}
m_connect.setEnvironment(m_servers);
if (m_connect.exec() == QDialog::Accepted)
{
bool required = m_connect.required();
string host(m_connect.host().toStdString());
NodeId nodeID;
try
{
nodeID = NodeId(fromHex(m_connect.nodeId().toStdString()));
}
catch (BadHexCharacter&) {}
m_connect.reset();
if (required)
web3()->requirePeer(nodeID, host);
else
web3()->addNode(nodeID, host);
}
}
void Main::on_mine_triggered()
{
if (ui->mine->isChecked())
{
// EthashAux::computeFull(ethereum()->blockChain().number());
ethereum()->setBeneficiary(m_beneficiary);
ethereum()->startMining();
}
else
ethereum()->stopMining();
}
void Main::keysChanged()
{
emit keyManagerChanged();
onBalancesChange();
}
void Main::on_killAccount_triggered()
{
if (ui->ourAccounts->currentRow() >= 0)
{
auto hba = ui->ourAccounts->currentItem()->data(Qt::UserRole).toByteArray();
Address h((byte const*)hba.data(), Address::ConstructFromPointer);
QString s = QInputDialog::getText(this, QString::fromStdString("Kill Account " + m_keyManager.accountName(h) + "?!"),
QString::fromStdString("Account " + m_keyManager.accountName(h) + " (" + render(h) + ") has " + formatBalance(ethereum()->balanceAt(h)) + " in it.\r\nIt, 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? \r\n If so, type 'YES' to confirm."),
QLineEdit::Normal, "NO");
if (s != "YES")
return;
m_keyManager.kill(h);
if (m_keyManager.accounts().empty())
m_keyManager.import(Secret::random(), "Default account");
m_beneficiary = m_keyManager.accounts().front();
keysChanged();
if (m_beneficiary == h)
setBeneficiary(m_keyManager.accounts().front());
}
}
void Main::on_reencryptKey_triggered()
{
if (ui->ourAccounts->currentRow() >= 0)
{
auto hba = ui->ourAccounts->currentItem()->data(Qt::UserRole).toByteArray();
Address a((byte const*)hba.data(), Address::ConstructFromPointer);
QStringList kdfs = {"PBKDF2-SHA256", "Scrypt"};
bool ok = true;
KDF kdf = (KDF)kdfs.indexOf(QInputDialog::getItem(this, "Re-Encrypt Key", "Select a key derivation function to use for storing your key:", kdfs, kdfs.size() - 1, false, &ok));
if (!ok)
return;
std::string hint;
std::string password = getPassword("Create Account", "Enter the password you would like to use for this key. Don't forget it!\nEnter nothing to use your Master password.", &hint, &ok);
if (!ok)
return;
try {
auto pw = [&](){
auto p = QInputDialog::getText(this, "Re-Encrypt Key", "Enter the original password for this key.\nHint: " + QString::fromStdString(m_keyManager.passwordHint(a)), QLineEdit::Password, QString()).toStdString();
if (p.empty())
throw PasswordUnknown();
return p;
};
while (!(password.empty() ? m_keyManager.recode(a, SemanticPassword::Master, pw, kdf) : m_keyManager.recode(a, password, hint, pw, kdf)))
if (QMessageBox::question(this, "Re-Encrypt Key", "Password given is incorrect. Would you like to try again?", QMessageBox::Retry, QMessageBox::Cancel) == QMessageBox::Cancel)
return;
}
catch (PasswordUnknown&) {}
}
}
void Main::on_reencryptAll_triggered()
{
QStringList kdfs = {"PBKDF2-SHA256", "Scrypt"};
bool ok = false;
QString kdf = QInputDialog::getItem(this, "Re-Encrypt Key", "Select a key derivation function to use for storing your keys:", kdfs, kdfs.size() - 1, false, &ok);
if (!ok)
return;
try {
for (Address const& a: m_keyManager.accounts())
while (!m_keyManager.recode(a, SemanticPassword::Existing, [&](){
auto p = QInputDialog::getText(nullptr, "Re-Encrypt Key", QString("Enter the original password for key %1.\nHint: %2").arg(QString::fromStdString(pretty(a))).arg(QString::fromStdString(m_keyManager.passwordHint(a))), QLineEdit::Password, QString()).toStdString();
if (p.empty())
throw PasswordUnknown();
return p;
}, (KDF)kdfs.indexOf(kdf)))
if (QMessageBox::question(this, "Re-Encrypt Key", "Password given is incorrect. Would you like to try again?", QMessageBox::Retry, QMessageBox::Cancel) == QMessageBox::Cancel)
return;
}
catch (PasswordUnknown&) {}
}
void Main::on_go_triggered()
{
if (!ui->net->isChecked())
{
ui->net->setChecked(true);
on_net_triggered();
}
for (auto const& i: Host::pocHosts())
web3()->requirePeer(i.first, i.second);
}
std::string Main::prettyU256(dev::u256 const& _n) const
{
unsigned inc = 0;
string raw;
ostringstream s;
if (_n > szabo && _n < 1000000 * ether)
s << "" << formatBalance(_n) << " (0x" << hex << (uint64_t)_n << ")";
else if (!(_n >> 64))
s << "" << (uint64_t)_n << " (0x" << hex << (uint64_t)_n << ")";
else if (!~(_n >> 64))
s << "" << (int64_t)_n << " (0x" << hex << (int64_t)_n << ")";
else if ((_n >> 160) == 0)
{
Address a = right160(_n);
string n = pretty(a);
if (n.empty())
s << "0x" << a << "";
else
s << "" << htmlEscaped(n) << " (0x" << a.abridged() << ")";
}
else if ((raw = fromRaw((h256)_n, &inc)).size())
return "\"" + htmlEscaped(raw) + "\"" + (inc ? " + " + toString(inc) : "") + "";
else
s << "0x" << (h256)_n << "";
return s.str();
}
int Main::authenticate(QString _title, QString _text)
{
QMessageBox userInput(this);
userInput.setText(_title);
userInput.setInformativeText(_text);
userInput.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
userInput.button(QMessageBox::Ok)->setText("Allow");
userInput.button(QMessageBox::Cancel)->setText("Reject");
userInput.setDefaultButton(QMessageBox::Cancel);
return userInput.exec();
}
void Main::dappLoaded(Dapp& _dapp)
{
QUrl url = m_dappHost->hostDapp(std::move(_dapp));
ui->webView->page()->setUrl(url);
}
void Main::pageLoaded(QByteArray const& _content, QString const& _mimeType, QUrl const& _uri)
{
ui->webView->page()->setContent(_content, _mimeType, _uri);
}
void Main::initPlugin(Plugin* _p)
{
QSettings s("ethereum", "alethzero");
_p->readSettings(s);
}
void Main::finalisePlugin(Plugin* _p)
{
QSettings s("ethereum", "alethzero");
_p->writeSettings(s);
}
void Main::unloadPlugin(string const& _name)
{
shared_ptr p = takePlugin(_name);
if (p)
finalisePlugin(p.get());
}