const& keys)
return {begin(list), end(list)};
}
-static QString contentsOfQResource(string const& res)
+QString contentsOfQResource(string const& res)
{
QFile file(QString::fromStdString(res));
if (!file.open(QFile::ReadOnly))
@@ -112,7 +112,7 @@ static QString contentsOfQResource(string const& res)
}
//Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f");
-Address c_newConfig = Address("661005d2720d855f1d9976f88bb10c1a3398c77f");
+Address c_newConfig = Address("c6d9d2cd449a754c494264e1809c50e34d64562b");
//Address c_nameReg = Address("ddd1cea741d548f90d86fb87a3ae6492e18c03a1");
Main::Main(QWidget *parent) :
@@ -178,13 +178,13 @@ Main::Main(QWidget *parent) :
QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
QWebFrame* f = ui->webView->page()->mainFrame();
f->disconnect(SIGNAL(javaScriptWindowObjectCleared()));
+
connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qweb));
connect(m_qweb, SIGNAL(onNewId(QString)), this, SLOT(addNewId(QString)));
});
connect(ui->webView, &QWebView::loadFinished, [=]()
{
- m_qweb->poll();
});
connect(ui->webView, &QWebView::titleChanged, [=]()
@@ -311,7 +311,7 @@ void Main::installBalancesWatch()
altCoins.push_back(right160(ethereum()->stateAt(coinsAddr, i + 1)));
for (auto i: m_myKeys)
for (auto c: altCoins)
- tf.address(c).topic(h256(i.address(), h256::AlignRight));
+ tf.address(c).topic(0, h256(i.address(), h256::AlignRight));
uninstallWatch(m_balancesFilter);
m_balancesFilter = installWatch(tf, [=](LocalisedLogEntries const&){ onBalancesChange(); });
@@ -434,6 +434,11 @@ void Main::on_jsInput_returnPressed()
ui->jsInput->setText("");
}
+QVariant Main::evalRaw(QString const& _js)
+{
+ return ui->webView->page()->currentFrame()->evaluateJavaScript(_js);
+}
+
void Main::eval(QString const& _js)
{
if (_js.trimmed().isEmpty())
@@ -721,7 +726,7 @@ void Main::readSettings(bool _skipGeometry)
ui->enableOptimizer->setChecked(m_enableOptimizer);
ui->clientName->setText(s.value("clientName", "").toString());
if (ui->clientName->text().isEmpty())
- ui->clientName->setText(QInputDialog::getText(this, "Enter identity", "Enter a name that will identify you on the peer network"));
+ ui->clientName->setText(QInputDialog::getText(nullptr, "Enter identity", "Enter a name that will identify you on the peer network"));
ui->idealPeers->setValue(s.value("idealPeers", ui->idealPeers->value()).toInt());
ui->port->setValue(s.value("port", ui->port->value()).toInt());
ui->nameReg->setText(s.value("nameReg", "").toString());
@@ -783,6 +788,7 @@ void Main::on_importKeyFile_triggered()
}
}
+ cnote << k.address();
if (std::find(m_myKeys.begin(), m_myKeys.end(), k) == m_myKeys.end())
{
if (m_myKeys.empty())
@@ -1179,9 +1185,6 @@ void Main::timerEvent(QTimerEvent*)
else
interval += 100;
- if (m_qweb)
- m_qweb->poll();
-
for (auto const& i: m_handlers)
{
auto ls = ethereum()->checkWatch(i.first);
@@ -1594,7 +1597,7 @@ void Main::on_destination_currentTextChanged()
// updateFee();
}
-static shh::Topic topicFromText(QString _s)
+static shh::FullTopic topicFromText(QString _s)
{
shh::BuildTopic ret;
while (_s.size())
@@ -1671,7 +1674,7 @@ string const Main::getFunctionHashes(dev::solidity::CompilerStack const &_compil
{
ret += it.first.abridged();
ret += " :";
- ret += it.second->getName() + "\n";
+ ret += it.second->getDeclaration().getName() + "\n";
}
return ret;
}
@@ -1697,7 +1700,7 @@ void Main::on_data_textChanged()
// compiler.addSources(dev::solidity::StandardSources);
m_data = compiler.compile(src, m_enableOptimizer);
solidity = "Solidity
";
- solidity += "" + QString::fromStdString(compiler.getInterface()).replace(QRegExp("\\s"), "").toHtmlEscaped() + "
";
+ solidity += "var " + QString::fromStdString(compiler.getContractNames().front()) + " = web3.eth.contractFromAbi(" + QString::fromStdString(compiler.getInterface()).replace(QRegExp("\\s"), "").toHtmlEscaped() + ");
";
solidity += "" + QString::fromStdString(compiler.getSolidityInterface()).toHtmlEscaped() + "
";
solidity += "" + QString::fromStdString(getFunctionHashes(compiler)).toHtmlEscaped() + "
";
}
@@ -1990,16 +1993,71 @@ bool beginsWith(Address _a, bytes const& _b)
void Main::on_create_triggered()
{
bool ok = true;
- QString s = QInputDialog::getText(this, "Special Beginning?", "If you want a special key, enter some hex digits that it should begin with.\nNOTE: The more you enter, the longer generation will take.", QLineEdit::Normal, QString(), &ok);
+ enum { NoVanity = 0, FirstTwo, FirstTwoNextTwo, FirstThree, FirstFour, StringMatch };
+ QStringList items = {"No vanity (instant)", "Two pairs first (a few seconds)", "Two pairs first and second (a few minutes)", "Three pairs first (a few minutes)", "Four pairs first (several hours)", "Specific hex string"};
+ unsigned v = items.QList::indexOf(QInputDialog::getItem(this, "Vanity Key?", "Would you a vanity key? This could take several hours.", items, 0, false, &ok));
if (!ok)
return;
+
+ bytes bs;
+ if (v == StringMatch)
+ {
+ QString s = QInputDialog::getText(this, "Vanity Beginning?", "Enter some hex digits that it should begin with.\nNOTE: The more you enter, the longer generation will take.", QLineEdit::Normal, QString(), &ok);
+ if (!ok)
+ return;
+ bs = fromHex(s.toStdString());
+ }
+
KeyPair p;
- while (!beginsWith(p.address(), asBytes(s.toStdString())))
- p = KeyPair::create();
+ bool keepGoing = true;
+ unsigned done = 0;
+ function f = [&]() {
+ KeyPair lp;
+ while (keepGoing)
+ {
+ done++;
+ if (done % 1000 == 0)
+ cnote << "Tried" << done << "keys";
+ lp = KeyPair::create();
+ auto a = lp.address();
+ if (v == NoVanity ||
+ (v == FirstTwo && a[0] == a[1]) ||
+ (v == FirstTwoNextTwo && a[0] == a[1] && a[2] == a[3]) ||
+ (v == FirstThree && a[0] == a[1] && a[1] == a[2]) ||
+ (v == FirstFour && a[0] == a[1] && a[1] == a[2] && a[2] == a[3]) ||
+ (v == StringMatch && beginsWith(lp.address(), bs))
+ )
+ break;
+ }
+ if (keepGoing)
+ p = lp;
+ keepGoing = false;
+ };
+ vector ts;
+ for (unsigned t = 0; t < std::thread::hardware_concurrency() - 1; ++t)
+ ts.push_back(new std::thread(f));
+ f();
+ for (std::thread* t: ts)
+ {
+ t->join();
+ delete t;
+ }
m_myKeys.append(p);
keysChanged();
}
+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)
+ return;
+ m_myKeys.erase(m_myKeys.begin() + ui->ourAccounts->currentRow());
+ keysChanged();
+ }
+}
+
void Main::on_debugStep_triggered()
{
if (ui->debugTimeline->value() < m_history.size()) {
@@ -2356,10 +2414,10 @@ void Main::refreshWhispers()
shh::Envelope const& e = w.second;
shh::Message m;
for (pair const& i: m_server->ids())
- if (!!(m = e.open(i.second)))
+ if (!!(m = e.open(shh::FullTopic(), i.second)))
break;
if (!m)
- m = e.open();
+ m = e.open(shh::FullTopic());
QString msg;
if (m.from())
@@ -2372,7 +2430,7 @@ void Main::refreshWhispers()
time_t ex = e.expiry();
QString t(ctime(&ex));
t.chop(1);
- QString item = QString("[%1 - %2s] *%3 %5 %4").arg(t).arg(e.ttl()).arg(e.workProved()).arg(toString(e.topics()).c_str()).arg(msg);
+ QString item = QString("[%1 - %2s] *%3 %5 %4").arg(t).arg(e.ttl()).arg(e.workProved()).arg(toString(e.topic()).c_str()).arg(msg);
ui->whispers->addItem(item);
}
}
diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h
index bcfa8a0fc..b5639fc68 100644
--- a/alethzero/MainWin.h
+++ b/alethzero/MainWin.h
@@ -71,6 +71,8 @@ struct WorldState
using WatchHandler = std::function;
+QString contentsOfQResource(std::string const& res);
+
class Main : public QMainWindow
{
Q_OBJECT
@@ -87,6 +89,8 @@ public:
std::string lookupNatSpecUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionData);
QList owned() const { return m_myIdentities + m_myKeys; }
+
+ QVariant evalRaw(QString const& _js);
public slots:
void load(QString _file);
@@ -104,6 +108,7 @@ private slots:
void on_mine_triggered();
void on_send_clicked();
void on_create_triggered();
+ void on_killAccount_triggered();
void on_net_triggered();
void on_verbosity_valueChanged();
void on_ourAccounts_doubleClicked();
diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp
index ce1f28507..37d37bce1 100644
--- a/alethzero/OurWebThreeStubServer.cpp
+++ b/alethzero/OurWebThreeStubServer.cpp
@@ -24,25 +24,26 @@
#include
#include
#include
+
#include "MainWin.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
-OurWebThreeStubServer::OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3,
- std::vector const& _accounts, Main* main):
+OurWebThreeStubServer::OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, WebThreeDirect& _web3,
+ vector const& _accounts, Main* main):
WebThreeStubServer(_conn, _web3, _accounts), m_web3(&_web3), m_main(main)
{}
-std::string OurWebThreeStubServer::shh_newIdentity()
+string OurWebThreeStubServer::shh_newIdentity()
{
- dev::KeyPair kp = dev::KeyPair::create();
+ KeyPair kp = dev::KeyPair::create();
emit onNewId(QString::fromStdString(toJS(kp.sec())));
return toJS(kp.pub());
}
-bool OurWebThreeStubServer::showAuthenticationPopup(std::string const& _title, std::string const& _text) const
+bool OurWebThreeStubServer::showAuthenticationPopup(string const& _title, string const& _text) const
{
QMessageBox userInput;
userInput.setText(QString::fromStdString(_title));
@@ -54,19 +55,65 @@ bool OurWebThreeStubServer::showAuthenticationPopup(std::string const& _title, s
return userInput.exec() == QMessageBox::Ok;
}
-bool OurWebThreeStubServer::authenticate(dev::TransactionSkeleton const& _t) const
+void OurWebThreeStubServer::showBasicValueTransferNotice(u256 _value) const
+{
+ QMessageBox notice;
+ notice.setText("Basic Value Transfer Transaction");
+ notice.setInformativeText(QString::fromStdString("Value is " + toString(_value)));
+ notice.setStandardButtons(QMessageBox::Ok);
+ notice.exec();
+}
+
+bool OurWebThreeStubServer::authenticate(TransactionSkeleton const& _t)
{
h256 contractCodeHash = m_web3->ethereum()->postState().codeHash(_t.to);
if (contractCodeHash == EmptySHA3)
- // recipient has no code - nothing special about this transaction.
- // TODO: show basic message for value transfer.
+ // contract creation
+ return true;
+
+ if (false) //TODO: When is is just a value transfer?
+ {
+ // recipient has no code - nothing special about this transaction, show basic value transfer info
+ showBasicValueTransferNotice(_t.value);
return true;
+ }
+
+ string userNotice = m_main->lookupNatSpecUserNotice(contractCodeHash, _t.data);
- std::string userNotice = m_main->lookupNatSpecUserNotice(contractCodeHash, _t.data);
if (userNotice.empty())
return showAuthenticationPopup("Unverified Pending Transaction",
"An undocumented transaction is about to be executed.");
+ QNatspecExpressionEvaluator evaluator(this, m_main);
+ userNotice = evaluator.evalExpression(QString::fromStdString(userNotice)).toStdString();
+
// otherwise it's a transaction to a contract for which we have the natspec
return showAuthenticationPopup("Pending Transaction", userNotice);
}
+
+QNatspecExpressionEvaluator::QNatspecExpressionEvaluator(OurWebThreeStubServer* _server, Main* _main)
+: m_server(_server), m_main(_main)
+{}
+
+QNatspecExpressionEvaluator::~QNatspecExpressionEvaluator()
+{}
+
+QString QNatspecExpressionEvaluator::evalExpression(QString const& _expression) const
+{
+ // load natspec.js only when we need it for natspec evaluation
+ m_main->evalRaw(contentsOfQResource(":/js/natspec.js"));
+ QVariant result = m_main->evalRaw("evaluateExpression('" + _expression + "')");
+ if (result.type() == QVariant::Invalid)
+ {
+ cerr << "Could not evaluate natspec expression: \"" << _expression.toStdString() << "\"" << endl;
+ // return the expression unevaluated
+ return _expression;
+ }
+ return result.toString();
+}
+
+
+
+
+
+
diff --git a/alethzero/OurWebThreeStubServer.h b/alethzero/OurWebThreeStubServer.h
index a67af0827..5223d79bd 100644
--- a/alethzero/OurWebThreeStubServer.h
+++ b/alethzero/OurWebThreeStubServer.h
@@ -35,14 +35,31 @@ public:
std::vector const& _accounts, Main* main);
virtual std::string shh_newIdentity() override;
- virtual bool authenticate(dev::TransactionSkeleton const& _t) const;
+ virtual bool authenticate(dev::TransactionSkeleton const& _t);
signals:
void onNewId(QString _s);
private:
bool showAuthenticationPopup(std::string const& _title, std::string const& _text) const;
+ void showBasicValueTransferNotice(dev::u256 _value) const;
dev::WebThreeDirect* m_web3;
Main* m_main;
};
+
+
+class QNatspecExpressionEvaluator: public QObject
+{
+ Q_OBJECT
+
+public:
+ QNatspecExpressionEvaluator(OurWebThreeStubServer* _server, Main* _main);
+ virtual ~QNatspecExpressionEvaluator();
+
+ QString evalExpression(QString const& _expression) const;
+
+private:
+ OurWebThreeStubServer* m_server;
+ Main* m_main;
+};
diff --git a/eth/main.cpp b/eth/main.cpp
index 515197ddc..7a128298a 100644
--- a/eth/main.cpp
+++ b/eth/main.cpp
@@ -39,7 +39,7 @@
#endif
#if ETH_JSONRPC
#include
-#include
+#include
#endif
#include "BuildInfo.h"
using namespace std;
diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp
index 1d00fd225..531ad5526 100644
--- a/evmjit/libevmjit/Compiler.cpp
+++ b/evmjit/libevmjit/Compiler.cpp
@@ -450,13 +450,17 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
auto word = stack.pop();
auto k32_ = m_builder.CreateTrunc(idx, m_builder.getIntNTy(5), "k_32");
- auto k32 = m_builder.CreateZExt(k32_, Type::Word);
- auto k32x8 = m_builder.CreateMul(k32, Constant::get(8), "kx8");
+ auto k32 = m_builder.CreateZExt(k32_, Type::lowPrecision);
+ auto k32x8 = m_builder.CreateMul(k32, m_builder.getInt64(8), "kx8");
// test for word >> (k * 8 + 7)
- auto bitpos = m_builder.CreateAdd(k32x8, Constant::get(7), "bitpos");
- auto bitval = m_builder.CreateLShr(word, bitpos, "bitval");
- auto bittest = m_builder.CreateTrunc(bitval, Type::Bool, "bittest");
+ auto bitpos = m_builder.CreateAdd(k32x8, m_builder.getInt64(7), "bitpos");
+ auto bittester = m_builder.CreateShl(Constant::get(1), bitpos);
+ auto bitresult = m_builder.CreateAnd(word, bittester);
+ auto bittest = m_builder.CreateICmpUGT(bitresult, Constant::get(0));
+ // FIXME: The following does not work - LLVM bug, report!
+ //auto bitval = m_builder.CreateLShr(word, bitpos, "bitval");
+ //auto bittest = m_builder.CreateTrunc(bitval, Type::Bool, "bittest");
auto mask_ = m_builder.CreateShl(Constant::get(1), bitpos);
auto mask = m_builder.CreateSub(mask_, Constant::get(1), "mask");
diff --git a/libdevcore/Common.h b/libdevcore/Common.h
index 9fefea45a..9edeacccb 100644
--- a/libdevcore/Common.h
+++ b/libdevcore/Common.h
@@ -36,6 +36,7 @@
#include