diff --git a/abi/main.cpp b/abi/main.cpp index 27c5eea1b..df7fa8811 100644 --- a/abi/main.cpp +++ b/abi/main.cpp @@ -26,7 +26,7 @@ #include "../test/JsonSpiritHeaders.h" #include #include -#include +#include #include using namespace std; using namespace dev; diff --git a/alethzero/DappLoader.cpp b/alethzero/DappLoader.cpp index a91beb2f7..b2249ae5b 100644 --- a/alethzero/DappLoader.cpp +++ b/alethzero/DappLoader.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp index 009e2dc83..210649edb 100644 --- a/alethzero/DownloadView.cpp +++ b/alethzero/DownloadView.cpp @@ -52,7 +52,10 @@ void DownloadView::paintEvent(QPaintEvent*) QPointF pos(0, 0); auto bg = m_man->blocksGot(); - + unsigned subCount = m_man->subCount(); + if (subCount == 0) + return; + unsigned dh = 360 / subCount; for (unsigned i = bg.all().first, ei = bg.all().second; i < ei; ++i) { int s = -2; @@ -68,7 +71,6 @@ void DownloadView::paintEvent(QPaintEvent*) h++; }); } - unsigned dh = 360 / m_man->subCount(); if (s == -2) p.fillRect(QRectF(QPointF(pos) + QPointF(3 * area.width() / 8, 3 * area.height() / 8), area / 4), Qt::black); else if (s == -1) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 9486f9f01..07f48c0bc 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -44,7 +44,7 @@ #include #include #endif -#include +#include #include #include #include @@ -1166,10 +1166,10 @@ void Main::on_turboMining_triggered() void Main::refreshBlockChain() { - if (!ui->blocks->isVisible()) + if (!ui->blocks->isVisible() && isVisible()) return; - DEV_TIMED_FUNCTION; + DEV_TIMED_FUNCTION_ABOVE(500); cwatch << "refreshBlockChain()"; // TODO: keep the same thing highlighted. @@ -1353,7 +1353,7 @@ void Main::timerEvent(QTimerEvent*) auto ls = ethereum()->checkWatchSafe(i.first); if (ls.size()) { - cnote << "FIRING WATCH" << i.first << ls.size(); +// cnote << "FIRING WATCH" << i.first << ls.size(); i.second(ls); } } diff --git a/alethzero/NatspecHandler.cpp b/alethzero/NatspecHandler.cpp index a7cad6853..d00abc44f 100644 --- a/alethzero/NatspecHandler.cpp +++ b/alethzero/NatspecHandler.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include using namespace dev; diff --git a/eth/main.cpp b/eth/main.cpp index 1cf918346..33d049843 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include #include diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 040bd945c..ef0621b7f 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -31,11 +31,11 @@ #include #include -#include +#include #include #include #include -#include +#include #include #include #include @@ -174,6 +174,10 @@ public: m_minerType = MinerType::GPU; miningThreads = 1; } + else if (arg == "--no-precompute") + { + precompute = false; + } else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) { string m = boost::to_lower_copy(string(argv[++i])); @@ -268,6 +272,7 @@ public: << "Work farming mode:" << endl << " -F,--farm Put into mining farm mode with the work server at URL (default: http://127.0.0.1:8545)" << endl << " --farm-recheck Leave n ms between checks for changed work (default: 500)." << endl + << " --no-precompute Don't precompute the next epoch's DAG." << endl #endif << "Ethash verify mode:" << endl << " -w,--check-pow Check PoW credentials for validity." << endl @@ -388,7 +393,7 @@ private: (void)_m; (void)_remote; (void)_recheckPeriod; - #if ETH_JSONRPC || !ETH_TRUE +#if ETH_JSONRPC || !ETH_TRUE jsonrpc::HttpClient client(_remote); Farm rpc(client); @@ -399,7 +404,7 @@ private: f.startGPU(); ProofOfWork::WorkPackage current; - EthashAux::FullType dag; + EthashAux::FullType dag; while (true) try { @@ -418,9 +423,13 @@ private: cnote << "Getting work package..."; Json::Value v = rpc.eth_getWork(); h256 hh(v[0].asString()); - h256 newSeedHash(v[1].asString()); - if (!(dag = EthashAux::full(newSeedHash, true))) - BOOST_THROW_EXCEPTION(DAGCreationFailure()); + h256 newSeedHash(v[1].asString()); + if (current.seedHash != newSeedHash) + cnote << "Grabbing DAG for" << newSeedHash; + if (!(dag = EthashAux::full(newSeedHash, true, [&](unsigned _pc){ cout << "\rCreating DAG. " << _pc << "% done..." << flush; return 0; }))) + BOOST_THROW_EXCEPTION(DAGCreationFailure()); + if (precompute) + EthashAux::computeFull(sha3(newSeedHash), true); if (hh != current.headerHash) { current.headerHash = hh; @@ -459,7 +468,7 @@ private: cerr << "JSON-RPC problem. Probably couldn't connect. Retrying in " << i << "... \r"; cerr << endl; } - #endif +#endif exit(0); } @@ -484,5 +493,5 @@ private: /// Farm params string farmURL = "http://127.0.0.1:8545"; unsigned farmRecheckPeriod = 500; - + bool precompute = true; }; diff --git a/ethminer/main.cpp b/ethminer/main.cpp index 5b82db471..4deba38d1 100644 --- a/ethminer/main.cpp +++ b/ethminer/main.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include "MinerAux.h" using namespace std; using namespace dev; diff --git a/evmjit/libevmjit-cpp/Env.cpp b/evmjit/libevmjit-cpp/Env.cpp index a5a60f48c..d1f239f9f 100644 --- a/evmjit/libevmjit-cpp/Env.cpp +++ b/evmjit/libevmjit-cpp/Env.cpp @@ -1,6 +1,6 @@ #pragma GCC diagnostic ignored "-Wconversion" -#include +#include #include #include #include diff --git a/evmjit/libevmjit-cpp/JitVM.cpp b/evmjit/libevmjit-cpp/JitVM.cpp index 7acbec5c1..6efd4c31a 100644 --- a/evmjit/libevmjit-cpp/JitVM.cpp +++ b/evmjit/libevmjit-cpp/JitVM.cpp @@ -4,7 +4,7 @@ #include "JitVM.h" #include -#include +#include #include #include #include diff --git a/exp/main.cpp b/exp/main.cpp index 138ae76a4..47efe576a 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -34,6 +34,9 @@ #include #include #include +#include +#include +/* #include #include #include @@ -41,12 +44,11 @@ #include #include #include -#include #include #include #include #include -#include +#include #include #include #include @@ -55,17 +57,43 @@ #include #include #include -#include +#include */ using namespace std; using namespace dev; -using namespace dev::eth; +/*using namespace dev::eth; using namespace dev::p2p; using namespace dev::shh; namespace js = json_spirit; namespace fs = boost::filesystem; - +*/ #if 1 +int main() +{ + cdebug << "EXP"; + vector data; + for (unsigned i = 0; i < 10000; ++i) + data.push_back(rlp(i)); + + h256 ret; + DEV_TIMED(triedb) + { + MemoryDB mdb; + GenericTrieDB t(&mdb); + t.init(); + unsigned i = 0; + for (auto const& d: data) + t.insert(rlp(i++), d); + ret = t.root(); + } + cdebug << ret; + DEV_TIMED(hash256) + ret = orderedTrieRoot(data); + cdebug << ret; +} + +#elif 0 + int main() { KeyManager keyman; diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 95817e41c..ac4d89103 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -86,8 +86,9 @@ extern const u256 UndefinedU256; // Map types. using StringMap = std::map; +using BytesMap = std::map; using u256Map = std::map; -using HexMap = std::map; +using HexMap = std::map; // Hash types. using StringHashMap = std::unordered_map; @@ -200,7 +201,7 @@ private: #endif #define DEV_TIMED_ABOVE(S, MS) for (::std::pair<::dev::TimerHelper, bool> __eth_t(::dev::TimerHelper(#S, MS), true); __eth_t.second; __eth_t.second = false) -#define DEV_TIMED_SCOPE_ABOVE(S) ::dev::TimerHelper __eth_t(S, MS) +#define DEV_TIMED_SCOPE_ABOVE(S, MS) ::dev::TimerHelper __eth_t(S, MS) #if WIN32 #define DEV_TIMED_FUNCTION_ABOVE(MS) DEV_TIMED_SCOPE_ABOVE(__FUNCSIG__, MS) #else diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index 6cad29952..f8d8c172f 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -115,7 +115,7 @@ bytes dev::fromHex(std::string const& _s, WhenError _throw) return ret; } -bytes dev::asNibbles(std::string const& _s) +bytes dev::asNibbles(bytesConstRef const& _s) { std::vector ret; ret.reserve(_s.size() * 2); diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h index 6c1f34667..702f1f808 100644 --- a/libdevcore/CommonData.h +++ b/libdevcore/CommonData.h @@ -95,7 +95,7 @@ inline bytes asBytes(std::string const& _b) /// Converts a string into the big-endian base-16 stream of integers (NOT ASCII). /// @example asNibbles("A")[0] == 4 && asNibbles("A")[1] == 1 -bytes asNibbles(std::string const& _s); +bytes asNibbles(bytesConstRef const& _s); // Big-endian to/from host endian conversion functions. diff --git a/libdevcrypto/FileSystem.cpp b/libdevcore/FileSystem.cpp similarity index 97% rename from libdevcrypto/FileSystem.cpp rename to libdevcore/FileSystem.cpp index adf3a2946..dfda891f5 100644 --- a/libdevcrypto/FileSystem.cpp +++ b/libdevcore/FileSystem.cpp @@ -22,8 +22,8 @@ */ #include "FileSystem.h" -#include -#include +#include "Common.h" +#include "Log.h" #if defined(_WIN32) #include diff --git a/libdevcrypto/FileSystem.h b/libdevcore/FileSystem.h similarity index 100% rename from libdevcrypto/FileSystem.h rename to libdevcore/FileSystem.h diff --git a/libdevcore/Hash.cpp b/libdevcore/Hash.cpp new file mode 100644 index 000000000..c6b917b90 --- /dev/null +++ b/libdevcore/Hash.cpp @@ -0,0 +1,440 @@ +/* + 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 Hash.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "Hash.h" +#include +#include +#include +#include "picosha2.h" +using namespace std; +using namespace dev; + +namespace dev +{ + +h256 sha256(bytesConstRef _input) +{ + h256 ret; + picosha2::hash256(_input.begin(), _input.end(), ret.data(), ret.data() + 32); + return ret; +} + +namespace rmd160 +{ + +/********************************************************************\ + * + * FILE: rmd160.h + * FILE: rmd160.c + * + * CONTENTS: Header file for a sample C-implementation of the + * RIPEMD-160 hash-function. + * TARGET: any computer with an ANSI C compiler + * + * AUTHOR: Antoon Bosselaers, ESAT-COSIC + * DATE: 1 March 1996 + * VERSION: 1.0 + * + * Copyright (c) Katholieke Universiteit Leuven + * 1996, All Rights Reserved + * + \********************************************************************/ + +// Adapted into "header-only" format by Gav Wood. + +/* macro definitions */ + +#define RMDsize 160 + +/* collect four bytes into one word: */ +#define BYTES_TO_DWORD(strptr) \ +(((uint32_t) *((strptr)+3) << 24) | \ +((uint32_t) *((strptr)+2) << 16) | \ +((uint32_t) *((strptr)+1) << 8) | \ +((uint32_t) *(strptr))) + +/* ROL(x, n) cyclically rotates x over n bits to the left */ +/* x must be of an unsigned 32 bits type and 0 <= n < 32. */ +#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* the five basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define J(x, y, z) ((x) ^ ((y) | ~(z))) + +/* the ten basic operations FF() through III() */ +#define FF(a, b, c, d, e, x, s) {\ +(a) += F((b), (c), (d)) + (x);\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define GG(a, b, c, d, e, x, s) {\ +(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define HH(a, b, c, d, e, x, s) {\ +(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define II(a, b, c, d, e, x, s) {\ +(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define JJ(a, b, c, d, e, x, s) {\ +(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define FFF(a, b, c, d, e, x, s) {\ +(a) += F((b), (c), (d)) + (x);\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define GGG(a, b, c, d, e, x, s) {\ +(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define HHH(a, b, c, d, e, x, s) {\ +(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define III(a, b, c, d, e, x, s) {\ +(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define JJJ(a, b, c, d, e, x, s) {\ +(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} + +void MDinit(uint32_t *MDbuf) +{ + MDbuf[0] = 0x67452301UL; + MDbuf[1] = 0xefcdab89UL; + MDbuf[2] = 0x98badcfeUL; + MDbuf[3] = 0x10325476UL; + MDbuf[4] = 0xc3d2e1f0UL; + + return; +} + +/********************************************************************/ + +void MDcompress(uint32_t *MDbuf, uint32_t *X) +{ + uint32_t aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2], + dd = MDbuf[3], ee = MDbuf[4]; + uint32_t aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2], + ddd = MDbuf[3], eee = MDbuf[4]; + + /* round 1 */ + FF(aa, bb, cc, dd, ee, X[ 0], 11); + FF(ee, aa, bb, cc, dd, X[ 1], 14); + FF(dd, ee, aa, bb, cc, X[ 2], 15); + FF(cc, dd, ee, aa, bb, X[ 3], 12); + FF(bb, cc, dd, ee, aa, X[ 4], 5); + FF(aa, bb, cc, dd, ee, X[ 5], 8); + FF(ee, aa, bb, cc, dd, X[ 6], 7); + FF(dd, ee, aa, bb, cc, X[ 7], 9); + FF(cc, dd, ee, aa, bb, X[ 8], 11); + FF(bb, cc, dd, ee, aa, X[ 9], 13); + FF(aa, bb, cc, dd, ee, X[10], 14); + FF(ee, aa, bb, cc, dd, X[11], 15); + FF(dd, ee, aa, bb, cc, X[12], 6); + FF(cc, dd, ee, aa, bb, X[13], 7); + FF(bb, cc, dd, ee, aa, X[14], 9); + FF(aa, bb, cc, dd, ee, X[15], 8); + + /* round 2 */ + GG(ee, aa, bb, cc, dd, X[ 7], 7); + GG(dd, ee, aa, bb, cc, X[ 4], 6); + GG(cc, dd, ee, aa, bb, X[13], 8); + GG(bb, cc, dd, ee, aa, X[ 1], 13); + GG(aa, bb, cc, dd, ee, X[10], 11); + GG(ee, aa, bb, cc, dd, X[ 6], 9); + GG(dd, ee, aa, bb, cc, X[15], 7); + GG(cc, dd, ee, aa, bb, X[ 3], 15); + GG(bb, cc, dd, ee, aa, X[12], 7); + GG(aa, bb, cc, dd, ee, X[ 0], 12); + GG(ee, aa, bb, cc, dd, X[ 9], 15); + GG(dd, ee, aa, bb, cc, X[ 5], 9); + GG(cc, dd, ee, aa, bb, X[ 2], 11); + GG(bb, cc, dd, ee, aa, X[14], 7); + GG(aa, bb, cc, dd, ee, X[11], 13); + GG(ee, aa, bb, cc, dd, X[ 8], 12); + + /* round 3 */ + HH(dd, ee, aa, bb, cc, X[ 3], 11); + HH(cc, dd, ee, aa, bb, X[10], 13); + HH(bb, cc, dd, ee, aa, X[14], 6); + HH(aa, bb, cc, dd, ee, X[ 4], 7); + HH(ee, aa, bb, cc, dd, X[ 9], 14); + HH(dd, ee, aa, bb, cc, X[15], 9); + HH(cc, dd, ee, aa, bb, X[ 8], 13); + HH(bb, cc, dd, ee, aa, X[ 1], 15); + HH(aa, bb, cc, dd, ee, X[ 2], 14); + HH(ee, aa, bb, cc, dd, X[ 7], 8); + HH(dd, ee, aa, bb, cc, X[ 0], 13); + HH(cc, dd, ee, aa, bb, X[ 6], 6); + HH(bb, cc, dd, ee, aa, X[13], 5); + HH(aa, bb, cc, dd, ee, X[11], 12); + HH(ee, aa, bb, cc, dd, X[ 5], 7); + HH(dd, ee, aa, bb, cc, X[12], 5); + + /* round 4 */ + II(cc, dd, ee, aa, bb, X[ 1], 11); + II(bb, cc, dd, ee, aa, X[ 9], 12); + II(aa, bb, cc, dd, ee, X[11], 14); + II(ee, aa, bb, cc, dd, X[10], 15); + II(dd, ee, aa, bb, cc, X[ 0], 14); + II(cc, dd, ee, aa, bb, X[ 8], 15); + II(bb, cc, dd, ee, aa, X[12], 9); + II(aa, bb, cc, dd, ee, X[ 4], 8); + II(ee, aa, bb, cc, dd, X[13], 9); + II(dd, ee, aa, bb, cc, X[ 3], 14); + II(cc, dd, ee, aa, bb, X[ 7], 5); + II(bb, cc, dd, ee, aa, X[15], 6); + II(aa, bb, cc, dd, ee, X[14], 8); + II(ee, aa, bb, cc, dd, X[ 5], 6); + II(dd, ee, aa, bb, cc, X[ 6], 5); + II(cc, dd, ee, aa, bb, X[ 2], 12); + + /* round 5 */ + JJ(bb, cc, dd, ee, aa, X[ 4], 9); + JJ(aa, bb, cc, dd, ee, X[ 0], 15); + JJ(ee, aa, bb, cc, dd, X[ 5], 5); + JJ(dd, ee, aa, bb, cc, X[ 9], 11); + JJ(cc, dd, ee, aa, bb, X[ 7], 6); + JJ(bb, cc, dd, ee, aa, X[12], 8); + JJ(aa, bb, cc, dd, ee, X[ 2], 13); + JJ(ee, aa, bb, cc, dd, X[10], 12); + JJ(dd, ee, aa, bb, cc, X[14], 5); + JJ(cc, dd, ee, aa, bb, X[ 1], 12); + JJ(bb, cc, dd, ee, aa, X[ 3], 13); + JJ(aa, bb, cc, dd, ee, X[ 8], 14); + JJ(ee, aa, bb, cc, dd, X[11], 11); + JJ(dd, ee, aa, bb, cc, X[ 6], 8); + JJ(cc, dd, ee, aa, bb, X[15], 5); + JJ(bb, cc, dd, ee, aa, X[13], 6); + + /* parallel round 1 */ + JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); + JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); + JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); + JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); + JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); + JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); + JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); + JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); + + /* parallel round 2 */ + III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); + III(ddd, eee, aaa, bbb, ccc, X[11], 13); + III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); + III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); + III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); + III(eee, aaa, bbb, ccc, ddd, X[13], 8); + III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); + III(ccc, ddd, eee, aaa, bbb, X[10], 11); + III(bbb, ccc, ddd, eee, aaa, X[14], 7); + III(aaa, bbb, ccc, ddd, eee, X[15], 7); + III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); + III(ddd, eee, aaa, bbb, ccc, X[12], 7); + III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); + III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); + III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); + III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); + + /* parallel round 3 */ + HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); + HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); + HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); + HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); + HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); + HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); + HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); + HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); + HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); + HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); + HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); + HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); + HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); + HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); + HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); + HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); + + /* parallel round 4 */ + GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); + GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); + GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); + GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); + GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); + GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); + GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); + GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); + GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); + GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); + GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); + GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); + GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); + GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); + GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); + GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); + + /* parallel round 5 */ + FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); + FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); + FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); + FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); + FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); + FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); + FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); + FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); + FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); + FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); + FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); + FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); + FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); + FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); + + /* combine results */ + ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */ + MDbuf[1] = MDbuf[2] + dd + eee; + MDbuf[2] = MDbuf[3] + ee + aaa; + MDbuf[3] = MDbuf[4] + aa + bbb; + MDbuf[4] = MDbuf[0] + bb + ccc; + MDbuf[0] = ddd; + + return; +} + +void MDfinish(uint32_t *MDbuf, byte const *strptr, uint32_t lswlen, uint32_t mswlen) +{ + unsigned int i; /* counter */ + uint32_t X[16]; /* message words */ + + memset(X, 0, 16*sizeof(uint32_t)); + + /* put bytes from strptr into X */ + for (i=0; i<(lswlen&63); i++) { + /* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */ + X[i>>2] ^= (uint32_t) *strptr++ << (8 * (i&3)); + } + + /* append the bit m_n == 1 */ + X[(lswlen>>2)&15] ^= (uint32_t)1 << (8*(lswlen&3) + 7); + + if ((lswlen & 63) > 55) { + /* length goes to next block */ + MDcompress(MDbuf, X); + memset(X, 0, 16*sizeof(uint32_t)); + } + + /* append length in bits*/ + X[14] = lswlen << 3; + X[15] = (lswlen >> 29) | (mswlen << 3); + MDcompress(MDbuf, X); + + return; +} + +#undef ROL +#undef F +#undef G +#undef H +#undef I +#undef J +#undef FF +#undef GG +#undef HH +#undef II +#undef JJ +#undef FFF +#undef GGG +#undef HHH +#undef III +#undef JJJ + +} + +/* + * @returns RMD(_input) + */ +h160 ripemd160(bytesConstRef _input) +{ + h160 hashcode; + uint32_t buffer[RMDsize / 32]; // contains (A, B, C, D(, E)) + uint32_t current[16]; // current 16-word chunk + + // initialize + rmd160::MDinit(buffer); + byte const* message = _input.data(); + uint32_t remaining = _input.size(); // # of bytes not yet processed + + // process message in 16x 4-byte chunks + for (; remaining >= 64; remaining -= 64) + { + for (unsigned i = 0; i < 16; i++) + { + current[i] = BYTES_TO_DWORD(message); + message += 4; + } + rmd160::MDcompress(buffer, current); + } + // length mod 64 bytes left + + // finish: + rmd160::MDfinish(buffer, message, _input.size(), 0); + + for (unsigned i = 0; i < RMDsize / 8; i += 4) + { + hashcode[i] = buffer[i >> 2]; // implicit cast to byte + hashcode[i + 1] = (buffer[i >> 2] >> 8); //extracts the 8 least + hashcode[i + 2] = (buffer[i >> 2] >> 16); // significant bits. + hashcode[i + 3] = (buffer[i >> 2] >> 24); + } + + return hashcode; +} + +#undef BYTES_TO_DWORD +#undef RMDsize + +} diff --git a/libdevcore/Hash.h b/libdevcore/Hash.h new file mode 100644 index 000000000..7c5fcd67a --- /dev/null +++ b/libdevcore/Hash.h @@ -0,0 +1,38 @@ +/* + 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 Hash.h + * @author Gav Wood + * @date 2014 + * + * The FixedHash fixed-size "hash" container type. + */ + +#pragma once + +#include +#include +#include +#include "SHA3.h" + +namespace dev +{ + +h256 sha256(bytesConstRef _input); + +h160 ripemd160(bytesConstRef _input); + +} diff --git a/libdevcrypto/MemoryDB.cpp b/libdevcore/MemoryDB.cpp similarity index 100% rename from libdevcrypto/MemoryDB.cpp rename to libdevcore/MemoryDB.cpp diff --git a/libdevcrypto/MemoryDB.h b/libdevcore/MemoryDB.h similarity index 100% rename from libdevcrypto/MemoryDB.h rename to libdevcore/MemoryDB.h diff --git a/libdevcore/SHA3.cpp b/libdevcore/SHA3.cpp new file mode 100644 index 000000000..880f23d6e --- /dev/null +++ b/libdevcore/SHA3.cpp @@ -0,0 +1,223 @@ +/* + 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 SHA3.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "SHA3.h" +#include +#include +#include +#include +#include +#include "picosha2.h" +using namespace std; +using namespace dev; + +namespace dev +{ + +h256 EmptySHA3 = sha3(bytesConstRef()); +h256 EmptyListSHA3 = sha3(rlpList()); + +namespace keccak +{ + +/** libkeccak-tiny + * + * A single-file implementation of SHA-3 and SHAKE. + * + * Implementor: David Leon Gil + * License: CC0, attribution kindly requested. Blame taken too, + * but not liability. + */ + +#define decshake(bits) \ + int shake##bits(uint8_t*, size_t, const uint8_t*, size_t); + +#define decsha3(bits) \ + int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t); + +decshake(128) +decshake(256) +decsha3(224) +decsha3(256) +decsha3(384) +decsha3(512) + +/******** The Keccak-f[1600] permutation ********/ + +/*** Constants. ***/ +static const uint8_t rho[24] = \ + { 1, 3, 6, 10, 15, 21, + 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, + 62, 18, 39, 61, 20, 44}; +static const uint8_t pi[24] = \ + {10, 7, 11, 17, 18, 3, + 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, + 20, 14, 22, 9, 6, 1}; +static const uint64_t RC[24] = \ + {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, + 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, + 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, + 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, + 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; + +/*** Helper macros to unroll the permutation. ***/ +#define rol(x, s) (((x) << s) | ((x) >> (64 - s))) +#define REPEAT6(e) e e e e e e +#define REPEAT24(e) REPEAT6(e e e e) +#define REPEAT5(e) e e e e e +#define FOR5(v, s, e) \ + v = 0; \ + REPEAT5(e; v += s;) + +/*** Keccak-f[1600] ***/ +static inline void keccakf(void* state) { + uint64_t* a = (uint64_t*)state; + uint64_t b[5] = {0}; + uint64_t t = 0; + uint8_t x, y; + + for (int i = 0; i < 24; i++) { + // Theta + FOR5(x, 1, + b[x] = 0; + FOR5(y, 5, + b[x] ^= a[x + y]; )) + FOR5(x, 1, + FOR5(y, 5, + a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) + // Rho and pi + t = a[1]; + x = 0; + REPEAT24(b[0] = a[pi[x]]; + a[pi[x]] = rol(t, rho[x]); + t = b[0]; + x++; ) + // Chi + FOR5(y, + 5, + FOR5(x, 1, + b[x] = a[y + x];) + FOR5(x, 1, + a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) + // Iota + a[0] ^= RC[i]; + } +} + +/******** The FIPS202-defined functions. ********/ + +/*** Some helper macros. ***/ + +#define _(S) do { S } while (0) +#define FOR(i, ST, L, S) \ + _(for (size_t i = 0; i < L; i += ST) { S; }) +#define mkapply_ds(NAME, S) \ + static inline void NAME(uint8_t* dst, \ + const uint8_t* src, \ + size_t len) { \ + FOR(i, 1, len, S); \ + } +#define mkapply_sd(NAME, S) \ + static inline void NAME(const uint8_t* src, \ + uint8_t* dst, \ + size_t len) { \ + FOR(i, 1, len, S); \ + } + +mkapply_ds(xorin, dst[i] ^= src[i]) // xorin +mkapply_sd(setout, dst[i] = src[i]) // setout + +#define P keccakf +#define Plen 200 + +// Fold P*F over the full blocks of an input. +#define foldP(I, L, F) \ + while (L >= rate) { \ + F(a, I, rate); \ + P(a); \ + I += rate; \ + L -= rate; \ + } + +/** The sponge-based hash construction. **/ +static inline int hash(uint8_t* out, size_t outlen, + const uint8_t* in, size_t inlen, + size_t rate, uint8_t delim) { + if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) { + return -1; + } + uint8_t a[Plen] = {0}; + // Absorb input. + foldP(in, inlen, xorin); + // Xor in the DS and pad frame. + a[inlen] ^= delim; + a[rate - 1] ^= 0x80; + // Xor in the last block. + xorin(a, in, inlen); + // Apply P + P(a); + // Squeeze output. + foldP(out, outlen, setout); + setout(a, out, outlen); + memset(a, 0, 200); + return 0; +} + +/*** Helper macros to define SHA3 and SHAKE instances. ***/ +#define defshake(bits) \ + int shake##bits(uint8_t* out, size_t outlen, \ + const uint8_t* in, size_t inlen) { \ + return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x1f); \ + } +#define defsha3(bits) \ + int sha3_##bits(uint8_t* out, size_t outlen, \ + const uint8_t* in, size_t inlen) { \ + if (outlen > (bits/8)) { \ + return -1; \ + } \ + return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \ + } + +/*** FIPS202 SHAKE VOFs ***/ +defshake(128) +defshake(256) + +/*** FIPS202 SHA3 FOFs ***/ +defsha3(224) +defsha3(256) +defsha3(384) +defsha3(512) + +} + +h256 sha3(bytesConstRef _input) +{ + // FIXME: What with unaligned memory? + h256 ret; + keccak::sha3_256(ret.data(), 32, _input.data(), _input.size()); +// keccak::keccak(ret.data(), 32, (uint64_t const*)_input.data(), _input.size()); + return ret; +} + +} diff --git a/libdevcrypto/SHA3.h b/libdevcore/SHA3.h similarity index 66% rename from libdevcrypto/SHA3.h rename to libdevcore/SHA3.h index 66b8efe11..c3ef524fe 100644 --- a/libdevcrypto/SHA3.h +++ b/libdevcore/SHA3.h @@ -32,46 +32,29 @@ namespace dev // SHA-3 convenience routines. -/// Calculate SHA3-256 hash of the given input and load it into the given output. -void sha3(bytesConstRef _input, bytesRef _output); - -/// Calculate SHA3-256 hash of the given input, possibly interpreting it as nibbles, and return the hash as a string filled with binary data. -std::string sha3(std::string const& _input, bool _isNibbles); - -/// Calculate SHA3-256 hash of the given input, returning as a byte array. -bytes sha3Bytes(bytesConstRef _input); - -/// Calculate SHA3-256 hash of the given input (presented as a binary string), returning as a byte array. -inline bytes sha3Bytes(std::string const& _input) { return sha3Bytes((std::string*)&_input); } - -/// Calculate SHA3-256 hash of the given input, returning as a byte array. -inline bytes sha3Bytes(bytes const& _input) { return sha3Bytes((bytes*)&_input); } - /// Calculate SHA3-256 hash of the given input, returning as a 256-bit hash. h256 sha3(bytesConstRef _input); +/// Calculate SHA3-256 hash of the given input and load it into the given output. +inline void sha3(bytesConstRef _input, bytesRef _output) { sha3(_input).ref().populate(_output); } + /// Calculate SHA3-256 hash of the given input, returning as a 256-bit hash. -inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef((bytes*)&_input)); } +inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef(&_input)); } /// Calculate SHA3-256 hash of the given input (presented as a binary-filled string), returning as a 256-bit hash. inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); } - -/// Calculate SHA3-256 MAC -void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output); /// Calculate SHA3-256 hash of the given input (presented as a FixedHash), returns a 256-bit hash. template inline h256 sha3(FixedHash const& _input) { return sha3(_input.ref()); } -extern h256 EmptySHA3; - -extern h256 EmptyListSHA3; - -// Other crypto convenience routines +/// Calculate SHA3-256 hash of the given input, possibly interpreting it as nibbles, and return the hash as a string filled with binary data. +inline std::string sha3(std::string const& _input, bool _isNibbles) { return asString((_isNibbles ? sha3(fromHex(_input)) : sha3(bytesConstRef(&_input))).asBytes()); } -bytes aesDecrypt(bytesConstRef _cipher, std::string const& _password, unsigned _rounds = 2000, bytesConstRef _salt = bytesConstRef()); +/// Calculate SHA3-256 MAC +inline void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output) { sha3(_secret.toBytes() + _plain.toBytes()).ref().populate(_output); } -void sha256(bytesConstRef _input, bytesRef _output); +extern h256 EmptySHA3; -void ripemd160(bytesConstRef _input, bytesRef _output); +extern h256 EmptyListSHA3; } diff --git a/libdevcrypto/TrieCommon.cpp b/libdevcore/TrieCommon.cpp similarity index 100% rename from libdevcrypto/TrieCommon.cpp rename to libdevcore/TrieCommon.cpp diff --git a/libdevcrypto/TrieCommon.h b/libdevcore/TrieCommon.h similarity index 100% rename from libdevcrypto/TrieCommon.h rename to libdevcore/TrieCommon.h diff --git a/libdevcrypto/TrieDB.cpp b/libdevcore/TrieDB.cpp similarity index 100% rename from libdevcrypto/TrieDB.cpp rename to libdevcore/TrieDB.cpp diff --git a/libdevcrypto/TrieDB.h b/libdevcore/TrieDB.h similarity index 99% rename from libdevcrypto/TrieDB.h rename to libdevcore/TrieDB.h index cf85148d2..f9d7bff5f 100644 --- a/libdevcrypto/TrieDB.h +++ b/libdevcore/TrieDB.h @@ -30,9 +30,8 @@ #include #include #include -#include +#include #include "MemoryDB.h" -#include "OverlayDB.h" #include "TrieCommon.h" namespace ldb = leveldb; diff --git a/libdevcrypto/TrieHash.cpp b/libdevcore/TrieHash.cpp similarity index 80% rename from libdevcrypto/TrieHash.cpp rename to libdevcore/TrieHash.cpp index 0b02ce77f..cff3464b5 100644 --- a/libdevcrypto/TrieHash.cpp +++ b/libdevcore/TrieHash.cpp @@ -20,9 +20,9 @@ */ #include "TrieHash.h" -#include -#include // @TODO replace ASAP! -#include +#include +#include // @TODO replace ASAP! +#include #include using namespace std; using namespace dev; @@ -158,74 +158,40 @@ void hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_i } } -h256 hash256(StringMap const& _s) -{ - // build patricia tree. - if (_s.empty()) - return sha3(rlp("")); - HexMap hexMap; - for (auto i = _s.rbegin(); i != _s.rend(); ++i) - hexMap[asNibbles(i->first)] = i->second; - RLPStream s; - hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s); - return sha3(s.out()); -} - -bytes rlp256(StringMap const& _s) +bytes rlp256(BytesMap const& _s) { // build patricia tree. if (_s.empty()) return rlp(""); HexMap hexMap; for (auto i = _s.rbegin(); i != _s.rend(); ++i) - hexMap[asNibbles(i->first)] = i->second; + hexMap[asNibbles(bytesConstRef(&i->first))] = i->second; RLPStream s; - hash256aux(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s); + hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s); return s.out(); } -h256 hash256(u256Map const& _s) +h256 hash256(BytesMap const& _s) { - // build patricia tree. - if (_s.empty()) - return sha3(rlp("")); - HexMap hexMap; - for (auto i = _s.rbegin(); i != _s.rend(); ++i) - hexMap[asNibbles(toBigEndianString(i->first))] = asString(rlp(i->second)); - RLPStream s; - hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s); - return sha3(s.out()); + return sha3(rlp256(_s)); } -/*h256 orderedTrieRoot(std::vector const& _data) +h256 orderedTrieRoot(std::vector const& _data) { - StringMap m; + BytesMap m; unsigned j = 0; for (auto i: _data) - m[asString(rlp(j++))] = asString(i); + m[rlp(j++)] = i; return hash256(m); -}*/ - -h256 orderedTrieRoot(std::vector const& _data) -{ - MemoryDB db; - GenericTrieDB t(&db); - t.init(); - unsigned j = 0; - for (auto i: _data) - t.insert(rlp(j++), i.toBytes()); - return t.root(); } -h256 orderedTrieRoot(std::vector const& _data) +h256 orderedTrieRoot(std::vector const& _data) { - MemoryDB db; - GenericTrieDB t(&db); - t.init(); + BytesMap m; unsigned j = 0; for (auto i: _data) - t.insert(rlp(j++), i); - return t.root(); + m[rlp(j++)] = i.toBytes(); + return hash256(m); } } diff --git a/libdevcrypto/TrieHash.h b/libdevcore/TrieHash.h similarity index 80% rename from libdevcrypto/TrieHash.h rename to libdevcore/TrieHash.h index b0588fc38..9649ef0c7 100644 --- a/libdevcrypto/TrieHash.h +++ b/libdevcore/TrieHash.h @@ -27,21 +27,18 @@ namespace dev { -bytes rlp256(StringMap const& _s); -h256 hash256(StringMap const& _s); -h256 hash256(u256Map const& _s); +bytes rlp256(BytesMap const& _s); +h256 hash256(BytesMap const& _s); -/*h256 orderedTrieRoot(std::vector const& _data); +h256 orderedTrieRoot(std::vector const& _data); template inline h256 trieRootOver(unsigned _itemCount, T const& _getKey, U const& _getValue) { - StringMap m; + BytesMap m; for (unsigned i = 0; i < _itemCount; ++i) - m[asString(_getKey(i))] = asString(_getValue(i)); + m[_getKey(i)] = _getValue(i); return hash256(m); -}*/ - -using bytesMap = std::unordered_map; +} h256 orderedTrieRoot(std::vector const& _data); h256 orderedTrieRoot(std::vector const& _data); diff --git a/libdevcore/picosha2.h b/libdevcore/picosha2.h new file mode 100644 index 000000000..44b6bee59 --- /dev/null +++ b/libdevcore/picosha2.h @@ -0,0 +1,360 @@ +/* +The MIT License (MIT) + +Copyright (C) 2014 okdshin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +#ifndef PICOSHA2_H +#define PICOSHA2_H +//picosha2:20140213 +#include +#include +#include +#include +#include +#include +#include + +namespace picosha2 +{ + +namespace detail +{ + +inline uint8_t mask_8bit(uint8_t x){ + return x&0xff; +} + +inline uint32_t mask_32bit(uint32_t x){ + return x&0xffffffff; +} + +static const uint32_t add_constant[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +static const uint32_t initial_message_digest[8] = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 +}; + +inline uint32_t ch(uint32_t x, uint32_t y, uint32_t z){ + return (x&y)^((~x)&z); +} + +inline uint32_t maj(uint32_t x, uint32_t y, uint32_t z){ + return (x&y)^(x&z)^(y&z); +} + +inline uint32_t rotr(uint32_t x, std::size_t n){ + assert(n < 32); + return mask_32bit((x>>n)|(x<<(32-n))); +} + +inline uint32_t bsig0(uint32_t x){ + return rotr(x, 2)^rotr(x, 13)^rotr(x, 22); +} + +inline uint32_t bsig1(uint32_t x){ + return rotr(x, 6)^rotr(x, 11)^rotr(x, 25); +} + +inline uint32_t shr(uint32_t x, std::size_t n){ + assert(n < 32); + return x >> n; +} + +inline uint32_t ssig0(uint32_t x){ + return rotr(x, 7)^rotr(x, 18)^shr(x, 3); +} + +inline uint32_t ssig1(uint32_t x){ + return rotr(x, 17)^rotr(x, 19)^shr(x, 10); +} + +template +void hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last){ + (void)last; // FIXME: check this is valid + uint32_t w[64]; + std::fill(w, w+64, 0); + for(std::size_t i = 0; i < 16; ++i){ + w[i] = (static_cast(mask_8bit(*(first+i*4)))<<24) + |(static_cast(mask_8bit(*(first+i*4+1)))<<16) + |(static_cast(mask_8bit(*(first+i*4+2)))<<8) + |(static_cast(mask_8bit(*(first+i*4+3)))); + } + for(std::size_t i = 16; i < 64; ++i){ + w[i] = mask_32bit(ssig1(w[i-2])+w[i-7]+ssig0(w[i-15])+w[i-16]); + } + + uint32_t a = *message_digest; + uint32_t b = *(message_digest+1); + uint32_t c = *(message_digest+2); + uint32_t d = *(message_digest+3); + uint32_t e = *(message_digest+4); + uint32_t f = *(message_digest+5); + uint32_t g = *(message_digest+6); + uint32_t h = *(message_digest+7); + + for(std::size_t i = 0; i < 64; ++i){ + uint32_t temp1 = h+bsig1(e)+ch(e,f,g)+add_constant[i]+w[i]; + uint32_t temp2 = bsig0(a)+maj(a,b,c); + h = g; + g = f; + f = e; + e = mask_32bit(d+temp1); + d = c; + c = b; + b = a; + a = mask_32bit(temp1+temp2); + } + *message_digest += a; + *(message_digest+1) += b; + *(message_digest+2) += c; + *(message_digest+3) += d; + *(message_digest+4) += e; + *(message_digest+5) += f; + *(message_digest+6) += g; + *(message_digest+7) += h; + for(std::size_t i = 0; i < 8; ++i){ + *(message_digest+i) = mask_32bit(*(message_digest+i)); + } +} + +}//namespace detail + +template +void output_hex(InIter first, InIter last, std::ostream& os){ + os.setf(std::ios::hex, std::ios::basefield); + while(first != last){ + os.width(2); + os.fill('0'); + os << static_cast(*first); + ++first; + } + os.setf(std::ios::dec, std::ios::basefield); +} + +template +void bytes_to_hex_string(InIter first, InIter last, std::string& hex_str){ + std::ostringstream oss; + output_hex(first, last, oss); + hex_str.assign(oss.str()); +} + +template +void bytes_to_hex_string(const InContainer& bytes, std::string& hex_str){ + bytes_to_hex_string(bytes.begin(), bytes.end(), hex_str); +} + +template +std::string bytes_to_hex_string(InIter first, InIter last){ + std::string hex_str; + bytes_to_hex_string(first, last, hex_str); + return hex_str; +} + +template +std::string bytes_to_hex_string(const InContainer& bytes){ + std::string hex_str; + bytes_to_hex_string(bytes, hex_str); + return hex_str; +} + +class hash256_one_by_one { +public: + hash256_one_by_one(){ + init(); + } + + void init(){ + buffer_.clear(); + std::fill(data_length_digits_, data_length_digits_+4, 0); + std::copy(detail::initial_message_digest, detail::initial_message_digest+8, h_); + } + + template + void process(RaIter first, RaIter last){ + add_to_data_length(std::distance(first, last)); + std::copy(first, last, std::back_inserter(buffer_)); + std::size_t i = 0; + for(;i+64 <= buffer_.size(); i+=64){ + detail::hash256_block(h_, buffer_.begin()+i, buffer_.begin()+i+64); + } + buffer_.erase(buffer_.begin(), buffer_.begin()+i); + } + + void finish(){ + uint8_t temp[64]; + std::fill(temp, temp+64, 0); + std::size_t remains = buffer_.size(); + std::copy(buffer_.begin(), buffer_.end(), temp); + temp[remains] = 0x80; + + if(remains > 55){ + std::fill(temp+remains+1, temp+64, 0); + detail::hash256_block(h_, temp, temp+64); + std::fill(temp, temp+64-4, 0); + } + else { + std::fill(temp+remains+1, temp+64-4, 0); + } + + write_data_bit_length(&(temp[56])); + detail::hash256_block(h_, temp, temp+64); + } + + template + void get_hash_bytes(OutIter first, OutIter last)const{ + for(const uint32_t* iter = h_; iter != h_+8; ++iter){ + for(std::size_t i = 0; i < 4 && first != last; ++i){ + *(first++) = detail::mask_8bit(static_cast((*iter >> (24-8*i)))); + } + } + } + +private: + void add_to_data_length(uint32_t n) { + uint32_t carry = 0; + data_length_digits_[0] += n; + for(std::size_t i = 0; i < 4; ++i) { + data_length_digits_[i] += carry; + if(data_length_digits_[i] >= 65536u) { + data_length_digits_[i] -= 65536u; + carry = 1; + } + else { + break; + } + } + } + void write_data_bit_length(uint8_t* begin) { + uint32_t data_bit_length_digits[4]; + std::copy( + data_length_digits_, data_length_digits_+4, + data_bit_length_digits + ); + + // convert byte length to bit length (multiply 8 or shift 3 times left) + uint32_t carry = 0; + for(std::size_t i = 0; i < 4; ++i) { + uint32_t before_val = data_bit_length_digits[i]; + data_bit_length_digits[i] <<= 3; + data_bit_length_digits[i] |= carry; + data_bit_length_digits[i] &= 65535u; + carry = (before_val >> (16-3)) & 65535u; + } + + // write data_bit_length + for(int i = 3; i >= 0; --i) { + (*begin++) = static_cast(data_bit_length_digits[i] >> 8); + (*begin++) = static_cast(data_bit_length_digits[i]); + } + } + std::vector buffer_; + uint32_t data_length_digits_[4]; //as 64bit integer (16bit x 4 integer) + uint32_t h_[8]; +}; + +inline void get_hash_hex_string(const hash256_one_by_one& hasher, std::string& hex_str){ + uint8_t hash[32]; + hasher.get_hash_bytes(hash, hash+32); + return bytes_to_hex_string(hash, hash+32, hex_str); +} + +inline std::string get_hash_hex_string(const hash256_one_by_one& hasher){ + std::string hex_str; + get_hash_hex_string(hasher, hex_str); + return hex_str; +} + +template +void hash256(RaIter first, RaIter last, OutIter first2, OutIter last2){ + hash256_one_by_one hasher; + //hasher.init(); + hasher.process(first, last); + hasher.finish(); + hasher.get_hash_bytes(first2, last2); +} + +template +void hash256(RaIter first, RaIter last, OutContainer& dst){ + hash256(first, last, dst.begin(), dst.end()); +} + +template +void hash256(const RaContainer& src, OutIter first, OutIter last){ + hash256(src.begin(), src.end(), first, last); +} + +template +void hash256(const RaContainer& src, OutContainer& dst){ + hash256(src.begin(), src.end(), dst.begin(), dst.end()); +} + + +template +void hash256_hex_string(RaIter first, RaIter last, std::string& hex_str){ + uint8_t hashed[32]; + hash256(first, last, hashed, hashed+32); + std::ostringstream oss; + output_hex(hashed, hashed+32, oss); + hex_str.assign(oss.str()); +} + +template +std::string hash256_hex_string(RaIter first, RaIter last){ + std::string hex_str; + hash256_hex_string(first, last, hex_str); + return hex_str; +} + +inline void hash256_hex_string(const std::string& src, std::string& hex_str){ + hash256_hex_string(src.begin(), src.end(), hex_str); +} + +template +void hash256_hex_string(const RaContainer& src, std::string& hex_str){ + hash256_hex_string(src.begin(), src.end(), hex_str); +} + +template +std::string hash256_hex_string(const RaContainer& src){ + return hash256_hex_string(src.begin(), src.end()); +} + +}//namespace picosha2 + +#endif //PICOSHA2_H diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp index 56885ae36..e9edac0d3 100644 --- a/libdevcrypto/AES.cpp +++ b/libdevcrypto/AES.cpp @@ -19,9 +19,9 @@ * @date 2014 */ -#include "CryptoPP.h" #include "AES.h" - +#include +#include "CryptoPP.h" using namespace std; using namespace dev; using namespace dev::crypto; @@ -58,3 +58,31 @@ size_t Stream::streamOut(bytes&) return 0; } +bytes dev::aesDecrypt(bytesConstRef _ivCipher, std::string const& _password, unsigned _rounds, bytesConstRef _salt) +{ + bytes pw = asBytes(_password); + + if (!_salt.size()) + _salt = &pw; + + bytes target(64); + CryptoPP::PKCS5_PBKDF2_HMAC().DeriveKey(target.data(), target.size(), 0, pw.data(), pw.size(), _salt.data(), _salt.size(), _rounds); + + try + { + CryptoPP::AES::Decryption aesDecryption(target.data(), 16); + auto cipher = _ivCipher.cropped(16); + auto iv = _ivCipher.cropped(0, 16); + CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data()); + std::string decrypted; + CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decrypted)); + stfDecryptor.Put(cipher.data(), cipher.size()); + stfDecryptor.MessageEnd(); + return asBytes(decrypted); + } + catch (exception const& e) + { + cerr << e.what() << endl; + return bytes(); + } +} diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h index f0646eb85..32d1880dc 100644 --- a/libdevcrypto/AES.h +++ b/libdevcrypto/AES.h @@ -86,4 +86,7 @@ private: } } -} \ No newline at end of file + +bytes aesDecrypt(bytesConstRef _cipher, std::string const& _password, unsigned _rounds = 2000, bytesConstRef _salt = bytesConstRef()); + +} diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index a5c176fe6..87e258573 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -26,8 +26,9 @@ #include #include #include -#include "SHA3.h" -#include "FileSystem.h" +#include +#include +#include "AES.h" #include "CryptoPP.h" using namespace std; using namespace dev; diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h index 4991e3713..ca8a2e6b5 100644 --- a/libdevcrypto/CryptoPP.h +++ b/libdevcrypto/CryptoPP.h @@ -49,7 +49,7 @@ #include #pragma warning(pop) #pragma GCC diagnostic pop -#include "SHA3.h" +#include #include "Common.h" namespace dev diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp index a00a92872..a5aaf3984 100644 --- a/libdevcrypto/ECDHE.cpp +++ b/libdevcrypto/ECDHE.cpp @@ -19,9 +19,9 @@ * @date 2014 */ -#include "SHA3.h" -#include "CryptoPP.h" #include "ECDHE.h" +#include +#include "CryptoPP.h" using namespace std; using namespace dev; diff --git a/libdevcrypto/OverlayDB.h b/libdevcrypto/OverlayDB.h index 2e5428bdf..b37d2c11b 100644 --- a/libdevcrypto/OverlayDB.h +++ b/libdevcrypto/OverlayDB.h @@ -29,7 +29,7 @@ #include #include #include -#include "MemoryDB.h" +#include namespace ldb = leveldb; namespace dev diff --git a/libdevcrypto/SHA3.cpp b/libdevcrypto/SHA3.cpp deleted file mode 100644 index b7a47b745..000000000 --- a/libdevcrypto/SHA3.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - 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 SHA3.cpp - * @author Gav Wood - * @date 2014 - */ - -#include "SHA3.h" - -#include -#include "CryptoPP.h" -using namespace std; -using namespace dev; - -namespace dev -{ - -h256 EmptySHA3 = sha3(bytesConstRef()); -h256 EmptyListSHA3 = sha3(rlpList()); - -std::string sha3(std::string const& _input, bool _hex) -{ - if (!_hex) - { - string ret(32, '\0'); - sha3(bytesConstRef((byte const*)_input.data(), _input.size()), bytesRef((byte*)ret.data(), 32)); - return ret; - } - - uint8_t buf[32]; - sha3(bytesConstRef((byte const*)_input.data(), _input.size()), bytesRef((byte*)&(buf[0]), 32)); - std::string ret(64, '\0'); - for (unsigned int i = 0; i < 32; i++) - sprintf((char*)(ret.data())+i*2, "%02x", buf[i]); - return ret; -} - -void sha3(bytesConstRef _input, bytesRef _output) -{ - CryptoPP::SHA3_256 ctx; - ctx.Update((byte*)_input.data(), _input.size()); - assert(_output.size() >= 32); - ctx.Final(_output.data()); -} - -void ripemd160(bytesConstRef _input, bytesRef _output) -{ - CryptoPP::RIPEMD160 ctx; - ctx.Update((byte*)_input.data(), _input.size()); - assert(_output.size() >= 32); - ctx.Final(_output.data()); -} - -void sha256(bytesConstRef _input, bytesRef _output) -{ - CryptoPP::SHA256 ctx; - ctx.Update((byte*)_input.data(), _input.size()); - assert(_output.size() >= 32); - ctx.Final(_output.data()); -} - -bytes sha3Bytes(bytesConstRef _input) -{ - bytes ret(32); - sha3(_input, &ret); - return ret; -} - -h256 sha3(bytesConstRef _input) -{ - h256 ret; - sha3(_input, bytesRef(&ret[0], 32)); - return ret; -} - -void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output) -{ - CryptoPP::SHA3_256 ctx; - assert(_secret.size() > 0); - ctx.Update((byte*)_secret.data(), _secret.size()); - ctx.Update((byte*)_plain.data(), _plain.size()); - assert(_output.size() >= 32); - ctx.Final(_output.data()); -} - -bytes aesDecrypt(bytesConstRef _ivCipher, std::string const& _password, unsigned _rounds, bytesConstRef _salt) -{ - bytes pw = asBytes(_password); - - if (!_salt.size()) - _salt = &pw; - - bytes target(64); - CryptoPP::PKCS5_PBKDF2_HMAC().DeriveKey(target.data(), target.size(), 0, pw.data(), pw.size(), _salt.data(), _salt.size(), _rounds); - - try - { - CryptoPP::AES::Decryption aesDecryption(target.data(), 16); - auto cipher = _ivCipher.cropped(16); - auto iv = _ivCipher.cropped(0, 16); - CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data()); - std::string decrypted; - CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decrypted)); - stfDecryptor.Put(cipher.data(), cipher.size()); - stfDecryptor.MessageEnd(); - return asBytes(decrypted); - } - catch (exception const& e) - { - cerr << e.what() << endl; - return bytes(); - } -} - -} diff --git a/libdevcrypto/SecretStore.cpp b/libdevcrypto/SecretStore.cpp index 9be0b89e8..0416aa9f4 100644 --- a/libdevcrypto/SecretStore.cpp +++ b/libdevcrypto/SecretStore.cpp @@ -25,9 +25,9 @@ #include #include #include +#include +#include #include -#include "SHA3.h" -#include "FileSystem.h" using namespace std; using namespace dev; namespace js = json_spirit; diff --git a/libdevcrypto/SecretStore.h b/libdevcrypto/SecretStore.h index 1fb6adf4a..18c290c1f 100644 --- a/libdevcrypto/SecretStore.h +++ b/libdevcrypto/SecretStore.h @@ -24,8 +24,8 @@ #include #include #include +#include #include "Common.h" -#include "FileSystem.h" namespace dev { diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 3891f2ef6..be17ba449 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -206,14 +206,15 @@ bool ethash_cl_miner::init(uint8_t const* _dag, uint64_t _dagSize, unsigned work m_header = cl::Buffer(m_context, CL_MEM_READ_ONLY, 32); // compute dag on CPU - { + try { m_queue.enqueueWriteBuffer(m_dag, CL_TRUE, 0, _dagSize, _dag); - - // if this throws then it's because we probably need to subdivide the dag uploads for compatibility -// void* dag_ptr = m_queue.enqueueMapBuffer(m_dag, true, m_opencl_1_1 ? CL_MAP_WRITE : CL_MAP_WRITE_INVALIDATE_REGION, 0, _dagSize); - // memcpying 1GB: horrible... really. horrible. but necessary since we can't mmap *and* gpumap. -// _fillDAG(dag_ptr); -// m_queue.enqueueUnmapMemObject(m_dag, dag_ptr); + } + catch (...) + { + // didn't work. shitty driver. try allocating in CPU RAM and manually memcpying it. + void* dag_ptr = m_queue.enqueueMapBuffer(m_dag, true, m_opencl_1_1 ? CL_MAP_WRITE : CL_MAP_WRITE_INVALIDATE_REGION, 0, _dagSize); + memcpy(dag_ptr, _dag, _dagSize); + m_queue.enqueueUnmapMemObject(m_dag, dag_ptr); } // create mining buffers diff --git a/libethcore/ABI.h b/libethcore/ABI.h index 7fca09c9a..09aca6754 100644 --- a/libethcore/ABI.h +++ b/libethcore/ABI.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include namespace dev { diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index 00a5108c4..0e125b607 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -21,8 +21,8 @@ #include #include -#include -#include +#include +#include #include #include #include "EthashAux.h" @@ -191,22 +191,12 @@ void BlockInfo::populate(bytesConstRef _block, Strictness _s, h256 const& _h) struct BlockInfoDiagnosticsChannel: public LogChannel { static const char* name() { return EthBlue "▧" EthWhite " ◌"; } static const int verbosity = 9; }; -template h256 trieRootOver(unsigned _itemCount, T const& _getKey, U const& _getValue) -{ - MemoryDB db; - GenericTrieDB t(&db); - t.init(); - for (unsigned i = 0; i < _itemCount; ++i) - t.insert(_getKey(i), _getValue(i)); - return t.root(); -} - void BlockInfo::verifyInternals(bytesConstRef _block) const { RLP root(_block); auto txList = root[1]; - auto expectedRoot = trieRootOver(txList.itemCount(), [&](unsigned i){ return rlp(i); }, [&](unsigned i){ return txList[i].data(); }); + auto expectedRoot = trieRootOver(txList.itemCount(), [&](unsigned i){ return rlp(i); }, [&](unsigned i){ return txList[i].data().toBytes(); }); clog(BlockInfoDiagnosticsChannel) << "Expected trie root:" << toString(expectedRoot); if (transactionsRoot != expectedRoot) diff --git a/libethcore/Common.cpp b/libethcore/Common.cpp index c74aeba5e..56db647f3 100644 --- a/libethcore/Common.cpp +++ b/libethcore/Common.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "Exceptions.h" #include "ProofOfWork.h" using namespace std; diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 7609d8b6b..228f03f8e 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #if ETH_ETHASHCL || !ETH_TRUE @@ -75,6 +75,13 @@ Ethash::WorkPackage Ethash::package(BlockInfo const& _bi) return ret; } +void Ethash::ensurePrecomputed(unsigned _number) +{ + if (_number % ETHASH_EPOCH_LENGTH > ETHASH_EPOCH_LENGTH * 9 / 10) + // 90% of the way to the new epoch + EthashAux::computeFull(EthashAux::seedHash(_number + ETHASH_EPOCH_LENGTH), true); +} + void Ethash::prep(BlockInfo const& _header, std::function const& _f) { EthashAux::full(_header.seedHash(), true, _f); @@ -306,6 +313,7 @@ void Ethash::GPUMiner::workLoop() cnote << "workLoop" << !!m_miner << m_minerSeed << w.seedHash; if (!m_miner || m_minerSeed != w.seedHash) { + cnote << "Initialising miner..."; m_minerSeed = w.seedHash; delete m_miner; @@ -333,9 +341,9 @@ void Ethash::GPUMiner::workLoop() uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)w.boundary >> 192); m_miner->search(w.headerHash.data(), upper64OfBoundary, *m_hook); } - catch (...) + catch (cl::Error const& _e) { - cwarn << "Error GPU mining. GPU memory fragmentation?"; + cwarn << "Error GPU mining: " << _e.what() << "(" << _e.err() << ")"; } } diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 81f842e4f..86540678f 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -74,6 +74,7 @@ public: static std::string name(); static unsigned revision(); static void prep(BlockInfo const& _header, std::function const& _f = std::function()); + static void ensurePrecomputed(unsigned _number); static bool verify(BlockInfo const& _header); static bool preVerify(BlockInfo const& _header); static WorkPackage package(BlockInfo const& _header); diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index eccb986a7..a94c1237d 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -31,8 +31,8 @@ #include #include #include -#include -#include +#include +#include #include #include "BlockInfo.h" #include "Exceptions.h" @@ -167,7 +167,7 @@ EthashAux::FullType EthashAux::full(h256 const& _seedHash, bool _createIfMissing return ret; } - if (_createIfMissing || computeFull(_seedHash) == 100) + if (_createIfMissing || computeFull(_seedHash, false) == 100) { s_dagCallback = _f; cnote << "Loading from libethash..."; @@ -183,7 +183,7 @@ EthashAux::FullType EthashAux::full(h256 const& _seedHash, bool _createIfMissing #define DEV_IF_THROWS(X) try { X; } catch (...) -unsigned EthashAux::computeFull(h256 const& _seedHash) +unsigned EthashAux::computeFull(h256 const& _seedHash, bool _createIfMissing) { Guard l(get()->x_fulls); uint64_t blockNumber; @@ -199,7 +199,7 @@ unsigned EthashAux::computeFull(h256 const& _seedHash) return 100; } - if (!get()->m_fullGenerator || !get()->m_fullGenerator->joinable()) + if (_createIfMissing && (!get()->m_fullGenerator || !get()->m_fullGenerator->joinable())) { get()->m_fullProgress = 0; get()->m_generatingFullNumber = blockNumber / ETHASH_EPOCH_LENGTH * ETHASH_EPOCH_LENGTH; diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index b09f6465f..e6fed519f 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -71,7 +71,7 @@ public: static const uint64_t NotGenerating = (uint64_t)-1; /// Kicks off generation of DAG for @a _seedHash and @returns false or @returns true if ready. - static unsigned computeFull(h256 const& _seedHash); + static unsigned computeFull(h256 const& _seedHash, bool _createIfMissing = true); /// Information on the generation progress. static std::pair fullGeneratingProgress() { return std::make_pair(get()->m_generatingFullNumber, get()->m_fullProgress); } /// Kicks off generation of DAG for @a _blocknumber and blocks until ready; @returns result or empty pointer if not existing and _createIfMissing is false. diff --git a/libethcore/ICAP.cpp b/libethcore/ICAP.cpp index 6fce19a62..158c297f8 100644 --- a/libethcore/ICAP.cpp +++ b/libethcore/ICAP.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "Exceptions.h" #include "ABI.h" using namespace std; diff --git a/libethcore/Miner.h b/libethcore/Miner.h index 3a68491ff..cede34475 100644 --- a/libethcore/Miner.h +++ b/libethcore/Miner.h @@ -107,12 +107,10 @@ public: } if (!!_work) { - boost::timer t; - pause(); - cdebug << "pause took" << t.elapsed(); - t.restart(); - kickOff(); - cdebug << "kickOff took" << t.elapsed(); + DEV_TIMED_ABOVE(pause, 250) + pause(); + DEV_TIMED_ABOVE(kickOff, 250) + kickOff(); } else if (!_work && !!old) pause(); diff --git a/libethereum/Account.h b/libethereum/Account.h index 660dc0a4c..87fc82b6c 100644 --- a/libethereum/Account.h +++ b/libethereum/Account.h @@ -23,8 +23,8 @@ #include #include -#include -#include +#include +#include namespace dev { diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 73747b25b..e23fde6b6 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include @@ -96,7 +96,7 @@ ldb::Slice dev::eth::toSlice(h256 const& _h, unsigned _sub) #endif } -#if ETH_DEBUG +#if ETH_DEBUG&&0 static const chrono::system_clock::duration c_collectionDuration = chrono::seconds(15); static const unsigned c_collectionQueueSize = 2; static const unsigned c_maxCacheSize = 1024 * 1024 * 1; @@ -318,7 +318,9 @@ tuple BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st try { // Nonce & uncle nonces already verified thread at this point. - auto r = import(block.first, block.second, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce & ~ImportRequirements::CheckUncles); + ImportRoute r; + DEV_TIMED_ABOVE(Block import, 500) + r = import(block.first, block.second, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce & ~ImportRequirements::CheckUncles); fresh += r.first; dead += r.second; } diff --git a/libethereum/BlockQueue.h b/libethereum/BlockQueue.h index c865bac32..d0437739d 100644 --- a/libethereum/BlockQueue.h +++ b/libethereum/BlockQueue.h @@ -94,7 +94,7 @@ public: void retryAllUnknown(); /// Get information on the items queued. - std::pair items() const { ReadGuard l(m_lock); return std::make_pair(m_verified.size(), m_unknown.size()); } + std::pair items() const { ReadGuard l(m_lock); return std::make_pair(m_readySet.size(), m_unknownSet.size()); } /// Clear everything. void clear() { WriteGuard l(m_lock); DEV_INVARIANT_CHECK; Guard l2(m_verification); m_readySet.clear(); m_drainingSet.clear(); m_verified.clear(); m_unverified.clear(); m_unknownSet.clear(); m_unknown.clear(); m_future.clear(); } diff --git a/libethereum/CachedAddressState.cpp b/libethereum/CachedAddressState.cpp index a25017793..757aef466 100644 --- a/libethereum/CachedAddressState.cpp +++ b/libethereum/CachedAddressState.cpp @@ -21,8 +21,9 @@ #include "CachedAddressState.h" +#include #include -#include +#include #include "Account.h" using namespace std; using namespace dev; @@ -57,8 +58,8 @@ std::unordered_map CachedAddressState::storage() const if (m_r) { SecureTrieDB memdb(const_cast(m_o), m_r[2].toHash()); // promise we won't alter the overlay! :) -// for (auto const& j: memdb) -// ret[j.first] = RLP(j.second).toInt(); + for (auto const& j: memdb) + ret[j.first] = RLP(j.second).toInt(); } if (m_s) for (auto const& j: m_s->storageOverlay()) diff --git a/libethereum/CanonBlockChain.cpp b/libethereum/CanonBlockChain.cpp index f1de7292b..5dd7dc2ce 100644 --- a/libethereum/CanonBlockChain.cpp +++ b/libethereum/CanonBlockChain.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 97118a7a9..e372e611a 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -172,6 +172,7 @@ Client::Client(p2p::Host* _extNet, std::string const& _dbPath, WithExisting _for m_preMine(m_stateDB, BaseState::CanonGenesis), m_postMine(m_stateDB) { + m_lastGetWork = std::chrono::system_clock::now() - chrono::seconds(30); m_tqReady = m_tq.onReady([=](){ this->onTransactionQueueReady(); }); // TODO: should read m_tq->onReady(thisThread, syncTransactionQueue); m_bqReady = m_bq.onReady([=](){ this->onBlockQueueReady(); }); // TODO: should read m_bq->onReady(thisThread, syncBlockQueue); m_farm.onSolutionFound([=](ProofOfWork::Solution const& s){ return this->submitWork(s); }); @@ -197,6 +198,7 @@ Client::Client(p2p::Host* _extNet, std::shared_ptr _gp, std::string c m_preMine(m_stateDB), m_postMine(m_stateDB) { + m_lastGetWork = std::chrono::system_clock::now() - chrono::seconds(30); m_tqReady = m_tq.onReady([=](){ this->onTransactionQueueReady(); }); // TODO: should read m_tq->onReady(thisThread, syncTransactionQueue); m_bqReady = m_bq.onReady([=](){ this->onBlockQueueReady(); }); // TODO: should read m_bq->onReady(thisThread, syncBlockQueue); m_farm.onSolutionFound([=](ProofOfWork::Solution const& s){ return this->submitWork(s); }); @@ -453,8 +455,15 @@ ProofOfWork::WorkPackage Client::getWork() { // lock the work so a later submission isn't invalidated by processing a transaction elsewhere. // this will be reset as soon as a new block arrives, allowing more transactions to be processed. + bool oldShould = shouldServeWork(); m_lastGetWork = chrono::system_clock::now(); - m_remoteWorking = true; + + // if this request has made us bother to serve work, prep it now. + if (!oldShould && shouldServeWork()) + onPostStateChanged(); + else + // otherwise, set this to true so that it gets prepped next time. + m_remoteWorking = true; return ProofOfWork::package(m_miningInfo); } @@ -484,7 +493,7 @@ void Client::syncBlockQueue() cwork << "BQ ==> CHAIN ==> STATE"; { - tie(ir.first, ir.second, m_syncBlockQueue) = m_bc.sync(m_bq, m_stateDB, 10); + tie(ir.first, ir.second, m_syncBlockQueue) = m_bc.sync(m_bq, m_stateDB, rand() % 90 + 10); if (ir.first.empty()) return; } @@ -607,7 +616,8 @@ bool Client::remoteActive() const void Client::onPostStateChanged() { cnote << "Post state changed"; - if (isMining() || remoteActive()) + + if (m_bq.items().first == 0 && (isMining() || remoteActive())) { cnote << "Restarting mining..."; DEV_WRITE_GUARDED(x_working) @@ -619,6 +629,8 @@ void Client::onPostStateChanged() m_miningInfo = m_postMine.info(); } m_farm.setWork(m_miningInfo); + + Ethash::ensurePrecomputed(m_bc.number()); } m_remoteWorking = false; } @@ -636,7 +648,7 @@ void Client::noteChanged(h256Hash const& _filters) { Guard l(x_filtersWatches); if (_filters.size()) - filtersStreamOut(cnote << "noteChanged:", _filters); + filtersStreamOut(cwatch << "noteChanged:", _filters); // accrue all changes left in each filter into the watches. for (auto& w: m_watches) if (_filters.count(w.second.id)) diff --git a/libethereum/Client.h b/libethereum/Client.h index 7eeb7fb2d..c77cb6034 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -274,6 +274,9 @@ private: /// Ticks various system-level objects. void tick(); + /// @returns true only if it's worth bothering to prep the mining block. + bool shouldServeWork() const { return m_bq.items().first == 0 && (isMining() || remoteActive()); } + VersionChecker m_vc; ///< Dummy object to check & update the protocol version. CanonBlockChain m_bc; ///< Maintains block database. BlockQueue m_bq; ///< Maintains a list of incoming blocks not yet on the blockchain (to be imported). @@ -289,7 +292,7 @@ private: BlockInfo m_miningInfo; ///< The header we're attempting to mine on (derived from m_postMine). bool remoteActive() const; ///< Is there an active and valid remote worker? bool m_remoteWorking = false; ///< Has the remote worker recently been reset? - std::chrono::system_clock::time_point m_lastGetWork = std::chrono::system_clock::time_point::min(); ///< Is there an active and valid remote worker? + std::chrono::system_clock::time_point m_lastGetWork; ///< Is there an active and valid remote worker? std::weak_ptr m_host; ///< Our Ethereum Host. Don't do anything if we can't lock. diff --git a/libethereum/Defaults.cpp b/libethereum/Defaults.cpp index febe53d84..b839bbb5c 100644 --- a/libethereum/Defaults.cpp +++ b/libethereum/Defaults.cpp @@ -21,7 +21,7 @@ #include "Defaults.h" -#include +#include using namespace std; using namespace dev; using namespace dev::eth; diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index a1eee9440..4fbf51244 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -159,6 +159,42 @@ bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _sen return !m_ext; } +bool Executive::call(CallParameters const& _p, u256 const& _gasPrice, Address const& _origin) +{ + m_isCreation = false; +// cnote << "Transferring" << formatBalance(_value) << "to receiver."; + auto it = !(_p.codeAddress & ~h160(0xffffffff)) ? precompiled().find((unsigned)(u160)_p.codeAddress) : precompiled().end(); + if (it != precompiled().end()) + { + bigint g = it->second.gas(_p.data); + if (_p.gas < g) + { + m_endGas = 0; + m_excepted = TransactionException::OutOfGasBase; + // Bail from exception. + return true; // true actually means "all finished - nothing more to be done regarding go(). + } + else + { + m_endGas = (u256)(_p.gas - g); + m_precompiledOut = it->second.exec(_p.data); + m_out = &m_precompiledOut; + } + } + else if (m_s.addressHasCode(_p.codeAddress)) + { + m_vm = VMFactory::create(_p.gas); + bytes const& c = m_s.code(_p.codeAddress); + m_ext = make_shared(m_s, m_lastHashes, _p.receiveAddress, _p.senderAddress, _origin, _p.value, _gasPrice, _p.data, &c, m_depth); + } + else + m_endGas = _p.gas; + + m_s.transferBalance(_p.senderAddress, _p.receiveAddress, _p.value); + + return !m_ext; +} + bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _init, Address _origin) { m_isCreation = true; diff --git a/libethereum/Executive.h b/libethereum/Executive.h index 3806221be..8bb0ab771 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -95,6 +95,7 @@ public: /// Set up the executive for evaluating a bare CALL (message call) operation. /// @returns false iff go() must be called (and thus a VM execution in required). bool call(Address _myAddress, Address _codeAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256 _gas, Address _originAddress); + bool call(CallParameters const& _cp, u256 const& _gasPrice, Address const& _origin); /// Finalise an operation through accruing the substate into the parent context. void accrueSubState(SubState& _parentContext); diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index 68d146ce1..c0591cef5 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -26,16 +26,16 @@ using namespace std; using namespace dev; using namespace dev::eth; -bool ExtVM::call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, u256& io_gas, bytesRef _out, OnOpFunc const& _onOp, Address _myAddressOverride, Address _codeAddressOverride) +bool ExtVM::call(CallParameters& _p) { Executive e(m_s, lastHashes, depth + 1); - if (!e.call(_receiveAddress, _codeAddressOverride, _myAddressOverride ? _myAddressOverride : myAddress, _txValue, gasPrice, _txData, io_gas, origin)) + if (!e.call(_p, gasPrice, origin)) { - e.go(_onOp); + e.go(_p.onOp); e.accrueSubState(sub); } - io_gas = e.endGas(); - e.out().copyTo(_out); + _p.gas = e.endGas(); + e.out().copyTo(_p.out); return !e.excepted(); } diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index 1a2d180dd..babff4edf 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -58,7 +58,7 @@ public: virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp = {}) override final; /// Create a new message call. Leave _myAddressOverride as the default to use the present address as caller. - virtual bool call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, u256& io_gas, bytesRef _out, OnOpFunc const& _onOp = {}, Address _myAddressOverride = {}, Address _codeAddressOverride = {}) override final; + virtual bool call(CallParameters& _params) override final; /// Read address's balance. virtual u256 balance(Address _a) override final { return m_s.balance(_a); } diff --git a/libethereum/KeyManager.cpp b/libethereum/KeyManager.cpp index 11b2cb2a6..8c3fd28c3 100644 --- a/libethereum/KeyManager.cpp +++ b/libethereum/KeyManager.cpp @@ -61,12 +61,17 @@ bool KeyManager::load(std::string const& _pass) if (version == 1) { for (auto const& i: s[1]) + { m_keyInfo[m_addrLookup[(Address)i[0]] = (h128)i[1]] = KeyInfo((h256)i[2], (std::string)i[3]); + cdebug << toString((Address)i[0]) << toString((h128)i[1]) << toString((h256)i[2]) << (std::string)i[3]; + } + for (auto const& i: s[2]) m_passwordInfo[(h256)i[0]] = (std::string)i[1]; m_password = (string)s[3]; } m_cachedPasswords[hashPassword(m_password)] = m_password; + m_cachedPasswords[hashPassword(defaultPassword())] = defaultPassword(); return true; } catch (...) { @@ -210,4 +215,6 @@ void KeyManager::write(h128 const& _key, std::string const& _keysFile) const writeFile(_keysFile, encryptSymNoAuth(_key, h128(), &s.out())); m_key = _key; + m_cachedPasswords[hashPassword(defaultPassword())] = defaultPassword(); + } diff --git a/libethereum/KeyManager.h b/libethereum/KeyManager.h index 38e8d8853..0a83fcc00 100644 --- a/libethereum/KeyManager.h +++ b/libethereum/KeyManager.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include namespace dev { @@ -75,10 +75,11 @@ public: Address address(h128 const& _uuid) const; h128 import(Secret const& _s, std::string const& _info, std::string const& _pass, std::string const& _passInfo); - h128 import(Secret const& _s, std::string const& _info) { return import(_s, _info, m_password, std::string()); } + h128 import(Secret const& _s, std::string const& _info) { return import(_s, _info, defaultPassword(), std::string()); } SecretStore& store() { return m_store; } void importExisting(h128 const& _uuid, std::string const& _info, std::string const& _pass, std::string const& _passInfo); + void importExisting(h128 const& _uuid, std::string const& _info) { importExisting(_uuid, _info, defaultPassword(), std::string()); } Secret secret(Address const& _address, std::function const& _pass = DontKnowThrow) const; Secret secret(h128 const& _uuid, std::function const& _pass = DontKnowThrow) const; @@ -87,6 +88,7 @@ public: void kill(Address const& _a); private: + std::string defaultPassword() const { return asString(m_key.ref()); } h256 hashPassword(std::string const& _pass) const; // Only use if previously loaded ok. @@ -103,7 +105,11 @@ private: // Passwords that we're storing. mutable std::unordered_map m_cachedPasswords; - // The default password for keys in the keystore - protected by the master password. + // DEPRECATED. + // Used to be the default password for keys in the keystore, stored in the keys file. + // Now the default password is based off the key of the keys file directly, so this is redundant + // except for the fact that people have existing keys stored with it. Leave for now until/unless + // we have an upgrade strategy. std::string m_password; SecretStore m_store; diff --git a/libethereum/LogFilter.cpp b/libethereum/LogFilter.cpp index ab9848d59..21ba9d3ef 100644 --- a/libethereum/LogFilter.cpp +++ b/libethereum/LogFilter.cpp @@ -21,7 +21,7 @@ #include "LogFilter.h" -#include +#include #include "State.h" using namespace std; using namespace dev; diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index cdcb4a46a..0e80949fe 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -21,7 +21,9 @@ #include "Precompiled.h" -#include +#include +#include +#include #include #include #include @@ -61,19 +63,12 @@ static bytes ecrecoverCode(bytesConstRef _in) static bytes sha256Code(bytesConstRef _in) { - bytes ret(32); - sha256(_in, &ret); - return ret; + return sha256(_in).asBytes(); } static bytes ripemd160Code(bytesConstRef _in) { - bytes ret(32); - ripemd160(_in, &ret); - // leaves the 20-byte hash left-aligned. we want it right-aligned: - memmove(ret.data() + 12, ret.data(), 20); - memset(ret.data(), 0, 12); - return ret; + return h256(ripemd160(_in), h256::AlignRight).asBytes(); } static bytes identityCode(bytesConstRef _in) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 3bf7aaff7..c753f57ea 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -840,16 +840,8 @@ void State::commitToMine(BlockChain const& _bc) } } - // TODO: move over to using TrieHash - - - MemoryDB tm; - GenericTrieDB transactionsTrie(&tm); - transactionsTrie.init(); - - MemoryDB rm; - GenericTrieDB receiptsTrie(&rm); - receiptsTrie.init(); + BytesMap transactionsMap; + BytesMap receiptsMap; RLPStream txs; txs.appendList(m_transactions.size()); @@ -861,11 +853,11 @@ void State::commitToMine(BlockChain const& _bc) RLPStream receiptrlp; m_receipts[i].streamRLP(receiptrlp); - receiptsTrie.insert(&k.out(), &receiptrlp.out()); + receiptsMap.insert(std::make_pair(k.out(), receiptrlp.out())); RLPStream txrlp; m_transactions[i].streamRLP(txrlp); - transactionsTrie.insert(&k.out(), &txrlp.out()); + transactionsMap.insert(std::make_pair(k.out(), txrlp.out())); txs.appendRaw(txrlp.out()); } @@ -874,8 +866,8 @@ void State::commitToMine(BlockChain const& _bc) RLPStream(unclesCount).appendRaw(unclesData.out(), unclesCount).swapOut(m_currentUncles); - m_currentBlock.transactionsRoot = transactionsTrie.root(); - m_currentBlock.receiptsRoot = receiptsTrie.root(); + m_currentBlock.transactionsRoot = hash256(transactionsMap); + m_currentBlock.receiptsRoot = hash256(receiptsMap); m_currentBlock.logBloom = logBloom(); m_currentBlock.sha3Uncles = sha3(m_currentUncles); diff --git a/libethereum/State.h b/libethereum/State.h index d9fc9d2b5..f46d0e222 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -25,7 +25,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index 78852b7b8..09d6cd54c 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include #include namespace dev diff --git a/libethereum/Utility.cpp b/libethereum/Utility.cpp index 7b0a961b2..adfea4a51 100644 --- a/libethereum/Utility.cpp +++ b/libethereum/Utility.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include using namespace std; using namespace dev; using namespace dev::eth; diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 48fbd0b01..ce259bef2 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -108,6 +108,18 @@ using LastHashes = std::vector; using OnOpFunc = std::function; +struct CallParameters +{ + Address senderAddress; + Address codeAddress; + Address receiveAddress; + u256 gas; + u256 value; + bytesConstRef data; + bytesRef out; + OnOpFunc onOp; +}; + /** * @brief Interface and null implementation of the class for specifying VM externalities. */ @@ -153,7 +165,7 @@ public: virtual h160 create(u256, u256&, bytesConstRef, OnOpFunc const&) { return h160(); } /// Make a new message call. - virtual bool call(Address, u256, bytesConstRef, u256&, bytesRef, OnOpFunc const&, Address, Address) { return false; } + virtual bool call(CallParameters&) { return false; } /// Revert any changes made (by any of the other calls). virtual void log(h256s&& _topics, bytesConstRef _data) { sub.logs.push_back(LogEntry(myAddress, std::move(_topics), _data.toBytes())); } diff --git a/libevm/SmartVM.cpp b/libevm/SmartVM.cpp index 4f759a745..89397987e 100644 --- a/libevm/SmartVM.cpp +++ b/libevm/SmartVM.cpp @@ -21,7 +21,7 @@ #include "SmartVM.h" #include #include -#include +#include #include #include #include "VMFactory.h" diff --git a/libevm/SmartVM.h b/libevm/SmartVM.h index 29f464ecd..e21af23b0 100644 --- a/libevm/SmartVM.h +++ b/libevm/SmartVM.h @@ -31,12 +31,16 @@ namespace eth class SmartVM: public VMFace { public: - SmartVM(u256 _gas): VMFace(_gas) {} + SmartVM(u256 const& _gas): m_gas(_gas) {} virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final; + void reset(u256 const& _gas = 0) noexcept override { m_gas = _gas; } + u256 gas() const noexcept override { return (u256)m_gas; } + private: std::unique_ptr m_selectedVM; + bigint m_gas; }; } diff --git a/libevm/VM.cpp b/libevm/VM.cpp index 853ac25f6..27650e3ad 100644 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -25,9 +25,9 @@ using namespace std; using namespace dev; using namespace dev::eth; -void VM::reset(u256 _gas) noexcept +void VM::reset(u256 const& _gas) noexcept { - VMFace::reset(_gas); + m_gas = _gas; m_curPC = 0; m_jumpDests.clear(); } @@ -56,6 +56,8 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) { m_stack.reserve((unsigned)c_stackLimit); + unique_ptr callParams; + static const array c_metrics = metrics(); auto memNeed = [](u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; }; @@ -206,7 +208,7 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) BOOST_THROW_EXCEPTION(OutOfGas()); } - m_gas = (u256)((bigint)m_gas - runGas); + m_gas -= runGas; if (newTempSize > m_temp.size()) m_temp.resize((size_t)newTempSize); @@ -565,7 +567,7 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) m_stack.push_back(m_temp.size()); break; case Instruction::GAS: - m_stack.push_back(m_gas); + m_stack.push_back((u256)m_gas); break; case Instruction::JUMPDEST: break; @@ -614,7 +616,11 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) m_stack.pop_back(); if (_ext.balance(_ext.myAddress) >= endowment && _ext.depth < 1024) - m_stack.push_back((u160)_ext.create(endowment, m_gas, bytesConstRef(m_temp.data() + initOff, initSize), _onOp)); + { + u256 g(m_gas); + m_stack.push_back((u160)_ext.create(endowment, g, bytesConstRef(m_temp.data() + initOff, initSize), _onOp)); + m_gas = g; + } else m_stack.push_back(0); break; @@ -622,13 +628,16 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) case Instruction::CALL: case Instruction::CALLCODE: { - u256 gas = m_stack.back(); + if (!callParams) + callParams.reset(new CallParameters); + + callParams->gas = m_stack.back(); if (m_stack[m_stack.size() - 3] > 0) - gas += c_callStipend; + callParams->gas += c_callStipend; m_stack.pop_back(); - Address receiveAddress = asAddress(m_stack.back()); + callParams->receiveAddress = asAddress(m_stack.back()); m_stack.pop_back(); - u256 value = m_stack.back(); + callParams->value = m_stack.back(); m_stack.pop_back(); unsigned inOff = (unsigned)m_stack.back(); @@ -640,12 +649,19 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) unsigned outSize = (unsigned)m_stack.back(); m_stack.pop_back(); - if (_ext.balance(_ext.myAddress) >= value && _ext.depth < 1024) - m_stack.push_back(_ext.call(inst == Instruction::CALL ? receiveAddress : _ext.myAddress, value, bytesConstRef(m_temp.data() + inOff, inSize), gas, bytesRef(m_temp.data() + outOff, outSize), _onOp, {}, receiveAddress)); + if (_ext.balance(_ext.myAddress) >= callParams->value && _ext.depth < 1024) + { + callParams->onOp = _onOp; + callParams->senderAddress = _ext.myAddress; + callParams->codeAddress = inst == Instruction::CALL ? callParams->receiveAddress : callParams->senderAddress; + callParams->data = bytesConstRef(m_temp.data() + inOff, inSize); + callParams->out = bytesRef(m_temp.data() + outOff, outSize); + m_stack.push_back(_ext.call(*callParams)); + } else m_stack.push_back(0); - m_gas += gas; + m_gas += callParams->gas; break; } case Instruction::RETURN: diff --git a/libevm/VM.h b/libevm/VM.h index 30007e0b3..181fcdc2e 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include "VMFace.h" @@ -52,8 +52,6 @@ inline u256 fromAddress(Address _a) class VM: public VMFace { public: - virtual void reset(u256 _gas = 0) noexcept override final; - virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final; void require(u256 _n, u256 _d) { if (m_stack.size() < _n) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(StackUnderflow() << RequirementError((bigint)_n, (bigint)m_stack.size())); } if (m_stack.size() - _n + _d > c_stackLimit) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(OutOfStack() << RequirementError((bigint)(_d - _n), (bigint)m_stack.size())); } } @@ -64,17 +62,21 @@ public: bytes const& memory() const { return m_temp; } u256s const& stack() const { return m_stack; } + void reset(u256 const& _gas = 0) noexcept override; + u256 gas() const noexcept override { return (u256)m_gas; } + private: friend class VMFactory; /// Construct VM object. - explicit VM(u256 _gas): VMFace(_gas) {} + explicit VM(u256 _gas): m_gas(_gas) {} u256 m_curPC = 0; bytes m_temp; u256s m_stack; std::set m_jumpDests; std::function m_onFail; + bigint m_gas = 0; }; } diff --git a/libevm/VMFace.h b/libevm/VMFace.h index d2689d13e..92e6d4c4f 100644 --- a/libevm/VMFace.h +++ b/libevm/VMFace.h @@ -38,18 +38,15 @@ struct StackUnderflow: virtual VMException {}; class VMFace { public: - explicit VMFace(u256 _gas): m_gas(_gas) {} + VMFace() = default; virtual ~VMFace() = default; VMFace(VMFace const&) = delete; VMFace& operator=(VMFace const&) = delete; - virtual void reset(u256 _gas = 0) noexcept { m_gas = _gas; } - u256 gas() const noexcept { return m_gas; } + virtual void reset(u256 const& _gas = 0) noexcept = 0; + virtual u256 gas() const noexcept = 0; virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) = 0; - -protected: - u256 m_gas = 0; }; } diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index 9f6f9dd63..b2fa73116 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index 0aac9cedb..895778ed1 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -23,7 +23,7 @@ #include "KnownState.h" #include -#include +#include #include using namespace std; diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index e2599c1d5..998579a90 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include "Session.h" #include "Common.h" #include "Capability.h" diff --git a/libp2p/UDP.h b/libp2p/UDP.h index b09d556e7..a455b5057 100644 --- a/libp2p/UDP.h +++ b/libp2p/UDP.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include #include "Common.h" diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 9842901e7..14884254e 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include using namespace std; diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index b3fedc45d..bffa4158f 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -31,7 +31,7 @@ #include #include -#include +#include using namespace std; diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 838ee264e..2e513b7fc 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index d1f51decf..7577b83a1 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include diff --git a/libtestutils/Common.cpp b/libtestutils/Common.cpp index 5767be32c..cff21d464 100644 --- a/libtestutils/Common.cpp +++ b/libtestutils/Common.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "Common.h" using namespace std; diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 5235b0c4f..44f7f521c 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include #include "WebThreeStubServer.h" using namespace std; diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp index c29ac6bf6..dd9172c70 100644 --- a/libwhisper/Common.cpp +++ b/libwhisper/Common.cpp @@ -21,7 +21,7 @@ #include "Common.h" -#include +#include #include "Message.h" using namespace std; using namespace dev; diff --git a/libwhisper/Interface.h b/libwhisper/Interface.h index db595e21e..8b84193aa 100644 --- a/libwhisper/Interface.h +++ b/libwhisper/Interface.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include "Common.h" #include "Message.h" diff --git a/libwhisper/Message.h b/libwhisper/Message.h index bd73df268..893602190 100644 --- a/libwhisper/Message.h +++ b/libwhisper/Message.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include "Common.h" namespace dev diff --git a/libwhisper/WhisperHost.h b/libwhisper/WhisperHost.h index ebbbcf8ed..cd427da35 100644 --- a/libwhisper/WhisperHost.h +++ b/libwhisper/WhisperHost.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include "Common.h" #include "WhisperPeer.h" #include "Interface.h" diff --git a/libwhisper/WhisperPeer.h b/libwhisper/WhisperPeer.h index 8542e987d..ab9c8222a 100644 --- a/libwhisper/WhisperPeer.h +++ b/libwhisper/WhisperPeer.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include "Common.h" #include "Message.h" diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index f10b33408..a73dc920e 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include #include "QContractDefinition.h" @@ -50,6 +52,7 @@ const std::set c_predefinedContracts = namespace { +using namespace dev::eth; using namespace dev::solidity; class CollectLocalsVisitor: public ASTConstVisitor @@ -305,6 +308,7 @@ void CodeModel::runCompilationJob(int _jobId) } } cs.compile(false); + gasEstimation(cs); collectContracts(cs, sourceNames); } catch (dev::Exception const& _exception) @@ -350,6 +354,44 @@ QVariantMap CodeModel::resolveCompilationErrorLocation(CompilerStack const& _com return error; } +void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) +{ + if (m_gasCostsMaps) + m_gasCostsMaps->deleteLater(); + m_gasCostsMaps = new GasMapWrapper(this); + for (std::string n: _cs.getContractNames()) + { + ContractDefinition const& contractDefinition = _cs.getContractDefinition(n); + QString sourceName = QString::fromStdString(*contractDefinition.getLocation().sourceName); + + if (!m_gasCostsMaps->contains(sourceName)) + m_gasCostsMaps->insert(sourceName, QVariantList()); + + if (!contractDefinition.isFullyImplemented()) + continue; + dev::solidity::SourceUnit const& sourceUnit = _cs.getAST(*contractDefinition.getLocation().sourceName); + AssemblyItems const* items = _cs.getRuntimeAssemblyItems(n); + StructuralGasEstimator estimator; + std::map gasCosts = estimator.breakToStatementLevel(estimator.performEstimation(*items, std::vector({&sourceUnit})), {&sourceUnit}); + for (auto gasItem = gasCosts.begin(); gasItem != gasCosts.end(); ++gasItem) + { + SourceLocation const& location = gasItem->first->getLocation(); + GasMeter::GasConsumption cost = gasItem->second; + std::stringstream v; + v << cost.value; + m_gasCostsMaps->push(sourceName, location.start, location.end, QString::fromStdString(v.str()), cost.isInfinite); + } + } +} + +QVariantList CodeModel::gasCostByDocumentId(QString const& _documentId) const +{ + if (m_gasCostsMaps) + return m_gasCostsMaps->gasCostsByDocId(_documentId); + else + return QVariantList(); +} + void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs, std::vector const& _sourceNames) { Guard pl(x_pendingContracts); @@ -539,3 +581,29 @@ QString CodeModel::resolveFunctionName(dev::SourceLocation const& _location) } return QString(); } + +void GasMapWrapper::push(QString _source, int _start, int _end, QString _value, bool _isInfinite) +{ + GasMap* gas = new GasMap(_start, _end, _value, _isInfinite, this); + m_gasMaps.find(_source).value().push_back(QVariant::fromValue(gas)); +} + +bool GasMapWrapper::contains(QString _key) +{ + return m_gasMaps.contains(_key); +} + +void GasMapWrapper::insert(QString _source, QVariantList _variantList) +{ + m_gasMaps.insert(_source, _variantList); +} + +QVariantList GasMapWrapper::gasCostsByDocId(QString _source) +{ + auto gasIter = m_gasMaps.find(_source); + if (gasIter != m_gasMaps.end()) + return gasIter.value(); + else + return QVariantList(); +} + diff --git a/mix/CodeModel.h b/mix/CodeModel.h index 2510b4248..5291bdc72 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -32,6 +32,7 @@ #include #include #include "SolidityType.h" +#include "QBigInt.h" class QTextDocument; @@ -127,6 +128,42 @@ struct SourceMap }; using SourceMaps = QMap; //by source id +using GasCostsMaps = QMap; //gas cost by contract name + +class GasMapWrapper: public QObject +{ + Q_OBJECT + + Q_PROPERTY(GasCostsMaps gasMaps MEMBER m_gasMaps CONSTANT) + +public: + GasMapWrapper(QObject* _parent): QObject(_parent){} + void push(QString _source, int _start, int _end, QString _value, bool _isInfinite); + bool contains(QString _key); + void insert(QString _source, QVariantList _variantList); + QVariantList gasCostsByDocId(QString _source); + +private: + GasCostsMaps m_gasMaps; +}; + +class GasMap: public QObject +{ + Q_OBJECT + + Q_PROPERTY(int start MEMBER m_start CONSTANT) + Q_PROPERTY(int end MEMBER m_end CONSTANT) + Q_PROPERTY(QString gas MEMBER m_gas CONSTANT) + Q_PROPERTY(bool isInfinite MEMBER m_isInfinite CONSTANT) + +public: + GasMap(int _start, int _end, QString _gas, bool _isInfinite, QObject* _parent): QObject(_parent), m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite) {} + + int m_start; + int m_end; + QString m_gas; + bool m_isInfinite; +}; /// Code compilation model. Compiles contracts in background an provides compiled contract data class CodeModel: public QObject @@ -168,6 +205,10 @@ public: bool isContractOrFunctionLocation(dev::SourceLocation const& _location); /// Get funciton name by location QString resolveFunctionName(dev::SourceLocation const& _location); + /// Gas estimation for compiled sources + void gasEstimation(solidity::CompilerStack const& _cs); + /// Gas cost by doc id + Q_INVOKABLE QVariantList gasCostByDocumentId(QString const& _documentId) const; signals: /// Emited on compilation state change @@ -204,6 +245,7 @@ private: mutable dev::Mutex x_contractMap; ContractMap m_contractMap; SourceMaps m_sourceMaps; + GasMapWrapper* m_gasCostsMaps = 0; std::unique_ptr m_codeHighlighterSettings; QThread m_backgroundThread; BackgroundWorker m_backgroundWorker; @@ -217,3 +259,5 @@ private: } } + +//Q_DECLARE_METATYPE(dev::mix::GasMap) diff --git a/mix/FileIo.cpp b/mix/FileIo.cpp index 22538194c..cf8300677 100644 --- a/mix/FileIo.cpp +++ b/mix/FileIo.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include "FileIo.h" using namespace dev; diff --git a/mix/QFunctionDefinition.cpp b/mix/QFunctionDefinition.cpp index 13dbd4821..e6764d712 100644 --- a/mix/QFunctionDefinition.cpp +++ b/mix/QFunctionDefinition.cpp @@ -20,7 +20,7 @@ */ #include -#include +#include #include #include "QVariableDeclaration.h" #include "QFunctionDefinition.h" diff --git a/mix/qml/Application.qml b/mix/qml/Application.qml index fe62efe12..161f7141a 100644 --- a/mix/qml/Application.qml +++ b/mix/qml/Application.qml @@ -116,6 +116,10 @@ ApplicationWindow { MenuSeparator {} MenuItem { action: toggleAssemblyDebuggingAction } } + Menu { + title: qsTr("Tools") + MenuItem { action: gasEstimationAction } + } Menu { title: qsTr("Windows") MenuItem { action: openNextDocumentAction } @@ -409,4 +413,15 @@ ApplicationWindow { mainContent.codeEditor.goToCompilationError(); } } + + Action { + id: gasEstimationAction + text: qsTr("Display gas estimation") + shortcut: "Ctrl+G" + checkable: true + onTriggered: + { + mainContent.codeEditor.displayGasEstimation(checked); + } + } } diff --git a/mix/qml/CodeEditorView.qml b/mix/qml/CodeEditorView.qml index 4f5516264..51950fec7 100644 --- a/mix/qml/CodeEditorView.qml +++ b/mix/qml/CodeEditorView.qml @@ -168,6 +168,13 @@ Item { editors.itemAt(i).item.setFontSize(size); } + function displayGasEstimation(checked) + { + var editor = getEditor(currentDocumentId); + if (editor) + editor.displayGasEstimation(checked); + } + Component.onCompleted: projectModel.codeEditor = codeEditorView; Connections { @@ -177,6 +184,10 @@ Item { } onCompilationComplete: { sourceInError = ""; + var gasCosts = codeModel.gasCostByDocumentId(currentDocumentId); + var editor = getEditor(currentDocumentId); + if (editor) + editor.setGasCosts(gasCosts); } } @@ -280,6 +291,7 @@ Item { messageDialog.doc = editorListModel.get(index); messageDialog.open(); } + loader.item.displayGasEstimation(gasEstimationAction.checked); } } Component.onCompleted: { diff --git a/mix/qml/StatesComboBox.qml b/mix/qml/StatesComboBox.qml index 907580ee7..3d2b08eef 100644 --- a/mix/qml/StatesComboBox.qml +++ b/mix/qml/StatesComboBox.qml @@ -23,7 +23,6 @@ import QtQuick 2.0 import QtQuick.Controls 1.0 import QtQuick.Layouts 1.1 -import QtGraphicalEffects 1.0 import org.ethereum.qml.InverseMouseArea 1.0 Rectangle { diff --git a/mix/qml/StatusPane.qml b/mix/qml/StatusPane.qml index 0c01caeb1..1c1453002 100644 --- a/mix/qml/StatusPane.qml +++ b/mix/qml/StatusPane.qml @@ -3,7 +3,6 @@ import QtQuick.Controls 1.1 import QtQuick.Layouts 1.1 import QtQuick.Controls.Styles 1.3 import org.ethereum.qml.InverseMouseArea 1.0 -import QtGraphicalEffects 1.0 import "js/ErrorLocationFormater.js" as ErrorLocationFormater import "." diff --git a/mix/qml/WebCodeEditor.qml b/mix/qml/WebCodeEditor.qml index b188cacd6..054a63bd7 100644 --- a/mix/qml/WebCodeEditor.qml +++ b/mix/qml/WebCodeEditor.qml @@ -83,6 +83,16 @@ Item { editorBrowser.runJavaScript("setFontSize(" + size + ")", function(result) {}); } + function setGasCosts(gasCosts) { + if (initialized && editorBrowser) + editorBrowser.runJavaScript("setGasCosts('" + JSON.stringify(gasCosts) + "')", function(result) {}); + } + + function displayGasEstimation(show) { + if (initialized && editorBrowser) + editorBrowser.runJavaScript("displayGasEstimation('" + show + "')", function(result) {}); + } + Clipboard { id: clipboard @@ -134,7 +144,12 @@ Item { function compilationComplete() { if (editorBrowser) + { editorBrowser.runJavaScript("compilationComplete()", function(result) { }); + parent.displayGasEstimation(gasEstimationAction.checked); + } + + } function compilationError(error, firstLocation, secondLocations) diff --git a/mix/qml/html/cm/solarized.css b/mix/qml/html/cm/solarized.css index b8cede806..1d298b990 100644 --- a/mix/qml/html/cm/solarized.css +++ b/mix/qml/html/cm/solarized.css @@ -189,3 +189,9 @@ view-port } span.CodeMirror-selectedtext { color: #586e75 !important; } + +/* Gas Costs */ +.CodeMirror-gasCosts { + border-bottom: double 1px #2aa198; +} + diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index c85a87597..6af8ff131 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -208,5 +208,112 @@ setFontSize = function(size) editor.refresh(); } +makeGasCostMarker = function(value) { + var marker = document.createElement("div"); + marker.style.color = "#822"; + marker.innerHTML = value; + marker.className = "CodeMirror-errorannotation-context"; + return marker; +}; + +var gasCosts = null; +setGasCosts = function(_gasCosts) +{ + gasCosts = JSON.parse(_gasCosts); + if (showingGasEstimation) + { + displayGasEstimation(false); + displayGasEstimation(true); + } +} + +var showingGasEstimation = false; +var gasMarkText = []; +var gasMarkRef = {}; +displayGasEstimation = function(show) +{ + show = JSON.parse(show); + showingGasEstimation = show; + if (show) + { + var maxGas = 20000; + var step = colorGradient.length / maxGas; // 20000 max gas + clearGasMark(); + gasMarkText = []; + gasMarkRef = {}; + for (var i in gasCosts) + { + if (gasCosts[i].gas !== "0") + { + var color; + var colorIndex = Math.round(step * gasCosts[i].gas); + if (gasCosts[i].isInfinite || colorIndex > colorGradient.length) + color = colorGradient[colorGradient.length - 1]; + else + color = colorGradient[colorIndex]; + var className = "CodeMirror-gasCosts" + i; + var line = editor.posFromIndex(gasCosts[i].start) + gasMarkText.push(editor.markText(line, editor.posFromIndex(gasCosts[i].end), { inclusiveLeft: true, inclusiveRight: true, handleMouseEvents: true, className: className, css: "background-color:" + color })); + gasMarkRef[className] = { line: line.line, value: gasCosts[i] }; + } + } + CodeMirror.on(editor.getWrapperElement(), "mouseover", listenMouseOver); + } + else + { + CodeMirror.off(editor.getWrapperElement(), "mouseover", listenMouseOver); + clearGasMark(); + if (gasAnnotation) + { + gasAnnotation.clear(); + gasAnnotation = null; + } + } +} + +function clearGasMark() +{ + if (gasMarkText) + for (var k in gasMarkText) + gasMarkText[k].clear(); +} + +var gasAnnotation; +function listenMouseOver(e) +{ + var node = e.target || e.srcElement; + if (node) + { + if (node.className && node.className.indexOf("CodeMirror-gasCosts") !== -1) + { + if (gasAnnotation) + gasAnnotation.clear(); + var cl = getGasCostClass(node); + var gasTitle = gasMarkRef[cl].value.isInfinite ? "infinite" : gasMarkRef[cl].value.gas; + gasTitle = gasTitle + " gas"; + gasAnnotation = editor.addLineWidget(gasMarkRef[cl].line + 1, makeGasCostMarker(gasTitle), { coverGutter: false, above: true }); + } + else if (gasAnnotation) + { + gasAnnotation.clear(); + gasAnnotation = null; + } + } +} + +function getGasCostClass(node) +{ + var classes = node.className.split(" "); + for (var k in classes) + { + if (classes[k].indexOf("CodeMirror-gasCosts") !== -1) + return classes[k]; + } + return ""; +} + +// blue => red ["#1515ED", "#1714EA", "#1914E8", "#1B14E6", "#1D14E4", "#1F14E2", "#2214E0", "#2414DE", "#2614DC", "#2813DA", "#2A13D8", "#2D13D6", "#2F13D4", "#3113D2", "#3313D0", "#3513CE", "#3713CC", "#3A12CA", "#3C12C8", "#3E12C6", "#4012C4", "#4212C2", "#4512C0", "#4712BE", "#4912BC", "#4B11BA", "#4D11B8", "#4F11B6", "#5211B4", "#5411B2", "#5611B0", "#5811AE", "#5A11AC", "#5D11AA", "#5F10A7", "#6110A5", "#6310A3", "#6510A1", "#67109F", "#6A109D", "#6C109B", "#6E1099", "#700F97", "#720F95", "#750F93", "#770F91", "#790F8F", "#7B0F8D", "#7D0F8B", "#7F0F89", "#820E87", "#840E85", "#860E83", "#880E81", "#8A0E7F", "#8D0E7D", "#8F0E7B", "#910E79", "#930D77", "#950D75", "#970D73", "#9A0D71", "#9C0D6F", "#9E0D6D", "#A00D6B", "#A20D69", "#A50D67", "#A70C64", "#A90C62", "#AB0C60", "#AD0C5E", "#AF0C5C", "#B20C5A", "#B40C58", "#B60C56", "#B80B54", "#BA0B52", "#BD0B50", "#BF0B4E", "#C10B4C", "#C30B4A", "#C50B48", "#C70B46", "#CA0A44", "#CC0A42", "#CE0A40", "#D00A3E", "#D20A3C", "#D50A3A", "#D70A38", "#D90A36", "#DB0934", "#DD0932", "#DF0930", "#E2092E", "#E4092C", "#E6092A", "#E80928", "#EA0926", "#ED0924"] +/* green => red */ var colorGradient = ["#429C27", "#439A26", "#449926", "#469726", "#479626", "#489525", "#4A9325", "#4B9225", "#4D9025", "#4E8F25", "#4F8E24", "#518C24", "#528B24", "#548924", "#558824", "#568723", "#588523", "#598423", "#5B8223", "#5C8122", "#5D8022", "#5F7E22", "#607D22", "#627B22", "#637A21", "#647921", "#667721", "#677621", "#697421", "#6A7320", "#6B7220", "#6D7020", "#6E6F20", "#706E20", "#716C1F", "#726B1F", "#74691F", "#75681F", "#76671E", "#78651E", "#79641E", "#7B621E", "#7C611E", "#7D601D", "#7F5E1D", "#805D1D", "#825B1D", "#835A1D", "#84591C", "#86571C", "#87561C", "#89541C", "#8A531B", "#8B521B", "#8D501B", "#8E4F1B", "#904D1B", "#914C1A", "#924B1A", "#94491A", "#95481A", "#97461A", "#984519", "#994419", "#9B4219", "#9C4119", "#9E4019", "#9F3E18", "#A03D18", "#A23B18", "#A33A18", "#A43917", "#A63717", "#A73617", "#A93417", "#AA3317", "#AB3216", "#AD3016", "#AE2F16", "#B02D16", "#B12C16", "#B22B15", "#B42915", "#B52815", "#B72615", "#B82514", "#B92414", "#BB2214", "#BC2114", "#BE1F14", "#BF1E13", "#C01D13", "#C21B13", "#C31A13", "#C51813", "#C61712", "#C71612", "#C91412", "#CA1312", "#CC1212"] + editor.setOption("extraKeys", extraKeys); diff --git a/neth/main.cpp b/neth/main.cpp index 7ce64cba5..a6e661d2e 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include #include diff --git a/rlp/main.cpp b/rlp/main.cpp index 5f2f7f358..3924f9c44 100644 --- a/rlp/main.cpp +++ b/rlp/main.cpp @@ -25,7 +25,7 @@ #include "../test/JsonSpiritHeaders.h" #include #include -#include +#include using namespace std; using namespace dev; namespace js = json_spirit; diff --git a/test/deprecated/main.cpp b/test/deprecated/main.cpp index 6ec8885b3..47e96f337 100644 --- a/test/deprecated/main.cpp +++ b/test/deprecated/main.cpp @@ -20,10 +20,6 @@ * Main test functions. */ -#include -#include "TrieHash.h" -#include "MemTrie.h" - #include int trieTest(); diff --git a/test/libdevcrypto/MemTrie.cpp b/test/libdevcrypto/MemTrie.cpp index ab5a13b60..4507d1d80 100644 --- a/test/libdevcrypto/MemTrie.cpp +++ b/test/libdevcrypto/MemTrie.cpp @@ -21,8 +21,8 @@ #include "MemTrie.h" -#include -#include +#include +#include #include using namespace std; using namespace dev; diff --git a/test/libdevcrypto/crypto.cpp b/test/libdevcrypto/crypto.cpp index 88ff98965..497887145 100644 --- a/test/libdevcrypto/crypto.cpp +++ b/test/libdevcrypto/crypto.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include @@ -45,13 +45,19 @@ static CryptoPP::OID s_curveOID(CryptoPP::ASN1::secp256k1()); static CryptoPP::DL_GroupParameters_EC s_params(s_curveOID); static CryptoPP::DL_GroupParameters_EC::EllipticCurve s_curve(s_params.GetCurve()); -BOOST_AUTO_TEST_CASE(emptySHA3Types) +BOOST_AUTO_TEST_CASE(sha3general) { - h256 emptyListSHA3(fromHex("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")); - BOOST_REQUIRE_EQUAL(emptyListSHA3, EmptyListSHA3); + BOOST_REQUIRE_EQUAL(sha3(""), h256("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); + BOOST_REQUIRE_EQUAL(sha3("hello"), h256("1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8")); +} +BOOST_AUTO_TEST_CASE(emptySHA3Types) +{ h256 emptySHA3(fromHex("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); BOOST_REQUIRE_EQUAL(emptySHA3, EmptySHA3); + + h256 emptyListSHA3(fromHex("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")); + BOOST_REQUIRE_EQUAL(emptyListSHA3, EmptyListSHA3); } BOOST_AUTO_TEST_CASE(cryptopp_patch) @@ -805,7 +811,7 @@ int cryptoTest() std::string hmsg = sha3(t.rlp(false), false); cout << "SHA256(RLP(TX w/o SIG)): 0x" << toHex(hmsg) << endl; - bytes privkey = sha3Bytes("123"); + bytes privkey = sha3("123").asBytes(); { bytes pubkey(65); diff --git a/test/libdevcrypto/hexPrefix.cpp b/test/libdevcrypto/hexPrefix.cpp index c72f24535..223f1ac7b 100644 --- a/test/libdevcrypto/hexPrefix.cpp +++ b/test/libdevcrypto/hexPrefix.cpp @@ -27,7 +27,7 @@ #include "../JsonSpiritHeaders.h" #include #include -#include +#include #include "../TestHelper.h" using namespace std; diff --git a/test/libdevcrypto/trie.cpp b/test/libdevcrypto/trie.cpp index ecfc515aa..b5d8662dc 100644 --- a/test/libdevcrypto/trie.cpp +++ b/test/libdevcrypto/trie.cpp @@ -27,8 +27,8 @@ #include "../JsonSpiritHeaders.h" #include -#include -#include +#include +#include #include "MemTrie.h" #include "../TestHelper.h" @@ -294,15 +294,25 @@ BOOST_AUTO_TEST_CASE(trie_tests_ordered) } } -inline h256 stringMapHash256(StringMap const& _s) +h256 stringMapHash256(StringMap const& _s) { - return hash256(_s); + BytesMap bytesMap; + for (auto const& _v: _s) + bytesMap.insert(std::make_pair(bytes(_v.first.begin(), _v.first.end()), bytes(_v.second.begin(), _v.second.end()))); + return hash256(bytesMap); +} + +bytes stringMapRlp256(StringMap const& _s) +{ + BytesMap bytesMap; + for (auto const& _v: _s) + bytesMap.insert(std::make_pair(bytes(_v.first.begin(), _v.first.end()), bytes(_v.second.begin(), _v.second.end()))); + return rlp256(bytesMap); } BOOST_AUTO_TEST_CASE(moreTrieTests) { cnote << "Testing Trie more..."; -#if 0 // More tests... { MemoryDB m; @@ -311,7 +321,7 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) cout << t; cout << m; cout << t.root() << endl; - cout << hash256(StringMap()) << endl; + cout << stringMapHash256(StringMap()) << endl; t.insert(string("tesz"), string("test")); cout << t; @@ -336,7 +346,7 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) t.remove(string("test")); cout << m; cout << t.root() << endl; - cout << hash256(StringMap()) << endl; + cout << stringMapHash256(StringMap()) << endl; } { MemoryDB m; @@ -348,20 +358,23 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) cout << m; cout << t.root() << endl; cout << stringMapHash256({{"b", "B"}, {"a", "A"}}) << endl; - cout << RLP(rlp256({{"b", "B"}, {"a", "A"}})) << endl; + bytes r(stringMapRlp256({{"b", "B"}, {"a", "A"}})); + cout << RLP(r) << endl; } { MemTrie t; t.insert("dog", "puppy"); cout << hex << t.hash256() << endl; - cout << RLP(t.rlp()) << endl; + bytes r(t.rlp()); + cout << RLP(r) << endl; } { MemTrie t; t.insert("bed", "d"); t.insert("be", "e"); cout << hex << t.hash256() << endl; - cout << RLP(t.rlp()) << endl; + bytes r(t.rlp()); + cout << RLP(r) << endl; } { cout << hex << stringMapHash256({{"dog", "puppy"}, {"doe", "reindeer"}}) << endl; @@ -369,10 +382,10 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) t.insert("dog", "puppy"); t.insert("doe", "reindeer"); cout << hex << t.hash256() << endl; - cout << RLP(t.rlp()) << endl; + bytes r(t.rlp()); + cout << RLP(r) << endl; cout << toHex(t.rlp()) << endl; } -#endif { MemoryDB m; EnforceRefs r(m, true); @@ -387,16 +400,16 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) t.insert(a, b); s[a] = b; - /*cout << endl << "-------------------------------" << endl; + cout << endl << "-------------------------------" << endl; cout << a << " -> " << b << endl; cout << d; cout << m; cout << d.root() << endl; - cout << hash256(s) << endl;*/ + cout << stringMapHash256(s) << endl; BOOST_REQUIRE(d.check(true)); - BOOST_REQUIRE_EQUAL(t.hash256(), hash256(s)); - BOOST_REQUIRE_EQUAL(d.root(), hash256(s)); + BOOST_REQUIRE_EQUAL(t.hash256(), stringMapHash256(s)); + BOOST_REQUIRE_EQUAL(d.root(), stringMapHash256(s)); for (auto const& i: s) { (void)i; @@ -421,8 +434,8 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) BOOST_REQUIRE(d.check(true)); BOOST_REQUIRE(t.at(a).empty()); BOOST_REQUIRE(d.at(string(a)).empty()); - BOOST_REQUIRE_EQUAL(t.hash256(), hash256(s)); - BOOST_REQUIRE_EQUAL(d.root(), hash256(s)); + BOOST_REQUIRE_EQUAL(t.hash256(), stringMapHash256(s)); + BOOST_REQUIRE_EQUAL(d.root(), stringMapHash256(s)); for (auto const& i: s) { (void)i; @@ -493,7 +506,6 @@ BOOST_AUTO_TEST_CASE(trieLowerBound) BOOST_AUTO_TEST_CASE(trieStess) { cnote << "Stress-testing Trie..."; - if (0) { MemoryDB m; MemoryDB dm; @@ -512,8 +524,8 @@ BOOST_AUTO_TEST_CASE(trieStess) m[k] = v; t.insert(k, v); d.insert(k, v); - BOOST_REQUIRE_EQUAL(hash256(m), t.hash256()); - BOOST_REQUIRE_EQUAL(hash256(m), d.root()); + BOOST_REQUIRE_EQUAL(stringMapHash256(m), t.hash256()); + BOOST_REQUIRE_EQUAL(stringMapHash256(m), d.root()); BOOST_REQUIRE(d.check(true)); } while (!m.empty()) @@ -557,8 +569,8 @@ BOOST_AUTO_TEST_CASE(trieStess) cwarn << "Good?" << d2.root(); } BOOST_REQUIRE(d.check(true)); - BOOST_REQUIRE_EQUAL(hash256(m), t.hash256()); - BOOST_REQUIRE_EQUAL(hash256(m), d.root()); + BOOST_REQUIRE_EQUAL(stringMapHash256(m), t.hash256()); + BOOST_REQUIRE_EQUAL(stringMapHash256(m), d.root()); } } } diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index 191b94cc3..4e98b4036 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -21,7 +21,7 @@ */ #include -#include +#include #include #include #include diff --git a/test/libevm/vm.cpp b/test/libevm/vm.cpp index 10670bfe3..bda751af4 100644 --- a/test/libevm/vm.cpp +++ b/test/libevm/vm.cpp @@ -44,13 +44,10 @@ h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpF return na; } -bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256& io_gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride, Address _codeAddressOverride) +bool FakeExtVM::call(CallParameters& _p) { - Transaction t(_value, gasPrice, io_gas, _receiveAddress, _data.toVector()); + Transaction t(_p.value, gasPrice, _p.gas, _p.receiveAddress, _p.data.toVector()); callcreates.push_back(t); - (void)_out; - (void)_myAddressOverride; - (void)_codeAddressOverride; return true; } diff --git a/test/libevm/vm.h b/test/libevm/vm.h index dff89d98d..18fa1ca25 100644 --- a/test/libevm/vm.h +++ b/test/libevm/vm.h @@ -59,7 +59,7 @@ public: virtual void suicide(Address _a) override { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); } virtual bytes const& codeAt(Address _a) override { return std::get<3>(addresses[_a]); } virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::OnOpFunc const&) override; - virtual bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256& io_gas, bytesRef _out, eth::OnOpFunc const&, Address, Address) override; + virtual bool call(eth::CallParameters&) override; void setTransaction(Address _caller, u256 _value, u256 _gasPrice, bytes const& _data); void setContract(Address _myAddress, u256 _myBalance, u256 _myNonce, std::map const& _storage, bytes const& _code); void set(Address _a, u256 _myBalance, u256 _myNonce, std::map const& _storage, bytes const& _code); diff --git a/test/libp2p/rlpx.cpp b/test/libp2p/rlpx.cpp index 6a86652fb..620ddd952 100644 --- a/test/libp2p/rlpx.cpp +++ b/test/libp2p/rlpx.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 6713382fa..90ce20d26 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include using namespace std; @@ -1501,9 +1501,7 @@ BOOST_AUTO_TEST_CASE(sha256) compileAndRun(sourceCode); auto f = [&](u256 const& _input) -> u256 { - h256 ret; - dev::sha256(dev::ref(toBigEndian(_input)), bytesRef(&ret[0], 32)); - return ret; + return dev::sha256(dev::ref(toBigEndian(_input))); }; testSolidityAgainstCpp("a(bytes32)", f, u256(4)); testSolidityAgainstCpp("a(bytes32)", f, u256(5)); @@ -1520,9 +1518,7 @@ BOOST_AUTO_TEST_CASE(ripemd) compileAndRun(sourceCode); auto f = [&](u256 const& _input) -> u256 { - h256 ret; - dev::ripemd160(dev::ref(toBigEndian(_input)), bytesRef(&ret[0], 32)); - return u256(ret); + return h256(dev::ripemd160(h256(_input).ref()), h256::AlignLeft); // This should be aligned right. i guess it's fixed elsewhere? }; testSolidityAgainstCpp("a(bytes32)", f, u256(4)); testSolidityAgainstCpp("a(bytes32)", f, u256(5)); diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 4ec7b8bda..c52bbf9de 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include #include diff --git a/third/MainWin.cpp b/third/MainWin.cpp index 12625ffbc..3cfc016e3 100644 --- a/third/MainWin.cpp +++ b/third/MainWin.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include