Browse Source

Merge branch 'develop' into web3.js-v3.1

cl-refactor
Marek Kotewicz 10 years ago
parent
commit
07b3d6227b
  1. 1
      CMakeLists.txt
  2. 77
      alethzero/MainWin.cpp
  3. 2
      eth/main.cpp
  4. 41
      ethminer/CMakeLists.txt
  5. 39
      ethminer/Farm.h
  6. 28
      ethminer/PhoneHome.h
  7. 4
      ethminer/farm.json
  8. 483
      ethminer/main.cpp
  9. 3
      ethminer/phonehome.json
  10. 21
      libdevcore/Base64.h
  11. 5
      libethcore/Common.cpp
  12. 2
      libethcore/Common.h
  13. 4
      libethcore/Ethash.cpp
  14. 4
      libethcore/EthashAux.cpp
  15. 2
      libethcore/EthashAux.h
  16. 157
      libethcore/ICAP.cpp
  17. 106
      libethcore/ICAP.h
  18. 2
      libethereum/Transaction.cpp
  19. 2
      libethereum/Transaction.h
  20. 2
      libsolidity/InterfaceHandler.cpp
  21. 22
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  22. 88
      mix/CodeModel.cpp
  23. 3
      mix/CodeModel.h
  24. 4
      mix/ContractCallDataEncoder.cpp
  25. 9
      mix/HttpServer.cpp
  26. 8
      mix/HttpServer.h
  27. 30
      mix/MixClient.cpp
  28. 23
      mix/qml/QAddressView.qml
  29. 2
      mix/qml/StateListModel.qml
  30. 43
      mix/qml/StructView.qml
  31. 4
      mix/qml/TransactionDialog.qml
  32. 2
      mix/qml/VariablesView.qml
  33. 8
      mix/qml/WebPreview.qml
  34. 9
      mix/test/TestService.cpp
  35. 1
      mix/test/TestService.h
  36. 14
      mix/test/qml/TestMain.qml
  37. 17
      mix/test/qml/js/TestDebugger.js
  38. 4
      mix/test/qml/js/TestMiner.js
  39. 28
      mix/test/qml/js/TestProject.js
  40. 3
      solc/CommandLineInterface.cpp
  41. 6
      solc/docker_emscripten/Dockerfile
  42. 12
      test/libsolidity/SolidityInterface.cpp

1
CMakeLists.txt

@ -354,6 +354,7 @@ if (TOOLS)
add_subdirectory(rlp) add_subdirectory(rlp)
add_subdirectory(abi) add_subdirectory(abi)
add_subdirectory(ethminer)
add_subdirectory(eth) add_subdirectory(eth)
if("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug") if("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug")

77
alethzero/MainWin.cpp

@ -46,6 +46,7 @@
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libethcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include <libethcore/EthashAux.h> #include <libethcore/EthashAux.h>
#include <libethcore/ICAP.h>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include <liblll/CodeFragment.h> #include <liblll/CodeFragment.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>
@ -217,6 +218,7 @@ Main::Main(QWidget *parent) :
Main::~Main() Main::~Main()
{ {
m_httpConnector->StopListening();
writeSettings(); writeSettings();
// Must do this here since otherwise m_ethereum'll be deleted (and therefore clearWatches() called by the destructor) // Must do this here since otherwise m_ethereum'll be deleted (and therefore clearWatches() called by the destructor)
// *after* the client is dead. // *after* the client is dead.
@ -520,82 +522,11 @@ QString Main::pretty(dev::Address _a) const
return fromRaw(n); return fromRaw(n);
} }
template <size_t N> inline string toBase36(FixedHash<N> const& _h)
{
static char const* c_alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
typename FixedHash<N>::Arith a = _h;
std::string ret;
for (; a > 0; a /= 36)
ret = c_alphabet[(unsigned)a % 36] + ret;
return ret;
}
template <size_t N> inline FixedHash<N> fromBase36(string const& _h)
{
typename FixedHash<N>::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<string, string> 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<Address::size>(_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<Address::size>(data);
// TODO: Indirect ICAP
return Address();
}
QString Main::render(dev::Address _a) const QString Main::render(dev::Address _a) const
{ {
QString p = pretty(_a); QString p = pretty(_a);
if (!_a[0]) if (!_a[0])
p += QString(p.isEmpty() ? "" : " ") + QString::fromStdString(directICAP(_a)); p += QString(p.isEmpty() ? "" : " ") + QString::fromStdString(ICAP(_a).encoded());
if (!p.isEmpty()) if (!p.isEmpty())
return p + " (" + QString::fromStdString(_a.abridged()) + ")"; return p + " (" + QString::fromStdString(_a.abridged()) + ")";
return QString::fromStdString(_a.abridged()); return QString::fromStdString(_a.abridged());
@ -639,7 +570,7 @@ Address Main::fromString(QString const& _n) const
return Address(); return Address();
} }
} }
else if (Address a = fromICAP(_n.toStdString())) else if (Address a = ICAP::decoded(_n.toStdString()).direct())
return a; return a;
else else
return Address(); return Address();

2
eth/main.cpp

