diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 01b112b50..b05bcf1cc 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -158,7 +158,7 @@ Main::Main(QWidget *parent) : m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/AlethZero", false, {"eth", "shh"})); m_qwebConnector.reset(new QWebThreeConnector()); - m_server.reset(new OurWebThreeStubServer(*m_qwebConnector, *web3(), keysAsVector(m_myKeys))); + m_server.reset(new OurWebThreeStubServer(*m_qwebConnector, *web3(), keysAsVector(m_myKeys), this)); connect(&*m_server, SIGNAL(onNewId(QString)), SLOT(addNewId(QString))); m_server->setIdentities(keysAsVector(owned())); m_server->StartListening(); @@ -1872,7 +1872,30 @@ void Main::on_send_clicked() debugFinished(); Secret s = i.secret(); if (isCreation()) + { ethereum()->transact(s, value(), m_data, ui->gas->value(), gasPrice()); + + // LTODO: work in progress, recompile contract and get the hash of the code + // Also .. yeah improve the heuristic for Solidity and abstract to a function + string src = ui->data->toPlainText().toStdString(); + if (src.substr(0, 8) == "contract" || src.substr(0, 2) == "/*") // improve this heuristic + { + + dev::solidity::CompilerStack compiler; + try + { + m_data = compiler.compile(src, m_enableOptimizer); + for (std::string& s: compiler.getContractNames()) + m_natspecDB.add(compiler.getContractCodeHash(s), + compiler.getMetadata(s, dev::solidity::DocumentationType::NATSPEC_USER)); + + } + catch (...) + { + statusBar()->showMessage("Couldn't make transaction: no single account contains at least the required amount."); + } + } + } else ethereum()->transact(s, value(), fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice()); return; @@ -2257,6 +2280,11 @@ void Main::on_post_clicked() whisper()->inject(m.seal(from, topicFromText(ui->shhTopic->toPlainText()), ui->shhTtl->value(), ui->shhWork->value())); } +std::string Main::lookupNatSpec(dev::h256 const& _contractHash) const +{ + return m_natspecDB.retrieve(_contractHash); +} + void Main::refreshWhispers() { ui->whispers->clear(); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 52a71102d..e20aac27d 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -37,6 +37,8 @@ #include #include +#include "NatspecHandler.h" + namespace Ui { class Main; } @@ -80,7 +82,7 @@ public: dev::eth::Client* ethereum() const { return m_webThree->ethereum(); } std::shared_ptr whisper() const { return m_webThree->whisper(); } - std::string lookupNatSpec(dev::h256 const& _contractCode) const { (void)_contractCode; return ""; } // TODO: actually implement with leveldb & a UI. + std::string lookupNatSpec(dev::h256 const& _contractHash) const; QList owned() const { return m_myIdentities + m_myKeys; } @@ -269,4 +271,5 @@ private: QWebThree* m_qweb = nullptr; static QString fromRaw(dev::h256 _n, unsigned* _inc = nullptr); + NatspecHandler m_natspecDB; }; diff --git a/alethzero/NatspecHandler.cpp b/alethzero/NatspecHandler.cpp new file mode 100644 index 000000000..ae58208f1 --- /dev/null +++ b/alethzero/NatspecHandler.cpp @@ -0,0 +1,58 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ + +/** @file NatspecHandler.h + * @author Lefteris Karapetsas + * @date 2015 + */ +#include "NatspecHandler.h" +#include +#include + +#include +#include + +using namespace dev; +using namespace dev::eth; + +NatspecHandler::NatspecHandler() +{ + std::string path = Defaults::dbPath(); + boost::filesystem::create_directories(path); + ldb::Options o; + o.create_if_missing = true; + ldb::DB::Open(o, path + "/natspec", &m_db); +} + + +void NatspecHandler::add(dev::h256 const& _contractHash, std::string const& _doc) +{ + bytes k = _contractHash.asBytes(); + std::string v = _doc; + m_db->Put(m_writeOptions, ldb::Slice((char const*)k.data(), k.size()), ldb::Slice((char const*)v.data(), v.size())); +} + +std::string NatspecHandler::retrieve(dev::h256 const& _contractHash) const +{ + bytes k = _contractHash.asBytes(); + std::string ret; + m_db->Get(m_readOptions, ldb::Slice((char const*)k.data(), k.size()), &ret); + return ret; +} + + + diff --git a/alethzero/NatspecHandler.h b/alethzero/NatspecHandler.h new file mode 100644 index 000000000..36554fc44 --- /dev/null +++ b/alethzero/NatspecHandler.h @@ -0,0 +1,45 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ + +/** @file NatspecHandler.h + * @author Lefteris Karapetsas + * @date 2015 + */ + +#pragma once + +#pragma warning(push) +#pragma warning(disable: 4100 4267) +#include +#pragma warning(pop) +#include + +namespace ldb = leveldb; + +class NatspecHandler +{ + public: + NatspecHandler(); + + void add(dev::h256 const& _contractHash, std::string const& _doc); + std::string retrieve(dev::h256 const& _contractHash) const; + + private: + ldb::ReadOptions m_readOptions; + ldb::WriteOptions m_writeOptions; + ldb::DB* m_db; +}; diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp index 0d840e8d4..a156eeb1c 100644 --- a/alethzero/OurWebThreeStubServer.cpp +++ b/alethzero/OurWebThreeStubServer.cpp @@ -24,12 +24,14 @@ #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): - WebThreeStubServer(_conn, _web3, _accounts), m_web3(&_web3) +OurWebThreeStubServer::OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, + std::vector const& _accounts, Main* main): + WebThreeStubServer(_conn, _web3, _accounts), m_web3(&_web3), m_main(main) {} std::string OurWebThreeStubServer::shh_newIdentity() @@ -41,13 +43,11 @@ std::string OurWebThreeStubServer::shh_newIdentity() bool OurWebThreeStubServer::authenticate(dev::TransactionSkeleton const& _t) const { - return true; + // return true; // To get the balance of the sender cnote << "Sender has ETH: " << m_web3->ethereum()->postState().balance(_t.from); - Main* main; // don't know this yet, should be a member and set at construction time by Main, who will construct us. - h256 contractCodeHash = m_web3->ethereum()->postState().codeHash(_t.to); if (contractCodeHash == EmptySHA3) @@ -57,7 +57,7 @@ bool OurWebThreeStubServer::authenticate(dev::TransactionSkeleton const& _t) con return true; // or whatever. } - std::string natspecJson = main->lookupNatSpec(contractCodeHash); + std::string natspecJson = m_main->lookupNatSpec(contractCodeHash); if (natspecJson.empty()) { diff --git a/alethzero/OurWebThreeStubServer.h b/alethzero/OurWebThreeStubServer.h index 9ff973371..506a77884 100644 --- a/alethzero/OurWebThreeStubServer.h +++ b/alethzero/OurWebThreeStubServer.h @@ -24,12 +24,15 @@ #include #include +class Main; + class OurWebThreeStubServer: public QObject, public WebThreeStubServer { Q_OBJECT public: - OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, std::vector const& _accounts); + OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, + std::vector const& _accounts, Main* main); virtual std::string shh_newIdentity() override; virtual bool authenticate(dev::TransactionSkeleton const& _t) const; @@ -39,4 +42,5 @@ signals: private: dev::WebThreeDirect* m_web3; + Main* m_main; }; diff --git a/libethereum/Defaults.h b/libethereum/Defaults.h index 91d5872f7..3b19166b1 100644 --- a/libethereum/Defaults.h +++ b/libethereum/Defaults.h @@ -23,6 +23,7 @@ #include + namespace dev { namespace eth diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index 174f9cd22..547e5fe21 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -200,6 +200,13 @@ bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimiz return stack.compile(_sourceCode, _optimize); } +dev::h256 CompilerStack::getContractCodeHash(std::string const& _contractName) +{ + //LTODO + (void) _contractName; + return dev::h256(""); +} + void CompilerStack::reset(bool _keepSources) { m_parseSuccessful = false; diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h index afc9a5162..6b60f1dd3 100644 --- a/libsolidity/CompilerStack.h +++ b/libsolidity/CompilerStack.h @@ -28,6 +28,7 @@ #include #include #include +#include namespace dev { namespace solidity { @@ -104,6 +105,9 @@ public: /// scanning the source code - this is useful for printing exception information. static bytes staticCompile(std::string const& _sourceCode, bool _optimize = false); + /// Get the runtime context's code hash for a contract. LTODO + dev::h256 getContractCodeHash(std::string const& _contractName); + private: /** * Information pertaining to one source unit, filled gradually during parsing and compilation.