diff --git a/CMakeLists.txt b/CMakeLists.txt index b3773861e..ff8732156 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -354,6 +354,7 @@ if (TOOLS) add_subdirectory(rlp) add_subdirectory(abi) + add_subdirectory(ethminer) add_subdirectory(eth) if("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug") diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index eb2431f10..05aecdb72 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -217,6 +218,7 @@ Main::Main(QWidget *parent) : Main::~Main() { + m_httpConnector->StopListening(); writeSettings(); // Must do this here since otherwise m_ethereum'll be deleted (and therefore clearWatches() called by the destructor) // *after* the client is dead. @@ -520,82 +522,11 @@ QString Main::pretty(dev::Address _a) const return fromRaw(n); } -template inline string toBase36(FixedHash const& _h) -{ - static char const* c_alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - typename FixedHash::Arith a = _h; - std::string ret; - for (; a > 0; a /= 36) - ret = c_alphabet[(unsigned)a % 36] + ret; - return ret; -} - -template inline FixedHash fromBase36(string const& _h) -{ - typename FixedHash::Arith ret = 0; - for (char c: _h) - ret = ret * 36 + (c < 'A' ? c - '0' : (c - 'A' + 10)); - return ret; -} - -static string iban(std::string _c, std::string _d) -{ - boost::to_upper(_c); - boost::to_upper(_d); - auto totStr = _d + _c + "00"; - bigint tot = 0; - for (char x: totStr) - if (x >= 'A') - tot = tot * 100 + x - 'A' + 10; - else - tot = tot * 10 + x - '0'; - unsigned check = (unsigned)(u256)(98 - tot % 97); - ostringstream out; - out << _c << setfill('0') << setw(2) << check << _d; - return out.str(); -} - -static std::pair fromIban(std::string _iban) -{ - if (_iban.size() < 4) - return std::make_pair(string(), string()); - boost::to_upper(_iban); - std::string c = _iban.substr(0, 2); - std::string d = _iban.substr(4); - if (iban(c, d) != _iban) - return std::make_pair(string(), string()); - return make_pair(c, d); -} - -static string directICAP(dev::Address _a) -{ - if (!!_a[0]) - return string(); - std::string d = toBase36(_a); - while (d.size() < 30) - d = "0" + d; - return iban("XE", d); -} - -static Address fromICAP(std::string const& _s) -{ - std::string country; - std::string data; - std::tie(country, data) = fromIban(_s); - if (country.empty()) - return Address(); - if (country == "XE" && data.size() == 30) - // Direct ICAP - return fromBase36(data); - // TODO: Indirect ICAP - return Address(); -} - QString Main::render(dev::Address _a) const { QString p = pretty(_a); if (!_a[0]) - p += QString(p.isEmpty() ? "" : " ") + QString::fromStdString(directICAP(_a)); + p += QString(p.isEmpty() ? "" : " ") + QString::fromStdString(ICAP(_a).encoded()); if (!p.isEmpty()) return p + " (" + QString::fromStdString(_a.abridged()) + ")"; return QString::fromStdString(_a.abridged()); @@ -639,7 +570,7 @@ Address Main::fromString(QString const& _n) const return Address(); } } - else if (Address a = fromICAP(_n.toStdString())) + else if (Address a = ICAP::decoded(_n.toStdString()).direct()) return a; else return Address(); diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index d781ad2b3..416bb3095 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -8,7 +8,6 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_RELEASE") - set(ETH_SHARED 1) if (PROFILING) set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}") @@ -31,7 +30,6 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG") - set(ETH_SHARED 1) if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++ -fcolor-diagnostics -Qunused-arguments -DBOOST_ASIO_HAS_CLANG_LIBCXX") @@ -55,8 +53,10 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # stack size 16MB set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ignore:4099,4075 /STACK:16777216") # windows likes static - set(ETH_STATIC 1) - + if (NOT ETH_STATIC) + message("Forcing static linkage for MSVC.") + set(ETH_STATIC 1) + endif () else () message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.") endif () @@ -72,3 +72,8 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA endif () endif () +if(ETH_STATIC) + set(BUILD_SHARED_LIBS OFF) +else() + set(BUILD_SHARED_LIBS ON) +endif(ETH_STATIC) diff --git a/ethminer/CMakeLists.txt b/ethminer/CMakeLists.txt new file mode 100644 index 000000000..cd8919bb2 --- /dev/null +++ b/ethminer/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) + +aux_source_directory(. SRC_LIST) + +include_directories(BEFORE ..) +include_directories(${Boost_INCLUDE_DIRS}) +include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) + +set(EXECUTABLE ethminer) + +file(GLOB HEADERS "*.h") + +add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) + +add_dependencies(${EXECUTABLE} BuildInfo.h) + +target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES}) + +if (READLINE_FOUND) + target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES}) +endif() + +if (JSONRPC) + target_link_libraries(${EXECUTABLE} web3jsonrpc) + target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_CLIENT_LIBRARIES}) + target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES}) + if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) + eth_copy_dlls(${EXECUTABLE} CURL_DLLS) + endif() +endif() + +target_link_libraries(${EXECUTABLE} webthree) +target_link_libraries(${EXECUTABLE} ethash) + +if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) + eth_copy_dlls("${EXECUTABLE}" MHD_DLLS) +endif() + +install( TARGETS ${EXECUTABLE} DESTINATION bin ) + diff --git a/ethminer/Farm.h b/ethminer/Farm.h new file mode 100644 index 000000000..ae2ef5a7d --- /dev/null +++ b/ethminer/Farm.h @@ -0,0 +1,39 @@ +/** + * This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY! + */ + +#ifndef JSONRPC_CPP_STUB_FARM_H_ +#define JSONRPC_CPP_STUB_FARM_H_ + +#include + +class Farm : public jsonrpc::Client +{ + public: + Farm(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {} + + Json::Value eth_getWork() throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p = Json::nullValue; + Json::Value result = this->CallMethod("eth_getWork",p); + if (result.isArray()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } + bool eth_submitWork(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + p.append(param2); + p.append(param3); + Json::Value result = this->CallMethod("eth_submitWork",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } +}; + +#endif //JSONRPC_CPP_STUB_FARM_H_ diff --git a/ethminer/PhoneHome.h b/ethminer/PhoneHome.h new file mode 100644 index 000000000..ae6091cc2 --- /dev/null +++ b/ethminer/PhoneHome.h @@ -0,0 +1,28 @@ +/** + * This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY! + */ + +#ifndef JSONRPC_CPP_STUB_PHONEHOME_H_ +#define JSONRPC_CPP_STUB_PHONEHOME_H_ + +#include + +class PhoneHome : public jsonrpc::Client +{ + public: + PhoneHome(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {} + + int report_benchmark(const std::string& param1, int param2) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + p.append(param2); + Json::Value result = this->CallMethod("report_benchmark",p); + if (result.isInt()) + return result.asInt(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } +}; + +#endif //JSONRPC_CPP_STUB_PHONEHOME_H_ diff --git a/ethminer/farm.json b/ethminer/farm.json new file mode 100644 index 000000000..1f4142d00 --- /dev/null +++ b/ethminer/farm.json @@ -0,0 +1,4 @@ +[ + { "name": "eth_getWork", "params": [], "order": [], "returns": []}, + { "name": "eth_submitWork", "params": ["", "", ""], "order": [], "returns": true} +] diff --git a/ethminer/main.cpp b/ethminer/main.cpp new file mode 100644 index 000000000..19324945f --- /dev/null +++ b/ethminer/main.cpp @@ -0,0 +1,483 @@ +/* + 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 main.cpp + * @author Gav Wood + * @date 2014 + * Ethereum client. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if ETH_JSONRPC || !ETH_TRUE +#include +#include +#include +#endif +#include "BuildInfo.h" +#if ETH_JSONRPC || !ETH_TRUE +#include "PhoneHome.h" +#include "Farm.h" +#endif +using namespace std; +using namespace dev; +using namespace dev::p2p; +using namespace dev::eth; +using namespace boost::algorithm; +using dev::eth::Instruction; + +#undef RETURN + +bool isTrue(std::string const& _m) +{ + return _m == "on" || _m == "yes" || _m == "true" || _m == "1"; +} + +bool isFalse(std::string const& _m) +{ + return _m == "off" || _m == "no" || _m == "false" || _m == "0"; +} + +void help() +{ + cout + << "Usage ethminer [OPTIONS]" << endl + << "Options:" << endl << endl +#if ETH_JSONRPC || !ETH_TRUE + << "Work farming mode:" << endl + << " -F,--farm Put into mining farm mode with the work server at URL (default: http://127.0.0.1:8080)" << endl + << " --farm-recheck Leave n ms between checks for changed work (default: 500)." << endl +#endif + << "Benchmarking mode:" << endl + << " -M,--benchmark Benchmark for mining and exit; use with --cpu and --opencl." << endl + << " --benchmark-warmup Set the duration of warmup for the benchmark tests (default: 3)." << endl + << " --benchmark-trial Set the duration for each trial for the benchmark tests (default: 3)." << endl + << " --benchmark-trials Set the duration of warmup for the benchmark tests (default: 5)." << endl +#if ETH_JSONRPC || !ETH_TRUE + << " --phone-home When benchmarking, publish results (default: on)" << endl +#endif + << "DAG creation mode:" << endl + << " -D,--create-dag Create the DAG in preparation for mining on given block and exit." << endl + << "General Options:" << endl + << " -C,--cpu When mining, use the CPU." << endl + << " -G,--opencl When mining use the GPU via OpenCL." << endl + << " --opencl-platform When mining using -G/--opencl use OpenCL platform n (default: 0)." << endl + << " --opencl-device When mining using -G/--opencl use OpenCL device n (default: 0)." << endl + << " -t, --mining-threads Limit number of CPU/GPU miners to n (default: use everything available on selected platform)" << endl + << " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl + << " -V,--version Show the version and exit." << endl + << " -h,--help Show this help message and exit." << endl + ; + exit(0); +} + +string credits() +{ + std::ostringstream cout; + cout + << "Ethereum (++) " << dev::Version << endl + << " Code by Gav Wood et al, (c) 2013, 2014, 2015." << endl + << " Based on a design by Vitalik Buterin." << endl << endl; + return cout.str(); +} + +void version() +{ + cout << "eth version " << dev::Version << endl; + cout << "eth network protocol version: " << dev::eth::c_protocolVersion << endl; + cout << "Client database version: " << dev::eth::c_databaseVersion << endl; + cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl; + exit(0); +} + +void doInitDAG(unsigned _n) +{ + BlockInfo bi; + bi.number = _n; + cout << "Initializing DAG for epoch beginning #" << (bi.number / 30000 * 30000) << " (seedhash " << bi.seedHash().abridged() << "). This will take a while." << endl; + Ethash::prep(bi); + exit(0); +} + +enum class OperationMode +{ + DAGInit, + Benchmark, + Farm +}; + +enum class MinerType +{ + CPU, + GPU +}; + +void doBenchmark(MinerType _m, bool _phoneHome, unsigned _warmupDuration = 15, unsigned _trialDuration = 3, unsigned _trials = 5) +{ + BlockInfo genesis = CanonBlockChain::genesis(); + genesis.difficulty = 1 << 18; + cdebug << genesis.boundary(); + + GenericFarm f; + f.onSolutionFound([&](ProofOfWork::Solution) { return false; }); + + string platformInfo = _m == MinerType::CPU ? ProofOfWork::CPUMiner::platformInfo() : _m == MinerType::GPU ? ProofOfWork::GPUMiner::platformInfo() : ""; + cout << "Benchmarking on platform: " << platformInfo << endl; + + cout << "Preparing DAG..." << endl; + Ethash::prep(genesis); + + genesis.difficulty = u256(1) << 63; + genesis.noteDirty(); + f.setWork(genesis); + if (_m == MinerType::CPU) + f.startCPU(); + else if (_m == MinerType::GPU) + f.startGPU(); + + map results; + uint64_t mean = 0; + uint64_t innerMean = 0; + for (unsigned i = 0; i <= _trials; ++i) + { + if (!i) + cout << "Warming up..." << endl; + else + cout << "Trial " << i << "... " << flush; + this_thread::sleep_for(chrono::seconds(i ? _trialDuration : _warmupDuration)); + + auto mp = f.miningProgress(); + f.resetMiningProgress(); + if (!i) + continue; + auto rate = mp.rate(); + + cout << rate << endl; + results[rate] = mp; + mean += rate; + if (i > 1 && i < 5) + innerMean += rate; + } + f.stop(); + cout << "min/mean/max: " << results.begin()->second.rate() << "/" << (mean / _trials) << "/" << results.rbegin()->second.rate() << " H/s" << endl; + cout << "inner mean: " << (innerMean / (_trials - 2)) << " H/s" << endl; + + (void)_phoneHome; +#if ETH_JSONRPC || !ETH_TRUE + if (_phoneHome) + { + cout << "Phoning home to find world ranking..." << endl; + jsonrpc::HttpClient client("http://gav.ethdev.com:3000/benchmark"); + PhoneHome rpc(client); + try + { + unsigned ranking = rpc.report_benchmark(platformInfo, innerMean); + cout << "Ranked: " << ranking << " of all benchmarks." << endl; + } + catch (...) + { + cout << "Error phoning home. ET is sad." << endl; + } + } +#endif + exit(0); +} + +struct HappyChannel: public LogChannel { static const char* name() { return ":-D"; } static const int verbosity = 1; }; +struct SadChannel: public LogChannel { static const char* name() { return ":-("; } static const int verbosity = 1; }; + +void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) +{ + (void)_m; + (void)_remote; + (void)_recheckPeriod; +#if ETH_JSONRPC || !ETH_TRUE + jsonrpc::HttpClient client(_remote); + Farm rpc(client); + GenericFarm f; + if (_m == MinerType::CPU) + f.startCPU(); + else if (_m == MinerType::GPU) + f.startGPU(); + + ProofOfWork::WorkPackage current; + while (true) + try + { + bool completed = false; + ProofOfWork::Solution solution; + f.onSolutionFound([&](ProofOfWork::Solution sol) + { + solution = sol; + return completed = true; + }); + for (unsigned i = 0; !completed; ++i) + { + if (current) + cnote << "Mining on PoWhash" << current.headerHash << ": " << f.miningProgress(); + else + cnote << "Getting work package..."; + Json::Value v = rpc.eth_getWork(); + h256 hh(v[0].asString()); + if (hh != current.headerHash) + { + current.headerHash = hh; + current.seedHash = h256(v[1].asString()); + current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight); + cnote << "Got work package:" << current.headerHash << " < " << current.boundary; + f.setWork(current); + } + this_thread::sleep_for(chrono::milliseconds(_recheckPeriod)); + } + cnote << "Solution found; submitting [" << solution.nonce << "," << current.headerHash << "," << solution.mixHash << "] to" << _remote << "..."; + bool ok = rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash)); + if (ok) + clog(HappyChannel) << "Submitted and accepted."; + else + clog(SadChannel) << "Not accepted."; + current.reset(); + } + catch (jsonrpc::JsonRpcException&) + { + for (auto i = 3; --i; this_thread::sleep_for(chrono::seconds(1))) + cerr << "JSON-RPC problem. Probably couldn't connect. Retrying in " << i << "... \r"; + cerr << endl; + } +#endif + exit(0); +} + +int main(int argc, char** argv) +{ + // Init defaults + Defaults::get(); + + /// Operating mode. + OperationMode mode = OperationMode::Farm; + + /// Mining options + MinerType minerType = MinerType::CPU; + unsigned openclPlatform = 0; + unsigned openclDevice = 0; + unsigned miningThreads = UINT_MAX; + + /// DAG initialisation param. + unsigned initDAG = 0; + + /// Benchmarking params + bool phoneHome = true; + unsigned benchmarkWarmup = 3; + unsigned benchmarkTrial = 3; + unsigned benchmarkTrials = 5; + + /// Farm params + string farmURL = "http://127.0.0.1:8080"; + unsigned farmRecheckPeriod = 500; + + for (int i = 1; i < argc; ++i) + { + string arg = argv[i]; + if ((arg == "-F" || arg == "--farm") && i + 1 < argc) + { + mode = OperationMode::Farm; + farmURL = argv[++i]; + } + else if (arg == "--farm-recheck" && i + 1 < argc) + try { + farmRecheckPeriod = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; + } + else if (arg == "--opencl-platform" && i + 1 < argc) + try { + openclPlatform = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; + } + else if (arg == "--opencl-device" && i + 1 < argc) + try { + openclDevice = stol(argv[++i]); + miningThreads = 1; + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; + } + else if (arg == "--phone-home" && i + 1 < argc) + { + string m = argv[++i]; + if (isTrue(m)) + phoneHome = true; + else if (isFalse(m)) + phoneHome = false; + else + { + cerr << "Bad " << arg << " option: " << m << endl; + return -1; + } + } + else if (arg == "--benchmark-warmup" && i + 1 < argc) + try { + benchmarkWarmup = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; + } + else if (arg == "--benchmark-trial" && i + 1 < argc) + try { + benchmarkTrial = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; + } + else if (arg == "--benchmark-trials" && i + 1 < argc) + try { + benchmarkTrials = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; + } + else if (arg == "-C" || arg == "--cpu") + minerType = MinerType::CPU; + else if (arg == "-G" || arg == "--opencl") + minerType = MinerType::GPU; + else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) + { + string m = boost::to_lower_copy(string(argv[++i])); + mode = OperationMode::DAGInit; + try + { + initDAG = stol(m); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << m << endl; + return -1; + } + } + else if ((arg == "-w" || arg == "--check-pow") && i + 4 < argc) + { + string m; + try + { + BlockInfo bi; + m = boost::to_lower_copy(string(argv[++i])); + h256 powHash(m); + m = boost::to_lower_copy(string(argv[++i])); + h256 seedHash; + if (m.size() == 64 || m.size() == 66) + seedHash = h256(m); + else + seedHash = EthashAux::seedHash(stol(m)); + m = boost::to_lower_copy(string(argv[++i])); + bi.difficulty = u256(m); + auto boundary = bi.boundary(); + m = boost::to_lower_copy(string(argv[++i])); + bi.nonce = h64(m); + auto r = EthashAux::eval(seedHash, powHash, bi.nonce); + bool valid = r.value < boundary; + cout << (valid ? "VALID :-)" : "INVALID :-(") << endl; + cout << r.value << (valid ? " < " : " >= ") << boundary << endl; + cout << " where " << boundary << " = 2^256 / " << bi.difficulty << endl; + cout << " and " << r.value << " = ethash(" << powHash << ", " << bi.nonce << ")" << endl; + cout << " with seed as " << seedHash << endl; + if (valid) + cout << "(mixHash = " << r.mixHash << ")" << endl; + cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(seedHash)->data()) << endl; + exit(0); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << m << endl; + return -1; + } + } + else if (arg == "-M" || arg == "--benchmark") + mode = OperationMode::Benchmark; + else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc) + { + try { + miningThreads = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; + } + } + else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc) + g_logVerbosity = atoi(argv[++i]); + else if (arg == "-h" || arg == "--help") + help(); + else if (arg == "-V" || arg == "--version") + version(); + else + { + cerr << "Invalid argument: " << arg << endl; + exit(-1); + } + } + + if (minerType == MinerType::CPU) + ProofOfWork::CPUMiner::setNumInstances(miningThreads); + else if (minerType == MinerType::GPU) + { + ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform); + ProofOfWork::GPUMiner::setDefaultDevice(openclDevice); + ProofOfWork::GPUMiner::setNumInstances(miningThreads); + } + + if (mode == OperationMode::DAGInit) + doInitDAG(initDAG); + + if (mode == OperationMode::Benchmark) + doBenchmark(minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials); + + if (mode == OperationMode::Farm) + doFarm(minerType, farmURL, farmRecheckPeriod); + + return 0; +} + diff --git a/ethminer/phonehome.json b/ethminer/phonehome.json new file mode 100644 index 000000000..0bed56d72 --- /dev/null +++ b/ethminer/phonehome.json @@ -0,0 +1,3 @@ +[ + { "name": "report_benchmark", "params": [ "", 0 ], "order": [], "returns": 0 } +] diff --git a/evmjit/libevmjit-cpp/CMakeLists.txt b/evmjit/libevmjit-cpp/CMakeLists.txt index add132f2a..5b4dbb9c8 100644 --- a/evmjit/libevmjit-cpp/CMakeLists.txt +++ b/evmjit/libevmjit-cpp/CMakeLists.txt @@ -15,7 +15,7 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # add PIC for archive endif() -add_library(${TARGET_NAME} ${SOURCES}) +add_library(${TARGET_NAME} STATIC ${SOURCES}) set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "libs") include_directories(../..) diff --git a/libdevcore/Base64.h b/libdevcore/Base64.h index 1e9c88429..8ff10cff0 100644 --- a/libdevcore/Base64.h +++ b/libdevcore/Base64.h @@ -30,7 +30,8 @@ #include #include -#include +#include "Common.h" +#include "FixedHash.h" namespace dev { @@ -38,4 +39,22 @@ namespace dev std::string toBase64(bytesConstRef _in); bytes fromBase64(std::string const& _in); +template inline std::string toBase36(FixedHash const& _h) +{ + static char const* c_alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + typename FixedHash::Arith a = _h; + std::string ret; + for (; a > 0; a /= 36) + ret = c_alphabet[(unsigned)a % 36] + ret; + return ret; +} + +template inline FixedHash fromBase36(std::string const& _h) +{ + typename FixedHash::Arith ret = 0; + for (char c: _h) + ret = ret * 36 + (c < 'A' ? c - '0' : (c - 'A' + 10)); + return ret; +} + } diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index ec3472605..4a96d7ec5 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -20,11 +20,7 @@ set(EXECUTABLE devcore) file(GLOB HEADERS "*.h") -if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES}) diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index aab20c0b8..295dd257a 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -17,11 +17,7 @@ include_directories(${LEVELDB_INCLUDE_DIRS}) set(EXECUTABLE devcrypto) file(GLOB HEADERS "*.h") -if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index 322ac80ea..1adb8428e 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -24,11 +24,7 @@ set(EXECUTABLE ethcore) file(GLOB HEADERS "*.h") -if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ethash) target_link_libraries(${EXECUTABLE} devcrypto) diff --git a/libethcore/Common.cpp b/libethcore/Common.cpp index 56120471b..01c8cfa4c 100644 --- a/libethcore/Common.cpp +++ b/libethcore/Common.cpp @@ -21,6 +21,8 @@ #include "Common.h" #include +#include +#include #include #include "Exceptions.h" #include "ProofOfWork.h" @@ -100,4 +102,5 @@ std::string formatBalance(bigint const& _b) return ret.str(); } -}} +} +} diff --git a/libethcore/Common.h b/libethcore/Common.h index 199057f91..84459c6bf 100644 --- a/libethcore/Common.h +++ b/libethcore/Common.h @@ -23,6 +23,8 @@ #pragma once +#include +#include #include #include #include diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 66dc953b7..e932fced4 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -121,7 +121,7 @@ bool Ethash::verify(BlockInfo const& _header) return slow; } -unsigned Ethash::CPUMiner::s_numInstances = 1; +unsigned Ethash::CPUMiner::s_numInstances = 0; void Ethash::CPUMiner::workLoop() { @@ -266,7 +266,7 @@ private: unsigned Ethash::GPUMiner::s_platformId = 0; unsigned Ethash::GPUMiner::s_deviceId = 0; -unsigned Ethash::GPUMiner::s_numInstances = 1; +unsigned Ethash::GPUMiner::s_numInstances = 0; Ethash::GPUMiner::GPUMiner(ConstructionInfo const& _ci): Miner(_ci), diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 44064cde6..19a96f550 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -64,7 +64,7 @@ ethash_params EthashAux::params(unsigned _n) h256 EthashAux::seedHash(unsigned _number) { unsigned epoch = _number / ETHASH_EPOCH_LENGTH; - RecursiveGuard l(get()->x_this); + Guard l(get()->x_epochs); if (epoch >= get()->m_seedHashes.size()) { h256 ret; @@ -87,7 +87,7 @@ h256 EthashAux::seedHash(unsigned _number) ethash_params EthashAux::params(h256 const& _seedHash) { - RecursiveGuard l(get()->x_this); + Guard l(get()->x_epochs); unsigned epoch = 0; try { diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index 40dd88e16..0389697f5 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -78,6 +78,8 @@ private: std::map> m_lights; std::map> m_fulls; FullType m_lastUsedFull; + + Mutex x_epochs; std::map m_epochs; h256s m_seedHashes; }; diff --git a/libethcore/ICAP.cpp b/libethcore/ICAP.cpp new file mode 100644 index 000000000..d4c4f9c46 --- /dev/null +++ b/libethcore/ICAP.cpp @@ -0,0 +1,157 @@ +/* + 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 ICAP.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "ICAP.h" +#include +#include +#include +#include "Exceptions.h" +using namespace std; +using namespace dev; +using namespace dev::eth; + +namespace dev +{ +namespace eth +{ + +string ICAP::iban(std::string _c, std::string _d) +{ + boost::to_upper(_c); + boost::to_upper(_d); + auto totStr = _d + _c + "00"; + bigint tot = 0; + for (char x: totStr) + if (x >= 'A') + tot = tot * 100 + x - 'A' + 10; + else + tot = tot * 10 + x - '0'; + unsigned check = (unsigned)(u256)(98 - tot % 97); + ostringstream out; + out << _c << setfill('0') << setw(2) << check << _d; + return out.str(); +} + +std::pair ICAP::fromIBAN(std::string _iban) +{ + if (_iban.size() < 4) + return std::make_pair(string(), string()); + boost::to_upper(_iban); + std::string c = _iban.substr(0, 2); + std::string d = _iban.substr(4); + if (iban(c, d) != _iban) + return std::make_pair(string(), string()); + return make_pair(c, d); +} + +ICAP ICAP::decoded(std::string const& _encoded) +{ + ICAP ret; + std::string country; + std::string data; + std::tie(country, data) = fromIBAN(_encoded); + if (country != "XE") + throw InvalidICAP(); + if (data.size() == 30) + { + ret.m_type = Direct; + // Direct ICAP + ret.m_direct = fromBase36(data); + } + else if (data.size() == 16) + { + ret.m_type = Indirect; + ret.m_asset = data.substr(0, 3); + if (ret.m_asset == "XET") + { + ret.m_institution = data.substr(3, 4); + ret.m_client = data.substr(7); + } + else if (ret.m_asset == "ETH") + ret.m_client = data.substr(4); + else + throw InvalidICAP(); + } + else + throw InvalidICAP(); + + return ret; +} + +std::string ICAP::encoded() const +{ + if (m_type == Direct) + { + if (!!m_direct[0]) + return string(); + std::string d = toBase36(m_direct); + while (d.size() < 30) + d = "0" + d; + return iban("XE", d); + } + else if (m_type == Indirect) + { + if ( + m_asset.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || + m_institution.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || + m_client.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || + m_asset.size() != 3 + ) + throw InvalidICAP(); + if (boost::to_upper_copy(m_asset) == "XET") + { + if (m_institution.size() != 4 || m_client.size() != 9) + throw InvalidICAP(); + } + else if (boost::to_upper_copy(m_asset) == "ETH") + { + if (m_client.size() != 13) + throw InvalidICAP(); + } + else + throw InvalidICAP(); + return iban("XE", m_asset + m_institution + m_client); + } + else + throw InvalidICAP(); +} + +Address ICAP::lookup(std::function const& _call, Address const& _reg) const +{ + (void)_call; + (void)_reg; + if (m_asset == "XET") + { + // TODO + throw InterfaceNotSupported("ICAP::lookup(), XET asset"); + } + else if (m_asset == "ETH") + { + // TODO +// return resolve(m_institution + "/" + m_client).primary(); + throw InterfaceNotSupported("ICAP::lookup(), ETH asset"); + } + else + throw InterfaceNotSupported("ICAP::lookup(), non XET asset"); +} + +} +} diff --git a/libethcore/ICAP.h b/libethcore/ICAP.h new file mode 100644 index 000000000..fd5db2f0a --- /dev/null +++ b/libethcore/ICAP.h @@ -0,0 +1,106 @@ +/* + 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 ICAP.h + * @author Gav Wood + * @date 2014 + * + * Ethereum-specific data structures & algorithms. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include "Common.h" + +namespace dev +{ +namespace eth +{ + +struct InvalidICAP: virtual public dev::Exception {}; + +static const std::string EmptyString; + +/** + * @brief Encapsulation of an ICAP address. + * Can be encoded, decoded, looked-up and inspected. + */ +class ICAP +{ +public: + /// Construct null ICAP object. + ICAP() = default; + /// Construct a direct ICAP object for given target address. Must have a zero first byte. + ICAP(Address const& _target): m_direct(_target) {} + /// Construct an indirect ICAP object for given target name. + ICAP(std::string const& _target): m_client(_target), m_asset("ETH") {} + /// Construct an indirect ICAP object for given client and institution names. + ICAP(std::string const& _client, std::string const& _inst): m_client(_client), m_institution(_inst), m_asset("XET") {} + /// Construct an indirect ICAP object for given client, institution and asset names. You generally don't want to use this. + ICAP(std::string const& _c, std::string const& _i, std::string const& _a): m_client(_c), m_institution(_i), m_asset(_a) {} + + /// Type of ICAP address. + enum Type + { + Invalid, + Direct, + Indirect + }; + + /// @returns IBAN encoding of client and data. + static std::string iban(std::string _c, std::string _d); + /// @returns Client and data from given IBAN address. + static std::pair fromIBAN(std::string _iban); + + /// @returns the ICAP object for the ICAP address given. + static ICAP decoded(std::string const& _encoded); + + /// @returns the encoded ICAP address. + std::string encoded() const; + /// @returns type of ICAP. + Type type() const { return m_type; } + /// @returns target address. Only valid when type() == Direct. + Address const& direct() const { return m_type == Direct ? m_direct : ZeroAddress; } + /// @returns asset. Only valid when type() == Indirect. + std::string const& asset() const { return m_type == Indirect ? m_asset : EmptyString; } + /// @returns target name. Only valid when type() == Indirect and asset() == "ETH". + std::string const& target() const { return m_type == Indirect && m_asset == "ETH" ? m_client : EmptyString; } + /// @returns institution name. Only valid when type() == Indirect and asset() == "XET". + std::string const& institution() const { return m_type == Indirect && m_asset == "XET" ? m_institution : EmptyString; } + /// @returns client name. Only valid when type() == Indirect and asset() == "XET". + std::string const& client() const { return m_type == Indirect && m_asset == "XET" ? m_client : EmptyString; } + /// @returns target address. Always valid, but requires the Registry address and a function to make calls. + Address address(std::function const& _call, Address const& _reg) const { return m_type == Direct ? direct() : m_type == Indirect ? lookup(_call, _reg) : Address(); } + + /// @returns target address. Looks up through the given Registry and call function. Only valid when type() == Indirect. + Address lookup(std::function const& _call, Address const& _reg) const; + +private: + Type m_type = Invalid; + Address m_direct; + std::string m_client; + std::string m_institution; + std::string m_asset; +}; + + +} +} diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index 1d0911909..8203402cb 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -19,11 +19,7 @@ set(EXECUTABLE ethereum) file(GLOB HEADERS "*.h") -if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} lll) diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index 411c8bd99..975af53a5 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -105,7 +105,7 @@ Address const& Transaction::safeSender() const noexcept catch (...) { cwarn << "safeSender() did throw an exception: " << boost::current_exception_diagnostic_information(); - return NullAddress; + return ZeroAddress; } } diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index faf5ea07a..0ce536b78 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -97,8 +97,6 @@ struct ExecutionResult std::ostream& operator<<(std::ostream& _out, ExecutionResult const& _er); -static const Address NullAddress; - /// Encodes a transaction, ready to be exported to or freshly imported from RLP. class Transaction { diff --git a/libethereumx/CMakeLists.txt b/libethereumx/CMakeLists.txt index d8d3021f0..42b551c64 100644 --- a/libethereumx/CMakeLists.txt +++ b/libethereumx/CMakeLists.txt @@ -11,11 +11,7 @@ set(EXECUTABLE ethereumx) file(GLOB HEADERS "*.h") -if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index b747acf6f..f6f0c01e4 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -20,11 +20,7 @@ set(EXECUTABLE evm) file(GLOB HEADERS "*.h") -if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} devcrypto) diff --git a/libevmcore/CMakeLists.txt b/libevmcore/CMakeLists.txt index 83a4e115c..2da76882e 100644 --- a/libevmcore/CMakeLists.txt +++ b/libevmcore/CMakeLists.txt @@ -19,11 +19,7 @@ set(EXECUTABLE evmcore) file(GLOB HEADERS "*.h") -if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcrypto) diff --git a/liblll/CMakeLists.txt b/liblll/CMakeLists.txt index b865d4afe..d3f465f37 100644 --- a/liblll/CMakeLists.txt +++ b/liblll/CMakeLists.txt @@ -19,11 +19,7 @@ set(EXECUTABLE lll) file(GLOB HEADERS "*.h") -if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) diff --git a/libnatspec/CMakeLists.txt b/libnatspec/CMakeLists.txt index d8d9d46ec..806fb4e0d 100644 --- a/libnatspec/CMakeLists.txt +++ b/libnatspec/CMakeLists.txt @@ -22,11 +22,7 @@ file(GLOB HEADERS "*.h") qt5_add_resources(NATSPECQRC natspec.qrc) -if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${RESOURCE_ADDED} ${SRC_LIST} ${HEADERS} ${NATSPECQRC}) -else() - add_library(${EXECUTABLE} SHARED ${RESOURCE_ADDED} ${SRC_LIST} ${HEADERS} ${NATSPECQRC}) -endif() +add_library(${EXECUTABLE} ${RESOURCE_ADDED} ${SRC_LIST} ${HEADERS} ${NATSPECQRC}) target_link_libraries(${EXECUTABLE} Qt5::Core) target_link_libraries(${EXECUTABLE} Qt5::Qml) diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index eb19d25fe..24a3116b6 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -25,11 +25,7 @@ set(EXECUTABLE p2p) file(GLOB HEADERS "*.h") -if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) if (MINIUPNPC_FOUND) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) diff --git a/libserpent/CMakeLists.txt b/libserpent/CMakeLists.txt index 71385b223..305e96a8a 100644 --- a/libserpent/CMakeLists.txt +++ b/libserpent/CMakeLists.txt @@ -17,11 +17,7 @@ set(EXECUTABLE serpent) file(GLOB HEADERS "*.h") -if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} evmcore) diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 0abd188c1..3d31331a4 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -19,11 +19,7 @@ set(EXECUTABLE solidity) file(GLOB HEADERS "*.h") -if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} evmcore) diff --git a/libtestutils/CMakeLists.txt b/libtestutils/CMakeLists.txt index 3ac4f34f8..882ee6b1b 100644 --- a/libtestutils/CMakeLists.txt +++ b/libtestutils/CMakeLists.txt @@ -23,11 +23,7 @@ if (NOT JSONRPC) list(REMOVE_ITEM HEADERS "./FixedWebThreeServer.h") endif() -if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 7b47a3f47..d7670fa2a 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -20,11 +20,7 @@ set(EXECUTABLE web3jsonrpc) file(GLOB HEADERS "*.h") -if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else () - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif () +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 7b124a6f2..0fd7e3eb2 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -194,7 +194,16 @@ static dev::eth::LogFilter toLogFilter(Json::Value const& _json) // commented to } if (!_json["topics"].empty()) for (unsigned i = 0; i < _json["topics"].size(); i++) - filter.topic(i, jsToFixed<32>(_json["topics"][i].asString())); + { + if (_json["topics"][i].isArray()) + { + for (auto t: _json["topics"][i]) + if (!t.isNull()) + filter.topic(i, jsToFixed<32>(t.asString())); + } + else if (!_json["topics"][i].isNull()) // if it is anything else then string, it should and will fail + filter.topic(i, jsToFixed<32>(_json["topics"][i].asString())); + } return filter; } @@ -224,7 +233,16 @@ static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m, if (!_json["topics"].empty()) for (auto i: _json["topics"]) - bt.shift(jsToBytes(i.asString())); + { + if (i.isArray()) + { + for (auto j: i) + if (!j.isNull()) + bt.shift(jsToBytes(j.asString())); + } + else if (!i.isNull()) // if it is anything else then string, it should and will fail + bt.shift(jsToBytes(i.asString())); + } return _m.seal(_from, bt, ttl, workToProve); } diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index ac97a9e2b..b72945cab 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -19,11 +19,7 @@ set(EXECUTABLE webthree) file(GLOB HEADERS "*.h") -if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt index 40e764863..6ee935a90 100644 --- a/libwhisper/CMakeLists.txt +++ b/libwhisper/CMakeLists.txt @@ -19,11 +19,7 @@ set(EXECUTABLE whisper) file(GLOB HEADERS "*.h") -if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index c14d26935..357ce88b9 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -249,7 +249,6 @@ void CodeModel::runCompilationJob(int _jobId) { if (_jobId != m_backgroundJobId) return; //obsolete job - ContractMap result; solidity::CompilerStack cs(true); try { @@ -260,40 +259,7 @@ void CodeModel::runCompilationJob(int _jobId) cs.addSource(c.first.toStdString(), c.second.toStdString()); } cs.compile(false); - - { - Guard pl(x_pendingContracts); - Guard l(x_contractMap); - for (std::string n: cs.getContractNames()) - { - if (c_predefinedContracts.count(n) != 0) - continue; - QString name = QString::fromStdString(n); - ContractDefinition const& contractDefinition = cs.getContractDefinition(n); - if (!contractDefinition.isFullyImplemented()) - continue; - QString sourceName = QString::fromStdString(*contractDefinition.getLocation().sourceName); - auto sourceIter = m_pendingContracts.find(sourceName); - QString source = sourceIter != m_pendingContracts.end() ? sourceIter->second : QString(); - CompiledContract* contract = new CompiledContract(cs, name, source); - QQmlEngine::setObjectOwnership(contract, QQmlEngine::CppOwnership); - result[name] = contract; - CompiledContract* prevContract = nullptr; - for (ContractMap::const_iterator c = m_contractMap.cbegin(); c != m_contractMap.cend(); ++c) - if (c.value()->documentId() == contract->documentId()) - prevContract = c.value(); - if (prevContract != nullptr && prevContract->contractInterface() != result[name]->contractInterface()) - emit contractInterfaceChanged(name); - if (prevContract == nullptr) - emit newContractCompiled(name); - else if (prevContract->contract()->name() != name) - emit contractRenamed(contract->documentId(), prevContract->contract()->name(), name); - } - releaseContracts(); - m_contractMap.swap(result); - emit codeChanged(); - emit compilationComplete(); - } + collectContracts(cs); } catch (dev::Exception const& _exception) { @@ -307,8 +273,7 @@ void CodeModel::runCompilationJob(int _jobId) sourceName = QString::fromStdString(*location->sourceName); if (!sourceName.isEmpty()) if (CompiledContract* contract = contractByDocumentId(sourceName)) - //substitute the location to match our contract names - message = message.replace(sourceName, contract->contract()->name()); + message = message.replace(sourceName, contract->contract()->name()); //substitute the location to match our contract names } compilationError(message, sourceName); } @@ -316,6 +281,55 @@ void CodeModel::runCompilationJob(int _jobId) emit stateChanged(); } +void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs) +{ + Guard pl(x_pendingContracts); + Guard l(x_contractMap); + ContractMap result; + for (std::string n: _cs.getContractNames()) + { + if (c_predefinedContracts.count(n) != 0) + continue; + QString name = QString::fromStdString(n); + ContractDefinition const& contractDefinition = _cs.getContractDefinition(n); + if (!contractDefinition.isFullyImplemented()) + continue; + QString sourceName = QString::fromStdString(*contractDefinition.getLocation().sourceName); + auto sourceIter = m_pendingContracts.find(sourceName); + QString source = sourceIter != m_pendingContracts.end() ? sourceIter->second : QString(); + CompiledContract* contract = new CompiledContract(_cs, name, source); + QQmlEngine::setObjectOwnership(contract, QQmlEngine::CppOwnership); + result[name] = contract; + CompiledContract* prevContract = nullptr; + // find previous contract by name + for (ContractMap::const_iterator c = m_contractMap.cbegin(); c != m_contractMap.cend(); ++c) + if (c.value()->contract()->name() == contract->contract()->name()) + prevContract = c.value(); + + // if not found, try by documentId + if (!prevContract) + { + for (ContractMap::const_iterator c = m_contractMap.cbegin(); c != m_contractMap.cend(); ++c) + if (c.value()->documentId() == contract->documentId()) + { + //make sure there are no other contracts in the same source, otherwise it is not a rename + if (!std::any_of(result.begin(),result.end(), [=](ContractMap::const_iterator::value_type _v) { return _v != contract && _v->documentId() == contract->documentId(); })) + prevContract = c.value(); + } + } + if (prevContract != nullptr && prevContract->contractInterface() != result[name]->contractInterface()) + emit contractInterfaceChanged(name); + if (prevContract == nullptr) + emit newContractCompiled(name); + else if (prevContract->contract()->name() != name) + emit contractRenamed(contract->documentId(), prevContract->contract()->name(), name); + } + releaseContracts(); + m_contractMap.swap(result); + emit codeChanged(); + emit compilationComplete(); +} + bool CodeModel::hasContract() const { Guard l(x_contractMap); diff --git a/mix/CodeModel.h b/mix/CodeModel.h index 6fb914118..199e1dee2 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -117,7 +117,7 @@ private: friend class CodeModel; }; -using ContractMap = QHash; +using ContractMap = QMap; //needs to be sorted /// Code compilation model. Compiles contracts in background an provides compiled contract data class CodeModel: public QObject @@ -182,6 +182,7 @@ private: void runCompilationJob(int _jobId); void stop(); void releaseContracts(); + void collectContracts(solidity::CompilerStack const& _cs); std::atomic m_compiling; mutable dev::Mutex x_contractMap; diff --git a/mix/HttpServer.cpp b/mix/HttpServer.cpp index 968580907..fa09f51d0 100644 --- a/mix/HttpServer.cpp +++ b/mix/HttpServer.cpp @@ -145,16 +145,23 @@ void HttpServer::readClient() if (socket->canReadLine()) { QString hdr = QString(socket->readLine()); + QVariantMap headers; if (hdr.startsWith("POST") || hdr.startsWith("GET")) { QUrl url(hdr.split(' ')[1]); QString l; do + { l = socket->readLine(); + //collect headers + int colon = l.indexOf(':'); + if (colon > 0) + headers[l.left(colon).trimmed().toLower()] = l.right(l.length() - colon - 1).trimmed(); + } while (!(l.isEmpty() || l == "\r" || l == "\r\n")); QString content = socket->readAll(); - std::unique_ptr request(new HttpRequest(this, url, content)); + std::unique_ptr request(new HttpRequest(this, std::move(url), std::move(content), std::move(headers))); clientConnected(request.get()); QTextStream os(socket); os.setAutoDetectUnicode(true); diff --git a/mix/HttpServer.h b/mix/HttpServer.h index 8a1e4553a..50a345747 100644 --- a/mix/HttpServer.h +++ b/mix/HttpServer.h @@ -25,6 +25,7 @@ #include #include #include +#include #include namespace dev @@ -40,10 +41,12 @@ class HttpRequest: public QObject Q_PROPERTY(QUrl url MEMBER m_url CONSTANT) /// Request body contents Q_PROPERTY(QString content MEMBER m_content CONSTANT) + /// Request HTTP headers + Q_PROPERTY(QVariantMap headers MEMBER m_headers CONSTANT) private: - HttpRequest(QObject* _parent, QUrl const& _url, QString const& _content): - QObject(_parent), m_url(_url), m_content(_content) + HttpRequest(QObject* _parent, QUrl&& _url, QString&& _content, QVariantMap&& _headers): + QObject(_parent), m_url(_url), m_content(_content), m_headers(_headers) { } @@ -60,6 +63,7 @@ private: QString m_content; QString m_response; QString m_responseContentType; + QVariantMap m_headers; friend class HttpServer; }; diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index b95dc5cf3..0b7d22f3f 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -42,6 +42,18 @@ namespace mix Secret const c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); u256 const c_mixGenesisDifficulty = 131072; //TODO: make it lower for Mix somehow +namespace +{ + +struct MixPow //dummy POW +{ + typedef int Solution; + static void assignResult(int, BlockInfo const&) {} + static bool verify(BlockInfo const&) { return true; } +}; + +} + bytes MixBlockChain::createGenesisBlock(h256 _stateRoot) { RLPStream block(3); @@ -250,22 +262,8 @@ void MixClient::mine() { WriteGuard l(x_state); m_state.commitToMine(bc()); - m_state.completeMine(Ethash::Solution()); - bc().import(m_state.blockData(), m_stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce); - /* - GenericFarm f; - bool completed = false; - f.onSolutionFound([&](ProofOfWork::Solution sol) - { - return completed = m_state.completeMine(sol); - }); - f.setWork(m_state.info()); - f.startCPU(); - while (!completed) - this_thread::sleep_for(chrono::milliseconds(20)); - - bc().import(m_state.blockData(), m_stateDB); - */ + m_state.completeMine(0); + bc().import(m_state.blockData(), m_state.db(), ImportRequirements::Default & ~ImportRequirements::ValidNonce); m_state.sync(bc()); m_startState = m_state; h256Set changed { dev::eth::PendingChangedFilter, dev::eth::ChainChangedFilter }; diff --git a/mix/qml/QBoolTypeView.qml b/mix/qml/QBoolTypeView.qml index 9911d4549..c68b4e133 100644 --- a/mix/qml/QBoolTypeView.qml +++ b/mix/qml/QBoolTypeView.qml @@ -6,6 +6,7 @@ Item id: editRoot property string value property string defaultValue + property alias readOnly: !boolCombo.enabled height: 20 width: 150 diff --git a/mix/qml/QHashTypeView.qml b/mix/qml/QHashTypeView.qml index a097c22dd..ee5848b3a 100644 --- a/mix/qml/QHashTypeView.qml +++ b/mix/qml/QHashTypeView.qml @@ -3,6 +3,7 @@ import QtQuick 2.0 Item { property alias value: textinput.text + property alias readOnly: textinput.readOnly id: editRoot height: 20 width: 150 diff --git a/mix/qml/QIntTypeView.qml b/mix/qml/QIntTypeView.qml index 8adb46846..eacef74e8 100644 --- a/mix/qml/QIntTypeView.qml +++ b/mix/qml/QIntTypeView.qml @@ -1,12 +1,12 @@ import QtQuick 2.0 -import QtQuick.Layouts 1.1 Item { property alias value: textinput.text + property alias readOnly: textinput.readOnly id: editRoot height: 20 - width: 150 + width: readOnly ? textinput.implicitWidth : 150 SourceSansProBold { @@ -22,12 +22,7 @@ Item anchors.fill: parent font.family: boldFont.name clip: true - MouseArea { - id: mouseArea - anchors.fill: parent - hoverEnabled: true - onClicked: textinput.forceActiveFocus() - } + selectByMouse: true } } } diff --git a/mix/qml/QStringTypeView.qml b/mix/qml/QStringTypeView.qml index ffbde734c..080c49282 100644 --- a/mix/qml/QStringTypeView.qml +++ b/mix/qml/QStringTypeView.qml @@ -3,9 +3,10 @@ import QtQuick 2.0 Item { property alias value: textinput.text + property alias readOnly: textinput.readOnly id: editRoot height: 20 - width: 150 + width: readOnly ? textinput.implicitWidth : 150 SourceSansProBold { @@ -22,12 +23,7 @@ Item anchors.fill: parent wrapMode: Text.WrapAnywhere font.family: boldFont.name - MouseArea { - id: mouseArea - anchors.fill: parent - hoverEnabled: true - onClicked: textinput.forceActiveFocus() - } + selectByMouse: true } } } diff --git a/mix/qml/StructView.qml b/mix/qml/StructView.qml index 798a634fa..4df9ace67 100644 --- a/mix/qml/StructView.qml +++ b/mix/qml/StructView.qml @@ -12,7 +12,7 @@ Column property int transactionIndex property string context Layout.fillWidth: true - spacing: 10 + spacing: 0 Repeater { id: repeater @@ -22,7 +22,7 @@ Column RowLayout { id: row - height: 30 + (members[index].type.category === QSolidityType.Struct ? (20 * members[index].type.members.length) : 0) + height: 20 + (members[index].type.category === QSolidityType.Struct ? (20 * members[index].type.members.length) : 0) Layout.fillWidth: true DefaultLabel { height: 20 @@ -32,12 +32,14 @@ Column } DefaultLabel { + height: 20 id: nameLabel text: modelData.name anchors.verticalCenter: parent.verticalCenter } DefaultLabel { + height: 20 id: equalLabel text: "=" anchors.verticalCenter: parent.verticalCenter @@ -45,6 +47,7 @@ Column Loader { id: typeLoader + height: 20 anchors.verticalCenter: parent.verticalCenter sourceComponent: { @@ -69,10 +72,10 @@ Column var ptype = members[index].type; var pname = members[index].name; var vals = value; + item.readOnly = context === "variable"; if (ptype.category === QSolidityType.Address) { item.value = getValue(); - item.readOnly = context === "variable"; if (context === "parameter") { var dec = modelData.type.name.split(" "); @@ -119,6 +122,10 @@ Column vals[pname] = item.value; valueChanged(); }); + + var newWidth = nameLabel.width + typeLabel.width + item.width + 108; + if (root.width < newWidth) + root.width = newWidth; } function getValue() diff --git a/mix/qml/VariablesView.qml b/mix/qml/VariablesView.qml index b04739274..6603bd24e 100644 --- a/mix/qml/VariablesView.qml +++ b/mix/qml/VariablesView.qml @@ -18,15 +18,15 @@ DebugInfoList property alias members: typeLoader.members; property alias value: typeLoader.value; anchors.fill: parent - StructView - { - id: typeLoader - members: [] - value: {} - Layout.preferredWidth: parent.width - context: "variable" - width: parent.width - } + anchors.rightMargin: 8 + StructView + { + id: typeLoader + members: [] + value: {} + context: "variable" + width:parent.width + } } } diff --git a/mix/qml/WebPreview.qml b/mix/qml/WebPreview.qml index 4f7451680..e4d0b61a5 100644 --- a/mix/qml/WebPreview.qml +++ b/mix/qml/WebPreview.qml @@ -17,6 +17,7 @@ Item { property string webContent; //for testing signal javaScriptMessage(var _level, string _sourceId, var _lineNb, string _content) signal webContentReady + signal ready function setPreviewUrl(url) { if (!initialized) @@ -184,8 +185,10 @@ Item { content = fileIo.readFile(doc.path); } - if (documentName === urlInput.text.replace(httpServer.url + "/", "")) { - //root page, inject deployment script + var accept = _request.headers["accept"]; + if (accept && accept.indexOf("text/html") >= 0 && !_request.headers["http_x_requested_with"]) + { + //navigate to page request, inject deployment script content = "\n" + content; _request.setResponseContentType("text/html"); } @@ -325,6 +328,7 @@ Item { webView.runJavaScript("init(\"" + httpServer.url + "/rpc/\")"); if (pendingPageUrl) setPreviewUrl(pendingPageUrl); + ready(); } } } diff --git a/mix/test/TestService.cpp b/mix/test/TestService.cpp index 75f69a9eb..487dac880 100644 --- a/mix/test/TestService.cpp +++ b/mix/test/TestService.cpp @@ -20,8 +20,9 @@ * Ethereum IDE client. */ -#include #include "TestService.h" +#include +#include #include #include #include @@ -177,7 +178,6 @@ void TestService::setTargetWindow(QObject* _window) window->requestActivate(); } - QWindow* TestService::eventWindow(QObject* _item) { QQuickItem* item = qobject_cast(_item); @@ -201,5 +201,10 @@ QWindow* TestService::eventWindow(QObject* _item) return 0; } +QString TestService::createUuid() const +{ + return QUuid::createUuid().toString(); +} + } } diff --git a/mix/test/TestService.h b/mix/test/TestService.h index be65cf558..55f02479f 100644 --- a/mix/test/TestService.h +++ b/mix/test/TestService.h @@ -41,6 +41,7 @@ public: void setTargetWindow(QObject* _window); public slots: + QString createUuid() const; bool waitForSignal(QObject* _item, QString _signalName, int _timeout); bool waitForRendering(QObject* _item, int timeout); bool keyPress(QObject* _item, int _key, int _modifiers, int _delay); diff --git a/mix/test/qml/TestMain.qml b/mix/test/qml/TestMain.qml index c0d179707..829364a99 100644 --- a/mix/test/qml/TestMain.qml +++ b/mix/test/qml/TestMain.qml @@ -41,7 +41,7 @@ TestCase var projectDlg = mainApplication.projectModel.newProjectDialog; wait(30); projectDlg.projectTitle = "TestProject"; - projectDlg.pathFieldText = "/tmp/MixTest"; //TODO: get platform temp path + projectDlg.pathFieldText = "/tmp/MixTest/" + ts.createUuid(); //TODO: get platform temp path projectDlg.acceptAndClose(); wait(1); if (!ts.waitForSignal(mainApplication.codeModel, "compilationComplete()", 5000)) @@ -82,6 +82,16 @@ TestCase ts.keyPressChar(mainApplication, "S", Qt.ControlModifier, 200); //Ctrl+S } + function createHtml(name, c) + { + mainApplication.projectModel.newHtmlFile(); + ts.waitForSignal(mainApplication.mainContent.codeEditor, "loadComplete()", 5000); + var doc = mainApplication.projectModel.listModel.get(mainApplication.projectModel.listModel.count - 1); + mainApplication.projectModel.renameDocument(doc.documentId, name); + mainApplication.mainContent.codeEditor.getEditor(doc.documentId).setText(c); + ts.keyPressChar(mainApplication, "S", Qt.ControlModifier, 200); //Ctrl+S + } + function clickElement(el, x, y) { if (el.contentItem) @@ -101,5 +111,7 @@ TestCase function test_miner_selectMiner() { TestMiner.test_selectMiner(); } function test_miner_mine() { TestMiner.test_mine(); } function test_project_contractRename() { TestProject.test_contractRename(); } + function test_project_multipleWebPages() { TestProject.test_multipleWebPages(); } + function test_project_multipleContractsSameFile() { TestProject.test_multipleContractsSameFile(); } } diff --git a/mix/test/qml/js/TestDebugger.js b/mix/test/qml/js/TestDebugger.js index 2300dd390..4933136ff 100644 --- a/mix/test/qml/js/TestDebugger.js +++ b/mix/test/qml/js/TestDebugger.js @@ -123,8 +123,7 @@ function test_arrayParametersAndStorage() transactionDialog.acceptAndClose(); mainApplication.projectModel.stateDialog.acceptAndClose(); mainApplication.mainContent.startQuickDebugging(); - if (!ts.waitForSignal(mainApplication.clientModel, "debugDataReady(QObject*)", 5000)) - fail("Error running transaction"); + waitForExecution(); //debug setM mainApplication.clientModel.debugRecord(3); mainApplication.mainContent.rightPane.debugSlider.value = mainApplication.mainContent.rightPane.debugSlider.maximumValue; @@ -158,8 +157,7 @@ function test_solidityDebugging() "}"); mainApplication.mainContent.startQuickDebugging(); - if (!ts.waitForSignal(mainApplication.clientModel, "debugDataReady(QObject*)", 5000)) - fail("Error running transaction"); + waitForExecution(); tryCompare(mainApplication.mainContent.rightPane.debugSlider, "maximumValue", 20); tryCompare(mainApplication.mainContent.rightPane.debugSlider, "value", 0); @@ -191,8 +189,7 @@ function test_vmDebugging() "}"); mainApplication.mainContent.startQuickDebugging(); - if (!ts.waitForSignal(mainApplication.clientModel, "debugDataReady(QObject*)", 5000)) - fail("Error running transaction"); + waitForExecution(); mainApplication.mainContent.rightPane.assemblyMode = !mainApplication.mainContent.rightPane.assemblyMode; tryCompare(mainApplication.mainContent.rightPane.debugSlider, "maximumValue", 41); @@ -225,12 +222,7 @@ function test_ctrTypeAsParam() " }\r " + "}"); mainApplication.projectModel.stateListModel.editState(0); //C1 ctor already added - mainApplication.projectModel.stateDialog.model.addTransaction(); var transactionDialog = mainApplication.projectModel.stateDialog.transactionDialog; - ts.waitForRendering(transactionDialog, 3000); - transactionDialog.selectContract("C2"); - transactionDialog.selectFunction("C2"); - transactionDialog.acceptAndClose(); mainApplication.projectModel.stateDialog.model.addTransaction(); transactionDialog = mainApplication.projectModel.stateDialog.transactionDialog; ts.waitForRendering(transactionDialog, 3000); @@ -241,8 +233,7 @@ function test_ctrTypeAsParam() transactionDialog.acceptAndClose(); mainApplication.projectModel.stateDialog.acceptAndClose(); mainApplication.mainContent.startQuickDebugging(); - if (!ts.waitForSignal(mainApplication.clientModel, "debugDataReady(QObject*)", 5000)) - fail("Error running transaction"); + waitForExecution(); tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(4), "returned", "(159)"); } diff --git a/mix/test/qml/js/TestMiner.js b/mix/test/qml/js/TestMiner.js index 9d98c9f24..3824f988e 100644 --- a/mix/test/qml/js/TestMiner.js +++ b/mix/test/qml/js/TestMiner.js @@ -25,6 +25,10 @@ function test_mine() waitForExecution(); mainApplication.clientModel.mine(); waitForMining(); + wait(1000); //there need to be at least 1 sec diff between block times + mainApplication.clientModel.mine(); + waitForMining(); tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(3), "contract", " - Block - "); + tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(4), "contract", " - Block - "); } diff --git a/mix/test/qml/js/TestProject.js b/mix/test/qml/js/TestProject.js index 0d20ec9a8..49b5ea51f 100644 --- a/mix/test/qml/js/TestProject.js +++ b/mix/test/qml/js/TestProject.js @@ -16,3 +16,31 @@ function test_contractRename() transactionDialog.close(); mainApplication.projectModel.stateDialog.close(); } + +function test_multipleWebPages() +{ + newProject(); + editHtml("page1"); + createHtml("page1.html", "
Fail
"); + clickElement(mainApplication.mainContent.webView.webView, 1, 1); + ts.typeString("\t\r"); + wait(300); //TODO: use a signal in qt 5.5 + mainApplication.mainContent.webView.getContent(); + ts.waitForSignal(mainApplication.mainContent.webView, "webContentReady()", 5000); + var body = mainApplication.mainContent.webView.webContent; + verify(body.indexOf("
OK
") != -1, "Web content not updated") +} + +function test_multipleContractsSameFile() +{ + newProject(); + editContract( + "contract C1 {}\r" + + "contract C2 {}\r" + + "contract C3 {}\r"); + waitForExecution(); + tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel, "count", 5); + tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(2), "contract", "C1"); + tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(3), "contract", "C2"); + tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(4), "contract", "C3"); +} diff --git a/secp256k1/CMakeLists.txt b/secp256k1/CMakeLists.txt index ab67b86a0..d66144fec 100644 --- a/secp256k1/CMakeLists.txt +++ b/secp256k1/CMakeLists.txt @@ -14,22 +14,14 @@ file(GLOB HEADERS "*.h") if (APPLE OR UNIX) - if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c field_5x52_asm.asm) - else() - add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c field_5x52_asm.asm) - endif() + add_library(${EXECUTABLE} ${EXECUTABLE}.c field_5x52_asm.asm) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") target_link_libraries(${EXECUTABLE} ${GMP_LIBRARIES}) elseif (CMAKE_COMPILER_IS_MINGW) include_directories(${Boost_INCLUDE_DIRS}) - if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c field_5x52_asm.asm) - else() - add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c field_5x52_asm.asm) - endif() + add_library(${EXECUTABLE} ${EXECUTABLE}.c field_5x52_asm.asm) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -W -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") target_link_libraries(${EXECUTABLE} ${GMP_LIBRARIES}) @@ -37,11 +29,7 @@ else() include_directories(${Boost_INCLUDE_DIRS}) - if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c) - else() - add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c) - endif() + add_library(${EXECUTABLE} ${EXECUTABLE}.c) # /TP - compile project as cpp project set_target_properties(${EXECUTABLE} PROPERTIES COMPILE_FLAGS "/TP /wd4244") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_NUM_BOOST -DUSE_FIELD_10X26 -DUSE_FIELD_INV_BUILTIN") diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt index 177823963..c8e74ed71 100644 --- a/solc/CMakeLists.txt +++ b/solc/CMakeLists.txt @@ -19,9 +19,5 @@ target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) -if (ETH_STATIC) - add_library(soljson STATIC jsonCompiler.cpp ${HEADERS}) -else() - add_library(soljson SHARED jsonCompiler.cpp ${HEADERS}) -endif() +add_library(soljson jsonCompiler.cpp ${HEADERS}) target_link_libraries(soljson solidity) diff --git a/solc/docker_emscripten/Dockerfile b/solc/docker_emscripten/Dockerfile index 1ad1875d7..23a0caba9 100644 --- a/solc/docker_emscripten/Dockerfile +++ b/solc/docker_emscripten/Dockerfile @@ -63,9 +63,9 @@ RUN git remote add -f solidityjs https://github.com/chriseth/cpp-ethereum # NOTE that we only get the latest commit of that branch RUN git cherry-pick solidityjs/solidity-js RUN emcmake cmake -DETH_STATIC=1 -DSOLIDITY=ON -DGUI=0 -DCMAKE_CXX_COMPILER=/home/user/emsdk_portable/emscripten/master/em++ -DCMAKE_C_COMPILER=/home/user/emsdk_portable/emscripten/master/emcc -RUN emmake make -j 6 soljs +RUN emmake make -j 6 soljson -WORKDIR /home/user/cpp-ethereum/soljs +WORKDIR /home/user/cpp-ethereum/solc # somehow it does not work to pipe out both files -#ENTRYPOINT tar -c soljs.js soljs.js.mem | base64 +#ENTRYPOINT tar -c soljson.js soljson.js.mem | base64