@ -1317,9 +1317,9 @@ int main(int argc, char** argv)
{ {
string hexAddr; string hexAddr;
u256 amount; u256 amount;
int size = hexAddr.length();
iss >> hexAddr >> amount; iss >> hexAddr >> amount;
int size = hexAddr.length();
if (size < 40) if (size < 40)
{ {
if (size > 0) if (size > 0)

41
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 )

39
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 <jsonrpccpp/client.h>
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_

28
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 <jsonrpccpp/client.h>
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_

4
ethminer/farm.json

@ -0,0 +1,4 @@
[
{ "name": "eth_getWork", "params": [], "order": [], "returns": []},
{ "name": "eth_submitWork", "params": ["", "", ""], "order": [], "returns": true}
]

483
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 <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* Ethereum client.
*/
#include <thread>
#include <chrono>
#include <fstream>
#include <iostream>
#include <signal.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/trim_all.hpp>
#include <libdevcrypto/FileSystem.h>
#include <libevmcore/Instruction.h>
#include <libdevcore/StructuredLogger.h>
#include <libethcore/ProofOfWork.h>
#include <libethcore/EthashAux.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
#include <libethereum/All.h>
#include <libwebthree/WebThree.h>
#if ETH_JSONRPC || !ETH_TRUE
#include <libweb3jsonrpc/WebThreeStubServer.h>
#include <jsonrpccpp/server/connectors/httpserver.h>
#include <jsonrpccpp/client/connectors/httpclient.h>
#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 <url> Put into mining farm mode with the work server at URL (default: http://127.0.0.1:8080)" << endl
<< " --farm-recheck <n> 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 <seconds> Set the duration of warmup for the benchmark tests (default: 3)." << endl
<< " --benchmark-trial <seconds> Set the duration for each trial for the benchmark tests (default: 3)." << endl
<< " --benchmark-trials <n> Set the duration of warmup for the benchmark tests (default: 5)." << endl
#if ETH_JSONRPC || !ETH_TRUE
<< " --phone-home <on/off> When benchmarking, publish results (default: on)" << endl
#endif
<< "DAG creation mode:" << endl
<< " -D,--create-dag <number> 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 <n> When mining using -G/--opencl use OpenCL platform n (default: 0)." << endl
<< " --opencl-device <n> When mining using -G/--opencl use OpenCL device n (default: 0)." << endl
<< " -t, --mining-threads <n> 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<Ethash> 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<uint64_t, MiningProgress> 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<Ethash> 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;
}

3
ethminer/phonehome.json

@ -0,0 +1,3 @@
[
{ "name": "report_benchmark", "params": [ "", 0 ], "order": [], "returns": 0 }
]

21
libdevcore/Base64.h

@ -30,7 +30,8 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <libdevcore/Common.h> #include "Common.h"
#include "FixedHash.h"
namespace dev namespace dev
{ {
@ -38,4 +39,22 @@ namespace dev
std::string toBase64(bytesConstRef _in); std::string toBase64(bytesConstRef _in);
bytes fromBase64(std::string const& _in); bytes fromBase64(std::string const& _in);
template <size_t N> inline std::string toBase36(FixedHash<N> const& _h)
{
static char const* c_alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
typename FixedHash<N>::Arith a = _h;
std::string ret;
for (; a > 0; a /= 36)
ret = c_alphabet[(unsigned)a % 36] + ret;
return ret;
}
template <size_t N> inline FixedHash<N> fromBase36(std::string const& _h)
{
typename FixedHash<N>::Arith ret = 0;
for (char c: _h)
ret = ret * 36 + (c < 'A' ? c - '0' : (c - 'A' + 10));
return ret;
}
} }

5
libethcore/Common.cpp

@ -21,6 +21,8 @@
#include "Common.h" #include "Common.h"
#include <random> #include <random>
#include <boost/algorithm/string/case_conv.hpp>
#include <libdevcore/Base64.h>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include "Exceptions.h" #include "Exceptions.h"
#include "ProofOfWork.h" #include "ProofOfWork.h"
@ -100,4 +102,5 @@ std::string formatBalance(bigint const& _b)
return ret.str(); return ret.str();
} }
}} }
}

2
libethcore/Common.h

@ -23,6 +23,8 @@
#pragma once #pragma once
#include <string>
#include <functional>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/FixedHash.h> #include <libdevcore/FixedHash.h>
#include <libdevcrypto/Common.h> #include <libdevcrypto/Common.h>

4
libethcore/Ethash.cpp

