From 809df5cdc593ec7613c766d67455df276c2f1bdc Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 15 Feb 2015 01:00:09 +0100 Subject: [PATCH] Working, albeit slowly, non-NatSpec transaction confirmations. --- alethzero/MainWin.cpp | 14 ++++- alethzero/MainWin.h | 14 +++-- alethzero/OurWebThreeStubServer.cpp | 70 +++++++++++++++-------- alethzero/OurWebThreeStubServer.h | 4 +- libethcore/CommonJS.h | 1 + libsolidity/CompilerStack.cpp | 5 ++ libsolidity/CompilerStack.h | 1 + libweb3jsonrpc/WebThreeStubServerBase.cpp | 2 + 8 files changed, 80 insertions(+), 31 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 865cfec3e..ec58fd559 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1733,7 +1733,7 @@ void Main::on_data_textChanged() // compiler.addSources(dev::solidity::StandardSources); m_data = compiler.compile(src, m_enableOptimizer); solidity = "

Solidity

"; - solidity += "
var " + QString::fromStdString(compiler.getContractNames().front()) + " = web3.eth.contractFromAbi(" + QString::fromStdString(compiler.getInterface()).replace(QRegExp("\\s"), "").toHtmlEscaped() + ");
"; + solidity += "
var " + QString::fromStdString(compiler.defaultContractName()) + " = web3.eth.contractFromAbi(" + QString::fromStdString(compiler.getInterface()).replace(QRegExp("\\s"), "").toHtmlEscaped() + ");
"; solidity += "
" + QString::fromStdString(compiler.getSolidityInterface()).toHtmlEscaped() + "
"; solidity += "
" + QString::fromStdString(getFunctionHashes(compiler)).toHtmlEscaped() + "
"; } @@ -2442,6 +2442,18 @@ string Main::lookupNatSpecUserNotice(dev::h256 const& _contractHash, dev::bytes return m_natspecDB.getUserNotice(_contractHash, _transactionData); } +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::refreshWhispers() { ui->whispers->clear(); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 5298a28a2..fa451b63f 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -79,6 +79,12 @@ public: QVariant evalRaw(QString const& _js); + QString pretty(dev::Address _a) const override; + QString prettyU256(dev::u256 _n) const override; + QString render(dev::Address _a) const override; + dev::Address fromString(QString const& _a) const override; + std::string renderDiff(dev::eth::StateDiff const& _d) const override; + public slots: void load(QString _file); void note(QString _entry); @@ -86,6 +92,8 @@ public slots: void warn(QString _entry); QString contents(QString _file); + int authenticate(QString _title, QString _text); + void onKeysChanged(); private slots: @@ -175,12 +183,6 @@ private: void updateDebugger(); void debugFinished(); - QString pretty(dev::Address _a) const override; - QString prettyU256(dev::u256 _n) const override; - QString render(dev::Address _a) const override; - dev::Address fromString(QString const& _a) const override; - std::string renderDiff(dev::eth::StateDiff const& _d) const override; - void alterDebugStateGroup(bool _enable) const; void updateFee(); diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp index 02d7236df..89d616756 100644 --- a/alethzero/OurWebThreeStubServer.cpp +++ b/alethzero/OurWebThreeStubServer.cpp @@ -46,48 +46,72 @@ string OurWebThreeStubServer::shh_newIdentity() bool OurWebThreeStubServer::showAuthenticationPopup(string const& _title, string const& _text) const { - QMessageBox userInput; - userInput.setText(QString::fromStdString(_title)); - userInput.setInformativeText(QString::fromStdString(_text + "\n Do you wish to allow this?")); - 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() == QMessageBox::Ok; + int button; + QMetaObject::invokeMethod(m_main, "authenticate", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, button), Q_ARG(QString, QString::fromStdString(_title)), Q_ARG(QString, QString::fromStdString(_text))); + return button == QMessageBox::Ok; } -void OurWebThreeStubServer::showBasicValueTransferNotice(u256 _value) const +bool OurWebThreeStubServer::showCreationNotice(TransactionSkeleton const& _t) const { - QMessageBox notice; - notice.setText("Basic Value Transfer Transaction"); - notice.setInformativeText(QString::fromStdString("Value is " + toString(_value))); - notice.setStandardButtons(QMessageBox::Ok); - notice.exec(); + return showAuthenticationPopup("Contract Creation Transaction", "ÐApp is attemping to create a contract; to be endowed with " + formatBalance(_t.value) + ", with additional network fees of up to " + formatBalance(_t.gas * _t.gasPrice) + ".\n\nMaximum total cost is " + formatBalance(_t.value + _t.gas * _t.gasPrice) + "."); +} + +bool OurWebThreeStubServer::showSendNotice(TransactionSkeleton const& _t) const +{ + return showAuthenticationPopup("Fund Transfer Transaction", "ÐApp is attempting to send " + formatBalance(_t.value) + " to a recipient " + m_main->pretty(_t.to).toStdString() + ", with additional network fees of up to " + formatBalance(_t.gas * _t.gasPrice) + ".\n\nMaximum total cost is " + formatBalance(_t.value + _t.gas * _t.gasPrice) + "."); +} + +bool OurWebThreeStubServer::showUnknownCallNotice(TransactionSkeleton const& _t) const +{ + return showAuthenticationPopup("DANGEROUS! Unknown Contract Transaction!", + "ÐApp is attempting to call into an unknown contract at address " + + m_main->pretty(_t.to).toStdString() + + ".\n\nCall involves sending " + + formatBalance(_t.value) + " to the recipient, with additional network fees of up to " + + formatBalance(_t.gas * _t.gasPrice) + + "However, this also does other stuff which we don't understand, and does so in your name.\n\n" + + "WARNING: This is probably going to cost you at least " + + formatBalance(_t.value + _t.gas * _t.gasPrice) + + ", however this doesn't include any side-effects, which could be of far greater importance.\n\n" + + "REJECT UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!"); } bool OurWebThreeStubServer::authenticate(TransactionSkeleton const& _t) { + if (_t.creation) + { + // recipient has no code - nothing special about this transaction, show basic value transfer info + return showCreationNotice(_t); + } + h256 contractCodeHash = m_web3->ethereum()->postState().codeHash(_t.to); if (contractCodeHash == EmptySHA3) - // 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; + return showSendNotice(_t); } + // TODO: include total cost in Ether string userNotice = m_main->lookupNatSpecUserNotice(contractCodeHash, _t.data); if (userNotice.empty()) - return showAuthenticationPopup("Unverified Pending Transaction", - "An undocumented transaction is about to be executed."); + return showUnknownCallNotice(_t); NatspecExpressionEvaluator evaluator; 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); + return showAuthenticationPopup("Contract Transaction", + "ÐApp attempting to conduct contract interaction with " + + m_main->pretty(_t.to).toStdString() + + ": " + userNotice + ".\n\n" + + (_t.value > 0 ? + "In addition, ÐApp is attempting to send " + + formatBalance(_t.value) + " to said recipient, with additional network fees of up to " + + formatBalance(_t.gas * _t.gasPrice) + " = " + + formatBalance(_t.value + _t.gas * _t.gasPrice) + "." + : + "Additional network fees are at most" + + formatBalance(_t.gas * _t.gasPrice) + ".") + ); } diff --git a/alethzero/OurWebThreeStubServer.h b/alethzero/OurWebThreeStubServer.h index 303b73111..fbdae7d03 100644 --- a/alethzero/OurWebThreeStubServer.h +++ b/alethzero/OurWebThreeStubServer.h @@ -42,7 +42,9 @@ signals: private: bool showAuthenticationPopup(std::string const& _title, std::string const& _text) const; - void showBasicValueTransferNotice(dev::u256 _value) const; + bool showCreationNotice(dev::eth::TransactionSkeleton const& _t) const; + bool showSendNotice(dev::eth::TransactionSkeleton const& _t) const; + bool showUnknownCallNotice(dev::eth::TransactionSkeleton const& _t) const; dev::WebThreeDirect* m_web3; Main* m_main; diff --git a/libethcore/CommonJS.h b/libethcore/CommonJS.h index 2f82d8945..abe74f0af 100644 --- a/libethcore/CommonJS.h +++ b/libethcore/CommonJS.h @@ -144,6 +144,7 @@ inline Address jsToAddress(std::string const& _s) { return jsToFixedgetName(); +} + CompilerStack::Contract const& CompilerStack::getContract(string const& _contractName) const { if (m_contracts.empty()) diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h index 439077f36..cb4770cd3 100644 --- a/libsolidity/CompilerStack.h +++ b/libsolidity/CompilerStack.h @@ -73,6 +73,7 @@ public: void parse(std::string const& _sourceCode); /// Returns a list of the contract names in the sources. std::vector getContractNames() const; + std::string defaultContractName() const; /// Compiles the source units that were previously added and parsed. void compile(bool _optimize = false); diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 49094a423..27b8268da 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -279,6 +279,8 @@ static TransactionSkeleton toTransaction(Json::Value const& _json) ret.from = jsToAddress(_json["from"].asString()); if (_json["to"].isString()) ret.to = jsToAddress(_json["to"].asString()); + else + ret.creation = true; if (!_json["value"].empty()) { if (_json["value"].isString())