@ -121,7 +121,7 @@ bool Ethash::verify(BlockInfo const& _header)
return slow; return slow;
} }
unsigned Ethash::CPUMiner::s_numInstances = 1; unsigned Ethash::CPUMiner::s_numInstances = 0;
void Ethash::CPUMiner::workLoop() void Ethash::CPUMiner::workLoop()
{ {
@ -266,7 +266,7 @@ private:
unsigned Ethash::GPUMiner::s_platformId = 0; unsigned Ethash::GPUMiner::s_platformId = 0;
unsigned Ethash::GPUMiner::s_deviceId = 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): Ethash::GPUMiner::GPUMiner(ConstructionInfo const& _ci):
Miner(_ci), Miner(_ci),

4
libethcore/EthashAux.cpp

@ -64,7 +64,7 @@ ethash_params EthashAux::params(unsigned _n)
h256 EthashAux::seedHash(unsigned _number) h256 EthashAux::seedHash(unsigned _number)
{ {
unsigned epoch = _number / ETHASH_EPOCH_LENGTH; unsigned epoch = _number / ETHASH_EPOCH_LENGTH;
RecursiveGuard l(get()->x_this); Guard l(get()->x_epochs);
if (epoch >= get()->m_seedHashes.size()) if (epoch >= get()->m_seedHashes.size())
{ {
h256 ret; h256 ret;
@ -87,7 +87,7 @@ h256 EthashAux::seedHash(unsigned _number)
ethash_params EthashAux::params(h256 const& _seedHash) ethash_params EthashAux::params(h256 const& _seedHash)
{ {
RecursiveGuard l(get()->x_this); Guard l(get()->x_epochs);
unsigned epoch = 0; unsigned epoch = 0;
try try
{ {

2
libethcore/EthashAux.h

@ -78,6 +78,8 @@ private:
std::map<h256, std::shared_ptr<LightAllocation>> m_lights; std::map<h256, std::shared_ptr<LightAllocation>> m_lights;
std::map<h256, std::weak_ptr<FullAllocation>> m_fulls; std::map<h256, std::weak_ptr<FullAllocation>> m_fulls;
FullType m_lastUsedFull; FullType m_lastUsedFull;
Mutex x_epochs;
std::map<h256, unsigned> m_epochs; std::map<h256, unsigned> m_epochs;
h256s m_seedHashes; h256s m_seedHashes;
}; };

157
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 <http://www.gnu.org/licenses/>.
*/
/** @file ICAP.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "ICAP.h"
#include <boost/algorithm/string/case_conv.hpp>
#include <libdevcore/Base64.h>
#include <libdevcrypto/SHA3.h>
#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<string, string> 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<Address::size>(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<Address::size>(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<bytes(Address, bytes)> 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");
}
}
}

106
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 <http://www.gnu.org/licenses/>.
*/
/** @file ICAP.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*
* Ethereum-specific data structures & algorithms.
*/
#pragma once
#include <string>
#include <functional>
#include <libdevcore/Common.h>
#include <libdevcore/Exceptions.h>
#include <libdevcore/FixedHash.h>
#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<std::string, std::string> 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<bytes(Address, bytes)> 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<bytes(Address, bytes)> 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;
};
}
}

2
libethereum/Transaction.cpp

@ -105,7 +105,7 @@ Address const& Transaction::safeSender() const noexcept
catch (...) catch (...)
{ {
cwarn << "safeSender() did throw an exception: " << boost::current_exception_diagnostic_information(); cwarn << "safeSender() did throw an exception: " << boost::current_exception_diagnostic_information();
return NullAddress; return ZeroAddress;
} }
} }

2
libethereum/Transaction.h

@ -97,8 +97,6 @@ struct ExecutionResult
std::ostream& operator<<(std::ostream& _out, ExecutionResult const& _er); 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. /// Encodes a transaction, ready to be exported to or freshly imported from RLP.
class Transaction class Transaction
{ {

2
libsolidity/InterfaceHandler.cpp

@ -107,7 +107,7 @@ unique_ptr<string> InterfaceHandler::getABISolidityInterface(ContractDefinition
ret += "returns" + populateParameters(it.second->getReturnParameterNames(), it.second->getReturnParameterTypeNames()); ret += "returns" + populateParameters(it.second->getReturnParameterNames(), it.second->getReturnParameterTypeNames());
else if (ret.back() == ' ') else if (ret.back() == ' ')
ret.pop_back(); ret.pop_back();
ret += "{}"; ret += ";";
} }
return unique_ptr<string>(new string(ret + "}")); return unique_ptr<string>(new string(ret + "}"));

22
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -194,7 +194,16 @@ static dev::eth::LogFilter toLogFilter(Json::Value const& _json) // commented to
} }
if (!_json["topics"].empty()) if (!_json["topics"].empty())
for (unsigned i = 0; i < _json["topics"].size(); i++) 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; return filter;
} }
@ -224,7 +233,16 @@ static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m,
if (!_json["topics"].empty()) if (!_json["topics"].empty())
for (auto i: _json["topics"]) 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); return _m.seal(_from, bt, ttl, workToProve);
} }

88
mix/CodeModel.cpp

@ -249,7 +249,6 @@ void CodeModel::runCompilationJob(int _jobId)
{ {
if (_jobId != m_backgroundJobId) if (_jobId != m_backgroundJobId)
return; //obsolete job return; //obsolete job
ContractMap result;
solidity::CompilerStack cs(true); solidity::CompilerStack cs(true);
try try
{ {
@ -260,40 +259,7 @@ void CodeModel::runCompilationJob(int _jobId)
cs.addSource(c.first.toStdString(), c.second.toStdString()); cs.addSource(c.first.toStdString(), c.second.toStdString());
} }
cs.compile(false); cs.compile(false);
collectContracts(cs);
{
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();
}
} }
catch (dev::Exception const& _exception) catch (dev::Exception const& _exception)
{ {
@ -307,8 +273,7 @@ void CodeModel::runCompilationJob(int _jobId)
sourceName = QString::fromStdString(*location->sourceName); sourceName = QString::fromStdString(*location->sourceName);
if (!sourceName.isEmpty()) if (!sourceName.isEmpty())
if (CompiledContract* contract = contractByDocumentId(sourceName)) if (CompiledContract* contract = contractByDocumentId(sourceName))
//substitute the location to match our contract names message = message.replace(sourceName, contract->contract()->name()); //substitute the location to match our contract names
message = message.replace(sourceName, contract->contract()->name());
} }
compilationError(message, sourceName); compilationError(message, sourceName);
} }
@ -316,6 +281,55 @@ void CodeModel::runCompilationJob(int _jobId)
emit stateChanged(); 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 bool CodeModel::hasContract() const
{ {
Guard l(x_contractMap); Guard l(x_contractMap);

3
mix/CodeModel.h

@ -117,7 +117,7 @@ private:
friend class CodeModel; friend class CodeModel;
}; };
using ContractMap = QHash<QString, CompiledContract*>; using ContractMap = QMap<QString, CompiledContract*>; //needs to be sorted
/// Code compilation model. Compiles contracts in background an provides compiled contract data /// Code compilation model. Compiles contracts in background an provides compiled contract data
class CodeModel: public QObject class CodeModel: public QObject
@ -182,6 +182,7 @@ private:
void runCompilationJob(int _jobId); void runCompilationJob(int _jobId);
void stop(); void stop();
void releaseContracts(); void releaseContracts();
void collectContracts(solidity::CompilerStack const& _cs);
std::atomic<bool> m_compiling; std::atomic<bool> m_compiling;
mutable dev::Mutex x_contractMap; mutable dev::Mutex x_contractMap;

4
mix/ContractCallDataEncoder.cpp

@ -195,7 +195,7 @@ QVariant ContractCallDataEncoder::decode(SolidityType const& _type, bytes const&
bytes rawParam(32); bytes rawParam(32);
value.populate(&rawParam); value.populate(&rawParam);
QSolidityType::Type type = _type.type; QSolidityType::Type type = _type.type;
if (type == QSolidityType::Type::SignedInteger || type == QSolidityType::Type::UnsignedInteger || type == QSolidityType::Type::Address) if (type == QSolidityType::Type::SignedInteger || type == QSolidityType::Type::UnsignedInteger)
return QVariant::fromValue(toString(decodeInt(rawParam))); return QVariant::fromValue(toString(decodeInt(rawParam)));
else if (type == QSolidityType::Type::Bool) else if (type == QSolidityType::Type::Bool)
return QVariant::fromValue(toString(decodeBool(rawParam))); return QVariant::fromValue(toString(decodeBool(rawParam)));
@ -203,6 +203,8 @@ QVariant ContractCallDataEncoder::decode(SolidityType const& _type, bytes const&
return QVariant::fromValue(toString(decodeBytes(rawParam))); return QVariant::fromValue(toString(decodeBytes(rawParam)));
else if (type == QSolidityType::Type::Struct) else if (type == QSolidityType::Type::Struct)
return QVariant::fromValue(QString("struct")); //TODO return QVariant::fromValue(QString("struct")); //TODO
else if (type == QSolidityType::Type::Address)
return QVariant::fromValue(toString(decodeBytes(unpadLeft(rawParam))));
else else
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Parameter declaration not found")); BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Parameter declaration not found"));
} }

9
mix/HttpServer.cpp

@ -145,16 +145,23 @@ void HttpServer::readClient()
if (socket->canReadLine()) if (socket->canReadLine())
{ {
QString hdr = QString(socket->readLine()); QString hdr = QString(socket->readLine());
QVariantMap headers;
if (hdr.startsWith("POST") || hdr.startsWith("GET")) if (hdr.startsWith("POST") || hdr.startsWith("GET"))
{ {
QUrl url(hdr.split(' ')[1]); QUrl url(hdr.split(' ')[1]);
QString l; QString l;
do do
{
l = socket->readLine(); 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")); while (!(l.isEmpty() || l == "\r" || l == "\r\n"));
QString content = socket->readAll(); QString content = socket->readAll();
std::unique_ptr<HttpRequest> request(new HttpRequest(this, url, content)); std::unique_ptr<HttpRequest> request(new HttpRequest(this, std::move(url), std::move(content), std::move(headers)));
clientConnected(request.get()); clientConnected(request.get());
QTextStream os(socket); QTextStream os(socket);
os.setAutoDetectUnicode(true); os.setAutoDetectUnicode(true);

8
mix/HttpServer.h

@ -25,6 +25,7 @@
#include <QObject> #include <QObject>
#include <QTcpServer> #include <QTcpServer>
#include <QUrl> #include <QUrl>
#include <QVariantMap>
#include <QQmlParserStatus> #include <QQmlParserStatus>
namespace dev namespace dev
@ -40,10 +41,12 @@ class HttpRequest: public QObject
Q_PROPERTY(QUrl url MEMBER m_url CONSTANT) Q_PROPERTY(QUrl url MEMBER m_url CONSTANT)
/// Request body contents /// Request body contents
Q_PROPERTY(QString content MEMBER m_content CONSTANT) Q_PROPERTY(QString content MEMBER m_content CONSTANT)
/// Request HTTP headers
Q_PROPERTY(QVariantMap headers MEMBER m_headers CONSTANT)
private: private:
HttpRequest(QObject* _parent, QUrl const& _url, QString const& _content): HttpRequest(QObject* _parent, QUrl&& _url, QString&& _content, QVariantMap&& _headers):
QObject(_parent), m_url(_url), m_content(_content) QObject(_parent), m_url(_url), m_content(_content), m_headers(_headers)
{ {
} }
@ -60,6 +63,7 @@ private:
QString m_content; QString m_content;
QString m_response; QString m_response;
QString m_responseContentType; QString m_responseContentType;
QVariantMap m_headers;
friend class HttpServer; friend class HttpServer;
}; };

30
mix/MixClient.cpp

@ -42,6 +42,18 @@ namespace mix
Secret const c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); Secret const c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074");
u256 const c_mixGenesisDifficulty = 131072; //TODO: make it lower for Mix somehow 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) bytes MixBlockChain::createGenesisBlock(h256 _stateRoot)
{ {
RLPStream block(3); RLPStream block(3);
@ -250,22 +262,8 @@ void MixClient::mine()
{ {
WriteGuard l(x_state); WriteGuard l(x_state);
m_state.commitToMine(bc()); m_state.commitToMine(bc());
m_state.completeMine<Ethash>(Ethash::Solution()); m_state.completeMine<MixPow>(0);
bc().import(m_state.blockData(), m_stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce); bc().import(m_state.blockData(), m_state.db(), ImportRequirements::Default & ~ImportRequirements::ValidNonce);
/*
GenericFarm<ProofOfWork> f;
bool completed = false;
f.onSolutionFound([&](ProofOfWork::Solution sol)
{
return completed = m_state.completeMine<ProofOfWork>(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.sync(bc()); m_state.sync(bc());
m_startState = m_state; m_startState = m_state;
h256Set changed { dev::eth::PendingChangedFilter, dev::eth::ChainChangedFilter }; h256Set changed { dev::eth::PendingChangedFilter, dev::eth::ChainChangedFilter };

23
mix/qml/QAddressView.qml

@ -5,10 +5,12 @@ import QtQuick.Controls.Styles 1.3
Item Item
{ {
property alias value: textinput.text property alias value: textinput.text
property alias contractCreationTr: ctrModel property alias accountRef: ctrModel
property string subType
property bool readOnly
id: editRoot id: editRoot
height: 20 height: 20
width: 200 width: 320
SourceSansProBold SourceSansProBold
{ {
@ -17,19 +19,19 @@ Item
function init() function init()
{ {
trCombobox.visible = ctrModel.count > 1; //index 0 is a blank value. trCombobox.visible = !readOnly
if (value.indexOf("<") === 0) textinput.readOnly = readOnly
if (!readOnly)
{ {
for (var k = 0; k < ctrModel.count; k++) for (var k = 0; k < ctrModel.count; k++)
{ {
if ("<" + ctrModel.get(k).functionId + ">" === value) if (ctrModel.get(k).value === value)
{ {
trCombobox.currentIndex = k; trCombobox.currentIndex = k;
return; return;
} }
} }
trCombobox.currentIndex = 0; trCombobox.currentIndex = 0;
value = "";
} }
} }
@ -43,7 +45,7 @@ Item
text: value text: value
width: parent.width width: parent.width
height: parent.width height: parent.width
wrapMode: Text.WrapAnywhere wrapMode: Text.WordWrap
clip: true clip: true
font.family: boldFont.name font.family: boldFont.name
MouseArea { MouseArea {
@ -73,7 +75,7 @@ Item
property bool selected: false property bool selected: false
id: trCombobox id: trCombobox
model: ctrModel model: ctrModel
textRole: "functionId" textRole: "itemid"
height: 20 height: 20
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: textinput.parent.right anchors.left: textinput.parent.right
@ -84,7 +86,10 @@ Item
return; return;
else if (currentText !== " - ") else if (currentText !== " - ")
{ {
textinput.text = "<" + currentText + ">"; if (model.get(currentIndex).type === "contract")
textinput.text = "<" + currentText + ">";
else
textinput.text = model.get(currentIndex).value; //address
trCombobox.selected = true; trCombobox.selected = true;
} }
else if (textinput.text.indexOf("<") === 0) else if (textinput.text.indexOf("<") === 0)

2
mix/qml/StateListModel.qml

@ -183,7 +183,7 @@ Item {
_secret = clientModel.newSecret(); _secret = clientModel.newSecret();
var address = clientModel.address(_secret); var address = clientModel.address(_secret);
var name = qsTr("Account") + "-" + address.substring(0, 4); var name = qsTr("Account") + "-" + address.substring(0, 4);
return { name: name, secret: _secret, balance: QEtherHelper.createEther(_balance, _unit) }; return { name: name, secret: _secret, balance: QEtherHelper.createEther(_balance, _unit), address: address };
} }
function createDefaultState() { function createDefaultState() {

43
mix/qml/StructView.qml

@ -7,8 +7,10 @@ Column
{ {
id: root id: root
property alias members: repeater.model //js array property alias members: repeater.model //js array
property variant accounts
property var value: ({}) property var value: ({})
property int transactionIndex property int transactionIndex
property string context
Layout.fillWidth: true Layout.fillWidth: true
spacing: 10 spacing: 10
Repeater Repeater
@ -69,21 +71,40 @@ Column
var vals = value; var vals = value;
if (ptype.category === QSolidityType.Address) if (ptype.category === QSolidityType.Address)
{ {
item.contractCreationTr.append({"functionId": " - "}); item.value = getValue();
var trCr = -1; item.readOnly = context === "variable";
for (var k = 0; k < transactionsModel.count; k++) if (context === "parameter")
{ {
if (k >= transactionIndex) var dec = modelData.type.name.split(" ");
break; item.subType = dec[0];
var tr = transactionsModel.get(k); item.accountRef.append({"itemid": " - "});
if (tr.functionId === tr.contractId)
if (item.subType === "contract" || item.subType === "address")
{
var trCr = 0;
for (var k = 0; k < transactionsModel.count; k++)
{
if (k >= transactionIndex)
break;
var tr = transactionsModel.get(k);
if (tr.functionId === tr.contractId && (dec[1] === tr.contractId || item.subType === "address"))
{
item.accountRef.append({ "itemid": tr.contractId + " - " + trCr, "value": "<" + tr.contractId + " - " + trCr + ">", "type": "contract" });
trCr++;
}
}
}
if (item.subType === "address")
{ {
trCr++; for (k = 0; k < accounts.length; k++)
if (modelData.type.name === qsTr("contract") + " " + tr.contractId) {
item.contractCreationTr.append({ "functionId": tr.contractId + " - " + trCr }); if (accounts[k].address === undefined)
accounts[k].address = clientModel.address(accounts[k].secret);
item.accountRef.append({ "itemid": accounts[k].name, "value": "0x" + accounts[k].address, "type": "address" });
}
} }
} }
item.value = getValue();
item.init(); item.init();
} }
else if (ptype.category === QSolidityType.Struct && !item.members) else if (ptype.category === QSolidityType.Struct && !item.members)

4
mix/qml/TransactionDialog.qml

@ -11,7 +11,7 @@ import "."
Dialog { Dialog {
id: modalTransactionDialog id: modalTransactionDialog
modality: Qt.ApplicationModal modality: Qt.ApplicationModal
width: 520 width: 570
height: 500 height: 500
visible: false visible: false
title: qsTr("Edit Transaction") title: qsTr("Edit Transaction")
@ -387,6 +387,8 @@ Dialog {
id: typeLoader id: typeLoader
Layout.preferredWidth: 150 Layout.preferredWidth: 150
members: paramsModel; members: paramsModel;
accounts: senderComboBox.model
context: "parameter"
} }
} }

2
mix/qml/VariablesView.qml

@ -24,6 +24,8 @@ DebugInfoList
members: [] members: []
value: {} value: {}
Layout.preferredWidth: parent.width Layout.preferredWidth: parent.width
context: "variable"
width: parent.width
} }
} }
} }

8
mix/qml/WebPreview.qml

@ -17,6 +17,7 @@ Item {
property string webContent; //for testing property string webContent; //for testing
signal javaScriptMessage(var _level, string _sourceId, var _lineNb, string _content) signal javaScriptMessage(var _level, string _sourceId, var _lineNb, string _content)
signal webContentReady signal webContentReady
signal ready
function setPreviewUrl(url) { function setPreviewUrl(url) {
if (!initialized) if (!initialized)
@ -184,8 +185,10 @@ Item {
content = fileIo.readFile(doc.path); content = fileIo.readFile(doc.path);
} }
if (documentName === urlInput.text.replace(httpServer.url + "/", "")) { var accept = _request.headers["accept"];
//root page, inject deployment script if (accept && accept.indexOf("text/html") >= 0 && !_request.headers["http_x_requested_with"])
{
//navigate to page request, inject deployment script
content = "<script>web3=parent.web3;BigNumber=parent.BigNumber;contracts=parent.contracts;</script>\n" + content; content = "<script>web3=parent.web3;BigNumber=parent.BigNumber;contracts=parent.contracts;</script>\n" + content;
_request.setResponseContentType("text/html"); _request.setResponseContentType("text/html");
} }
@ -325,6 +328,7 @@ Item {
webView.runJavaScript("init(\"" + httpServer.url + "/rpc/\")"); webView.runJavaScript("init(\"" + httpServer.url + "/rpc/\")");
if (pendingPageUrl) if (pendingPageUrl)
setPreviewUrl(pendingPageUrl); setPreviewUrl(pendingPageUrl);
ready();
} }
} }
} }

9
mix/test/TestService.cpp

@ -20,8 +20,9 @@
* Ethereum IDE client. * Ethereum IDE client.
*/ */
#include <iostream>
#include "TestService.h" #include "TestService.h"
#include <iostream>
#include <QUuid>
#include <QtTest/QSignalSpy> #include <QtTest/QSignalSpy>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QQuickItem> #include <QQuickItem>
@ -177,7 +178,6 @@ void TestService::setTargetWindow(QObject* _window)
window->requestActivate(); window->requestActivate();
} }
QWindow* TestService::eventWindow(QObject* _item) QWindow* TestService::eventWindow(QObject* _item)
{ {
QQuickItem* item = qobject_cast<QQuickItem*>(_item); QQuickItem* item = qobject_cast<QQuickItem*>(_item);
@ -201,5 +201,10 @@ QWindow* TestService::eventWindow(QObject* _item)
return 0; return 0;
} }
QString TestService::createUuid() const
{
return QUuid::createUuid().toString();
}
} }
} }

1
mix/test/TestService.h

@ -41,6 +41,7 @@ public:
void setTargetWindow(QObject* _window); void setTargetWindow(QObject* _window);
public slots: public slots:
QString createUuid() const;
bool waitForSignal(QObject* _item, QString _signalName, int _timeout); bool waitForSignal(QObject* _item, QString _signalName, int _timeout);
bool waitForRendering(QObject* _item, int timeout); bool waitForRendering(QObject* _item, int timeout);
bool keyPress(QObject* _item, int _key, int _modifiers, int _delay); bool keyPress(QObject* _item, int _key, int _modifiers, int _delay);

14
mix/test/qml/TestMain.qml

@ -41,7 +41,7 @@ TestCase
var projectDlg = mainApplication.projectModel.newProjectDialog; var projectDlg = mainApplication.projectModel.newProjectDialog;
wait(30); wait(30);
projectDlg.projectTitle = "TestProject"; 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(); projectDlg.acceptAndClose();
wait(1); wait(1);
if (!ts.waitForSignal(mainApplication.codeModel, "compilationComplete()", 5000)) if (!ts.waitForSignal(mainApplication.codeModel, "compilationComplete()", 5000))
@ -82,6 +82,16 @@ TestCase
ts.keyPressChar(mainApplication, "S", Qt.ControlModifier, 200); //Ctrl+S 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) function clickElement(el, x, y)
{ {
if (el.contentItem) if (el.contentItem)
@ -101,5 +111,7 @@ TestCase
function test_miner_selectMiner() { TestMiner.test_selectMiner(); } function test_miner_selectMiner() { TestMiner.test_selectMiner(); }
function test_miner_mine() { TestMiner.test_mine(); } function test_miner_mine() { TestMiner.test_mine(); }
function test_project_contractRename() { TestProject.test_contractRename(); } function test_project_contractRename() { TestProject.test_contractRename(); }
function test_project_multipleWebPages() { TestProject.test_multipleWebPages(); }
function test_project_multipleContractsSameFile() { TestProject.test_multipleContractsSameFile(); }
} }

17
mix/test/qml/js/TestDebugger.js

@ -123,8 +123,7 @@ function test_arrayParametersAndStorage()
transactionDialog.acceptAndClose(); transactionDialog.acceptAndClose();
mainApplication.projectModel.stateDialog.acceptAndClose(); mainApplication.projectModel.stateDialog.acceptAndClose();
mainApplication.mainContent.startQuickDebugging(); mainApplication.mainContent.startQuickDebugging();
if (!ts.waitForSignal(mainApplication.clientModel, "debugDataReady(QObject*)", 5000)) waitForExecution();
fail("Error running transaction");
//debug setM //debug setM
mainApplication.clientModel.debugRecord(3); mainApplication.clientModel.debugRecord(3);
mainApplication.mainContent.rightPane.debugSlider.value = mainApplication.mainContent.rightPane.debugSlider.maximumValue; mainApplication.mainContent.rightPane.debugSlider.value = mainApplication.mainContent.rightPane.debugSlider.maximumValue;
@ -158,8 +157,7 @@ function test_solidityDebugging()
"}"); "}");
mainApplication.mainContent.startQuickDebugging(); mainApplication.mainContent.startQuickDebugging();
if (!ts.waitForSignal(mainApplication.clientModel, "debugDataReady(QObject*)", 5000)) waitForExecution();
fail("Error running transaction");
tryCompare(mainApplication.mainContent.rightPane.debugSlider, "maximumValue", 20); tryCompare(mainApplication.mainContent.rightPane.debugSlider, "maximumValue", 20);
tryCompare(mainApplication.mainContent.rightPane.debugSlider, "value", 0); tryCompare(mainApplication.mainContent.rightPane.debugSlider, "value", 0);
@ -191,8 +189,7 @@ function test_vmDebugging()
"}"); "}");
mainApplication.mainContent.startQuickDebugging(); mainApplication.mainContent.startQuickDebugging();
if (!ts.waitForSignal(mainApplication.clientModel, "debugDataReady(QObject*)", 5000)) waitForExecution();
fail("Error running transaction");
mainApplication.mainContent.rightPane.assemblyMode = !mainApplication.mainContent.rightPane.assemblyMode; mainApplication.mainContent.rightPane.assemblyMode = !mainApplication.mainContent.rightPane.assemblyMode;
tryCompare(mainApplication.mainContent.rightPane.debugSlider, "maximumValue", 41); tryCompare(mainApplication.mainContent.rightPane.debugSlider, "maximumValue", 41);
@ -225,12 +222,7 @@ function test_ctrTypeAsParam()
" }\r " + " }\r " +
"}"); "}");
mainApplication.projectModel.stateListModel.editState(0); //C1 ctor already added mainApplication.projectModel.stateListModel.editState(0); //C1 ctor already added
mainApplication.projectModel.stateDialog.model.addTransaction();
var transactionDialog = mainApplication.projectModel.stateDialog.transactionDialog; var transactionDialog = mainApplication.projectModel.stateDialog.transactionDialog;
ts.waitForRendering(transactionDialog, 3000);
transactionDialog.selectContract("C2");
transactionDialog.selectFunction("C2");
transactionDialog.acceptAndClose();
mainApplication.projectModel.stateDialog.model.addTransaction(); mainApplication.projectModel.stateDialog.model.addTransaction();
transactionDialog = mainApplication.projectModel.stateDialog.transactionDialog; transactionDialog = mainApplication.projectModel.stateDialog.transactionDialog;
ts.waitForRendering(transactionDialog, 3000); ts.waitForRendering(transactionDialog, 3000);
@ -241,8 +233,7 @@ function test_ctrTypeAsParam()
transactionDialog.acceptAndClose(); transactionDialog.acceptAndClose();
mainApplication.projectModel.stateDialog.acceptAndClose(); mainApplication.projectModel.stateDialog.acceptAndClose();
mainApplication.mainContent.startQuickDebugging(); mainApplication.mainContent.startQuickDebugging();
if (!ts.waitForSignal(mainApplication.clientModel, "debugDataReady(QObject*)", 5000)) waitForExecution();
fail("Error running transaction");
tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(4), "returned", "(159)"); tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(4), "returned", "(159)");
} }

4
mix/test/qml/js/TestMiner.js

@ -25,6 +25,10 @@ function test_mine()
waitForExecution(); waitForExecution();
mainApplication.clientModel.mine(); mainApplication.clientModel.mine();
waitForMining(); 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(3), "contract", " - Block - ");
tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(4), "contract", " - Block - ");
} }

28
mix/test/qml/js/TestProject.js

@ -16,3 +16,31 @@ function test_contractRename()
transactionDialog.close(); transactionDialog.close();
mainApplication.projectModel.stateDialog.close(); mainApplication.projectModel.stateDialog.close();
} }
function test_multipleWebPages()
{
newProject();
editHtml("<html><body><a href=\"page1.html\">page1</a></body></html>");
createHtml("page1.html", "<html><body><div id='queryres'>Fail</div></body><script>if (web3) document.getElementById('queryres').innerText='OK'</script></html>");
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("<div id=\"queryres\">OK</div>") != -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");
}

3
solc/CommandLineInterface.cpp

@ -380,6 +380,9 @@ bool CommandLineInterface::processInput()
void CommandLineInterface::handleCombinedJSON() void CommandLineInterface::handleCombinedJSON()
{ {
if (!m_args.count("combined-json"))
return;
Json::Value output(Json::objectValue); Json::Value output(Json::objectValue);
set<string> requests; set<string> requests;

6
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 # NOTE that we only get the latest commit of that branch
RUN git cherry-pick solidityjs/solidity-js 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 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 # 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

12
test/libsolidity/SolidityInterface.cpp

@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(single_function)
"}\n"); "}\n");
BOOST_REQUIRE_EQUAL(1, contract.getDefinedFunctions().size()); BOOST_REQUIRE_EQUAL(1, contract.getDefinedFunctions().size());
BOOST_CHECK_EQUAL(getSourcePart(*contract.getDefinedFunctions().front()), BOOST_CHECK_EQUAL(getSourcePart(*contract.getDefinedFunctions().front()),
"function f(uint256 a)returns(uint256 d){}"); "function f(uint256 a)returns(uint256 d);");
} }
BOOST_AUTO_TEST_CASE(single_constant_function) BOOST_AUTO_TEST_CASE(single_constant_function)
@ -87,7 +87,7 @@ BOOST_AUTO_TEST_CASE(single_constant_function)
"contract test { function f(uint a) constant returns(bytes1 x) { 1==2; } }"); "contract test { function f(uint a) constant returns(bytes1 x) { 1==2; } }");
BOOST_REQUIRE_EQUAL(1, contract.getDefinedFunctions().size()); BOOST_REQUIRE_EQUAL(1, contract.getDefinedFunctions().size());
BOOST_CHECK_EQUAL(getSourcePart(*contract.getDefinedFunctions().front()), BOOST_CHECK_EQUAL(getSourcePart(*contract.getDefinedFunctions().front()),
"function f(uint256 a)constant returns(bytes1 x){}"); "function f(uint256 a)constant returns(bytes1 x);");
} }
BOOST_AUTO_TEST_CASE(multiple_functions) BOOST_AUTO_TEST_CASE(multiple_functions)
@ -97,8 +97,8 @@ BOOST_AUTO_TEST_CASE(multiple_functions)
" function g(uint b) returns(uint e) { return b * 8; }\n" " function g(uint b) returns(uint e) { return b * 8; }\n"
"}\n"; "}\n";
ContractDefinition const& contract = checkInterface(sourceCode); ContractDefinition const& contract = checkInterface(sourceCode);
set<string> expectation({"function f(uint256 a)returns(uint256 d){}", set<string> expectation({"function f(uint256 a)returns(uint256 d);",
"function g(uint256 b)returns(uint256 e){}"}); "function g(uint256 b)returns(uint256 e);"});
BOOST_REQUIRE_EQUAL(2, contract.getDefinedFunctions().size()); BOOST_REQUIRE_EQUAL(2, contract.getDefinedFunctions().size());
BOOST_CHECK(expectation == set<string>({getSourcePart(*contract.getDefinedFunctions().at(0)), BOOST_CHECK(expectation == set<string>({getSourcePart(*contract.getDefinedFunctions().at(0)),
getSourcePart(*contract.getDefinedFunctions().at(1))})); getSourcePart(*contract.getDefinedFunctions().at(1))}));
@ -135,8 +135,8 @@ BOOST_AUTO_TEST_CASE(inheritance)
" event derivedEvent(uint indexed evtArgDerived); \n" " event derivedEvent(uint indexed evtArgDerived); \n"
" }"; " }";
ContractDefinition const& contract = checkInterface(sourceCode); ContractDefinition const& contract = checkInterface(sourceCode);
set<string> expectedFunctions({"function baseFunction(uint256 p)returns(uint256 i){}", set<string> expectedFunctions({"function baseFunction(uint256 p)returns(uint256 i);",
"function derivedFunction(bytes32 p)returns(bytes32 i){}"}); "function derivedFunction(bytes32 p)returns(bytes32 i);"});
BOOST_REQUIRE_EQUAL(2, contract.getDefinedFunctions().size()); BOOST_REQUIRE_EQUAL(2, contract.getDefinedFunctions().size());
BOOST_CHECK(expectedFunctions == set<string>({getSourcePart(*contract.getDefinedFunctions().at(0)), BOOST_CHECK(expectedFunctions == set<string>({getSourcePart(*contract.getDefinedFunctions().at(0)),
getSourcePart(*contract.getDefinedFunctions().at(1))})); getSourcePart(*contract.getDefinedFunctions().at(1))}));

Loading…
Cancel
Save