Browse Source

Merge remote-tracking branch 'up/develop' into ui_macos

cl-refactor
yann300 10 years ago
parent
commit
557802d5ca
  1. 30
      CMakeLists.txt
  2. 16
      CodingStandards.txt
  3. 55
      alethzero/DappLoader.cpp
  4. 7
      alethzero/DappLoader.h
  5. 18
      alethzero/Main.ui
  6. 30
      alethzero/MainWin.cpp
  7. 1
      alethzero/MainWin.h
  8. 234
      eth/main.cpp
  9. 4
      evmjit/libevmjit/ExecutionEngine.cpp
  10. 21
      exp/CMakeLists.txt
  11. 26
      exp/main.cpp
  12. 1
      libdevcore/CMakeLists.txt
  13. 2
      libdevcore/Common.cpp
  14. 6
      libdevcore/CommonIO.cpp
  15. 2
      libdevcore/CommonIO.h
  16. 2
      libdevcore/Log.cpp
  17. 2
      libdevcore/RLP.cpp
  18. 5
      libdevcore/RLP.h
  19. 1
      libdevcore/RangeMask.h
  20. 4
      libdevcore/TransientDirectory.cpp
  21. 4
      libdevcore/TransientDirectory.h
  22. 12
      libdevcore/Worker.cpp
  23. 6
      libdevcrypto/Common.cpp
  24. 2
      libethash/util.h
  25. 7
      libethcore/BlockInfo.cpp
  26. 4
      libethcore/BlockInfo.h
  27. 38
      libethcore/Ethasher.cpp
  28. 2
      libethcore/Ethasher.h
  29. 146
      libethcore/ProofOfWork.cpp
  30. 40
      libethcore/ProofOfWork.h
  31. 10
      libethereum/BlockChain.cpp
  32. 10
      libethereum/BlockChain.h
  33. 7
      libethereum/CMakeLists.txt
  34. 39
      libethereum/Client.cpp
  35. 25
      libethereum/Client.h
  36. 19
      libethereum/ClientBase.cpp
  37. 12
      libethereum/ClientBase.h
  38. 18
      libethereum/Interface.h
  39. 4
      libethereum/Miner.cpp
  40. 13
      libethereum/Miner.h
  41. 38
      libethereum/State.cpp
  42. 22
      libethereum/State.h
  43. 2
      libtestutils/BlockChainLoader.h
  44. 1
      libtestutils/FixedClient.h
  45. 2
      libtestutils/StateLoader.h
  46. 83
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  47. 1
      libweb3jsonrpc/WebThreeStubServerBase.h
  48. 7
      libweb3jsonrpc/abstractwebthreestubserver.h
  49. 5
      libweb3jsonrpc/spec.json
  50. 4
      mix/InverseMouseArea.cpp
  51. 8
      mix/InverseMouseArea.h
  52. 28
      mix/MixClient.cpp
  53. 16
      mix/MixClient.h
  54. 1
      mix/qml/Application.qml
  55. 52
      mix/qml/CodeEditorView.qml
  56. 4
      mix/qml/DebugInfoList.qml
  57. 109
      mix/qml/Debugger.qml
  58. 2
      mix/qml/ProjectModel.qml
  59. 11
      mix/qml/StatesComboBox.qml
  60. 21
      mix/qml/StatusPane.qml
  61. 122
      mix/qml/StepActionImage.qml
  62. 2
      mix/qml/WebCodeEditor.qml
  63. 12
      mix/qml/html/cm/solarized.css
  64. BIN
      mix/qml/img/closedtriangleindicator.png
  65. BIN
      mix/qml/img/closedtriangleindicator@2x.png
  66. BIN
      mix/qml/img/opentriangleindicator.png
  67. BIN
      mix/qml/img/opentriangleindicator@2x.png
  68. BIN
      mix/qml/img/signerroricon32.png
  69. BIN
      mix/qml/img/warningicon.png
  70. BIN
      mix/qml/img/warningicon@2x.png
  71. 3
      mix/qml/js/ProjectModel.js
  72. 5
      mix/res.qrc
  73. 8
      mix/test/qml/TestMain.qml
  74. 1
      mix/test/qml/js/TestDebugger.js
  75. 1
      test/TestUtils.cpp
  76. 9
      test/blockchain.cpp
  77. 2
      test/state.cpp
  78. 5
      test/stateOriginal.cpp
  79. 2
      test/vm.cpp
  80. 10
      test/webthreestubclient.h

30
CMakeLists.txt

@ -15,7 +15,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# Normally, set(...CACHE...) creates cache variables, but does not modify them.
function(createDefaultCacheConfig)
set(VMTRACE OFF CACHE BOOL "VM tracing and run-time checks (useful for cross-implementation VM debugging)")
set(PARANOIA OFF CACHE BOOL "Additional run-time checks")
set(PARANOID OFF CACHE BOOL "Additional run-time checks")
set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on")
set(FATDB OFF CACHE BOOL "Build with ability to list entries in the Trie. Doubles DB size, slows everything down, but good for looking at state diffs and trie contents.")
set(USENPM OFF CACHE BOOL "Use npm to recompile ethereum.js if it was changed")
@ -35,7 +35,7 @@ endfunction()
# propagates CMake configuration options to the compiler
function(configureProject)
if (PARANOIA)
if (PARANOID)
add_definitions(-DETH_PARANOIA)
endif ()
@ -62,6 +62,8 @@ function(configureProject)
if (GUI)
add_definitions(-DETH_GUI)
endif()
add_definitions(-DETH_TRUE)
endfunction()
set(CPPETHEREUM 1)
@ -89,7 +91,7 @@ function(createBuildInfo)
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/int")
endif ()
if (PARANOIA)
if (PARANOID)
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/PARA")
endif ()
@ -123,9 +125,9 @@ cmake_policy(SET CMP0015 NEW)
# Clear invalid option
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
if (PARANOIA)
if (PARANOID)
message("Paranoia requires debug - disabling for release build.")
set(PARANOIA OFF)
set(PARANOID OFF)
endif ()
if (VMTRACE)
message("VM Tracing requires debug - disabling for release build.")
@ -134,7 +136,6 @@ if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
endif ()
createDefaultCacheConfig()
configureProject()
# Force chromium.
set (ETH_HAVE_WEBENGINE 1)
@ -151,10 +152,10 @@ if (HEADLESS)
set(BUNDLE "minimal")
endif ()
if (PARANOIA)
set(PARANOIA ON)
if (PARANOID)
set(PARANOID ON)
else ()
set(PARANOIA OFF)
set(PARANOID OFF)
endif ()
if (VMTRACE)
set(VMTRACE ON)
@ -261,6 +262,8 @@ elseif (BUNDLE STREQUAL "user")
set(TESTS OFF)
endif ()
configureProject()
# Default CMAKE_BUILD_TYPE to "Release".
set(CMAKE_BUILD_TYPE CACHE STRING "Release")
if ("x${CMAKE_BUILD_TYPE}" STREQUAL "x")
@ -270,7 +273,11 @@ endif ()
# Default TARGET_PLATFORM to "linux".
set(TARGET_PLATFORM CACHE STRING "linux")
if ("x${TARGET_PLATFORM}" STREQUAL "x")
set(TARGET_PLATFORM "linux")
if (WIN32)
set(TARGET_PLATFORM "windows")
else ()
set(TARGET_PLATFORM "linux")
endif ()
endif ()
message("------------------------------------------------------------------------")
@ -282,7 +289,6 @@ message("--------------------------------------------------------------- feature
message("-- Chromium support ${ETH_HAVE_WEBENGINE}")
message("-- VMTRACE VM execution tracing ${VMTRACE}")
message("-- PROFILING Profiling support ${PROFILING}")
message("-- PARANOIA Additional (SLOW) database checking ${PARANOIA}")
message("-- FATDB Full database exploring ${FATDB}")
message("-- JSONRPC JSON-RPC support ${JSONRPC}")
message("-- USENPM Javascript source building ${USENPM}")
@ -307,7 +313,7 @@ include(EthCompilerSettings)
message("-- CXXFLAGS: ${CMAKE_CXX_FLAGS}")
# this must be an include, as a function it would messs up with variable scope!
# this must be an include, as a function it would mess up with variable scope!
include(EthDependencies)
include(EthExecutableHelper)

16
CodingStandards.txt

@ -113,26 +113,33 @@ d. Favour declarations close to use; don't habitually declare at top of scope al
e. Always pass non-trivial parameters with a const& suffix.
f. If a function returns multiple values, use std::tuple (std::pair acceptable). Prefer not using */& arguments, except where efficiency requires.
g. Never use a macro where adequate non-preprocessor C++ can be written.
h. Prefer "using NewType = OldType" to "typedef OldType NewType".
i. Make use of auto whenever type is clear or unimportant:
h. Make use of auto whenever type is clear or unimportant:
- Always avoid doubly-stating the type.
- Use to avoid vast and unimportant type declarations.
i. Don't pass bools: prefer enumerations instead.
j. Prefer enum class to straight enum.
(WRONG)
const double d = 0;
int i, j;
char *s;
float meanAndSigma(std::vector<float> _v, float* _sigma);
float meanAndSigma(std::vector<float> _v, float* _sigma, bool _approximate);
Derived* x(dynamic_cast<Derived*>(base));
for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); ++l) {}
(CORRECT)
enum class Accuracy
{
Approximate,
Exact
};
double const d = 0;
int i;
int j;
char* s;
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v);
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v, Accuracy _a);
auto x = dynamic_cast<Derived*>(base);
for (auto i = x.begin(); i != x.end(); ++i) {}
@ -192,7 +199,6 @@ c. Where there are exceptions to this (due to excessive use and clear meaning),
d. In general expressions should be roughly as important/semantically meaningful as the space they occupy.
11. Commenting
a. Comments should be doxygen-compilable, using @notation rather than \notation.

55
alethzero/DappLoader.cpp

@ -25,6 +25,7 @@
#include <QStringList>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QMimeDatabase>
#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/CryptoPP.h>
@ -96,13 +97,31 @@ DappLocation DappLoader::resolveAppUri(QString const& _uri)
void DappLoader::downloadComplete(QNetworkReply* _reply)
{
QUrl requestUrl = _reply->request().url();
if (m_pageUrls.count(requestUrl) != 0)
{
//inject web3 js
QByteArray content = "<script>\n";
content.append(web3Content());
content.append("</script>\n");
content.append(_reply->readAll());
QString contentType = _reply->header(QNetworkRequest::ContentTypeHeader).toString();
if (contentType.isEmpty())
{
QMimeDatabase db;
contentType = db.mimeTypeForUrl(requestUrl).name();
}
pageReady(content, contentType, requestUrl);
return;
}
try
{
//try to interpret as rlp
QByteArray data = _reply->readAll();
_reply->deleteLater();
h256 expected = m_uriHashes[_reply->request().url()];
h256 expected = m_uriHashes[requestUrl];
bytes package(reinterpret_cast<unsigned char const*>(data.constData()), reinterpret_cast<unsigned char const*>(data.constData() + data.size()));
Secp256k1 dec;
dec.decrypt(expected, package);
@ -144,15 +163,7 @@ void DappLoader::loadDapp(RLP const& _rlp)
if (entry->path == "/deployment.js")
{
//inject web3 code
QString code;
code += contentsOfQResource(":/js/bignumber.min.js");
code += "\n";
code += contentsOfQResource(":/js/webthree.js");
code += "\n";
code += contentsOfQResource(":/js/setup.js");
code += "\n";
QByteArray res = code.toLatin1();
bytes b(res.data(), res.data() + res.size());
bytes b(web3Content().data(), web3Content().data() + web3Content().size());
b.insert(b.end(), content.begin(), content.end());
dapp.content[hash] = b;
}
@ -165,6 +176,22 @@ void DappLoader::loadDapp(RLP const& _rlp)
emit dappReady(dapp);
}
QByteArray const& DappLoader::web3Content()
{
if (m_web3Js.isEmpty())
{
QString code;
code += contentsOfQResource(":/js/bignumber.min.js");
code += "\n";
code += contentsOfQResource(":/js/webthree.js");
code += "\n";
code += contentsOfQResource(":/js/setup.js");
code += "\n";
m_web3Js = code.toLatin1();
}
return m_web3Js;
}
Manifest DappLoader::loadManifest(std::string const& _manifest)
{
/// https://github.com/ethereum/go-ethereum/wiki/URL-Scheme
@ -216,3 +243,11 @@ void DappLoader::loadDapp(QString const& _uri)
m_net.get(request);
}
void DappLoader::loadPage(QString const& _uri)
{
QUrl uri(_uri);
QNetworkRequest request(uri);
m_pageUrls.insert(uri);
m_net.get(request);
}

7
alethzero/DappLoader.h

@ -73,9 +73,13 @@ public:
///Load a new DApp. Resolves a name with a name reg contract. Asynchronous. dappReady is emitted once everything is read, dappError othervise
///@param _uri Eth name path
void loadDapp(QString const& _uri);
///Load a regular html page
///@param _uri Page Uri
void loadPage(QString const& _uri);
signals:
void dappReady(Dapp& _dapp);
void pageReady(QByteArray const& _content, QString const& _mimeType, QUrl const& _uri);
void dappError();
private slots:
@ -86,9 +90,12 @@ private:
DappLocation resolveAppUri(QString const& _uri);
void loadDapp(dev::RLP const& _rlp);
Manifest loadManifest(std::string const& _manifest);
QByteArray const& web3Content();
dev::WebThreeDirect* m_web3;
QNetworkAccessManager m_net;
std::map<QUrl, dev::h256> m_uriHashes;
std::set<QUrl> m_pageUrls;
QByteArray m_web3Js;
};

18
alethzero/Main.ui

@ -150,6 +150,7 @@
<string>&amp;Tools</string>
</property>
<addaction name="mine"/>
<addaction name="turboMining"/>
<addaction name="separator"/>
<addaction name="newTransaction"/>
<addaction name="newAccount"/>
@ -176,7 +177,6 @@
<addaction name="killBlockchain"/>
<addaction name="inject"/>
<addaction name="forceMining"/>
<addaction name="turboMining"/>
<addaction name="separator"/>
<addaction name="usePrivate"/>
<addaction name="jitvm"/>
@ -1608,14 +1608,6 @@ font-size: 14pt</string>
<string>&amp;Enable LLL Optimizer</string>
</property>
</action>
<action name="turboMining">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Reserved Debug 1</string>
</property>
</action>
<action name="localNetworking">
<property name="checkable">
<bool>true</bool>
@ -1679,6 +1671,14 @@ font-size: 14pt</string>
<string>&amp;NatSpec Enabled</string>
</property>
</action>
<action name="turboMining">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;GPU Mining</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>

30
alethzero/MainWin.cpp

@ -183,13 +183,6 @@ Main::Main(QWidget *parent) :
m_webPage = webPage;
connect(webPage, &WebPage::consoleMessage, [this](QString const& _msg) { Main::addConsoleMessage(_msg, QString()); });
ui->webView->setPage(m_webPage);
connect(ui->webView, &QWebEngineView::loadFinished, [this]()
{
auto f = ui->webView->page();
f->runJavaScript(contentsOfQResource(":/js/bignumber.min.js"));
f->runJavaScript(contentsOfQResource(":/js/webthree.js"));
f->runJavaScript(contentsOfQResource(":/js/setup.js"));
});
connect(ui->webView, &QWebEngineView::titleChanged, [=]()
{
@ -199,6 +192,7 @@ Main::Main(QWidget *parent) :
m_dappHost.reset(new DappHost(8081));
m_dappLoader = new DappLoader(this, web3());
connect(m_dappLoader, &DappLoader::dappReady, this, &Main::dappLoaded);
connect(m_dappLoader, &DappLoader::pageReady, this, &Main::pageLoaded);
// ui->webView->page()->settings()->setAttribute(QWebEngineSettings::DeveloperExtrasEnabled, true);
// QWebEngineInspector* inspector = new QWebEngineInspector();
// inspector->setPage(page);
@ -264,7 +258,7 @@ NetworkPreferences Main::netPrefs() const
{
listenIP.clear();
}
auto publicIP = ui->forcePublicIP->text().toStdString();
try
{
@ -274,7 +268,7 @@ NetworkPreferences Main::netPrefs() const
{
publicIP.clear();
}
if (isPublicAddress(publicIP))
return NetworkPreferences(publicIP, listenIP, ui->port->value(), ui->upnp->isChecked());
else
@ -713,6 +707,7 @@ void Main::writeSettings()
s.setValue("upnp", ui->upnp->isChecked());
s.setValue("forceAddress", ui->forcePublicIP->text());
s.setValue("forceMining", ui->forceMining->isChecked());
s.setValue("turboMining", ui->turboMining->isChecked());
s.setValue("paranoia", ui->paranoia->isChecked());
s.setValue("natSpec", ui->natSpec->isChecked());
s.setValue("showAll", ui->showAll->isChecked());
@ -783,6 +778,8 @@ void Main::readSettings(bool _skipGeometry)
ui->dropPeers->setChecked(false);
ui->forceMining->setChecked(s.value("forceMining", false).toBool());
on_forceMining_triggered();
ui->turboMining->setChecked(s.value("turboMining", false).toBool());
on_turboMining_triggered();
ui->paranoia->setChecked(s.value("paranoia", false).toBool());
ui->natSpec->setChecked(s.value("natSpec", true).toBool());
ui->showAll->setChecked(s.value("showAll", false).toBool());
@ -918,6 +915,7 @@ void Main::on_urlEdit_returnPressed()
{
//try do resolve dapp url
m_dappLoader->loadDapp(s);
return;
}
catch (...)
{
@ -931,8 +929,7 @@ void Main::on_urlEdit_returnPressed()
else
url.setScheme("http");
else {}
qDebug() << url.toString();
ui->webView->page()->setUrl(url);
m_dappLoader->loadPage(url.toString());
}
void Main::on_nameReg_textChanged()
@ -1799,7 +1796,7 @@ void Main::on_connect_triggered()
ui->net->setChecked(true);
on_net_triggered();
}
m_connect.setEnvironment(m_servers);
if (m_connect.exec() == QDialog::Accepted)
{
@ -1811,9 +1808,9 @@ void Main::on_connect_triggered()
nodeID = NodeId(fromHex(m_connect.nodeId().toStdString()));
}
catch (BadHexCharacter&) {}
m_connect.reset();
if (required)
web3()->requirePeer(nodeID, host);
else
@ -2016,3 +2013,8 @@ void Main::dappLoaded(Dapp& _dapp)
QUrl url = m_dappHost->hostDapp(std::move(_dapp));
ui->webView->page()->setUrl(url);
}
void Main::pageLoaded(QByteArray const& _content, QString const& _mimeType, QUrl const& _uri)
{
ui->webView->page()->setContent(_content, _mimeType, _uri);
}

1
alethzero/MainWin.h

@ -179,6 +179,7 @@ private slots:
// Dapps
void dappLoaded(Dapp& _dapp); //qt does not support rvalue refs for signals
void pageLoaded(QByteArray const& _content, QString const& _mimeType, QUrl const& _uri);
signals:
void poll();

234
eth/main.cpp

@ -115,9 +115,14 @@ void help()
<< " <APPDATA>/Etherum or Library/Application Support/Ethereum)." << endl
<< " -D,--create-dag <this/next/number> Create the DAG in preparation for mining on given block and exit." << endl
<< " -e,--ether-price <n> Set the ether price in the reference unit e.g. ¢ (Default: 30.679)." << endl
<< " -E,--export <file> Export file as a concatenated series of blocks and exit." << endl
<< " --from <n> Export only from block n; n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --to <n> Export only to block n (inclusive); n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --only <n> Equivalent to --export-from n --export-to n." << endl
<< " -f,--force-mining Mine even when there are no transaction to mine (Default: off)" << endl
<< " -h,--help Show this help message and exit." << endl
<< " -i,--interactive Enter interactive mode (default: non-interactive)." << endl
<< " -I,--import <file> Import file as a concatenated series of blocks and exit." << endl
#if ETH_JSONRPC
<< " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl
<< " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: " << SensibleHttpPort << ")." << endl
@ -209,44 +214,77 @@ void doInitDAG(unsigned _n)
exit(0);
}
static const unsigned NoDAGInit = (unsigned)-3;
enum class OperationMode
{
Node,
Import,
Export,
DAGInit
};
enum class Format
{
Binary,
Hex,
Human
};
int main(int argc, char** argv)
{
unsigned initDAG = NoDAGInit;
string listenIP;
unsigned short listenPort = 30303;
string publicIP;
string remoteHost;
unsigned short remotePort = 30303;
// Init defaults
Defaults::get();
/// Operating mode.
OperationMode mode = OperationMode::Node;
string dbPath;
unsigned mining = ~(unsigned)0;
NodeMode mode = NodeMode::Full;
unsigned peers = 5;
int miners = -1;
/// File name for import/export.
string filename;
/// Hashes/numbers for export range.
string exportFrom = "1";
string exportTo = "latest";
Format exportFormat = Format::Binary;
/// DAG initialisation param.
unsigned initDAG = 0;
/// General params for Node operation
NodeMode nodeMode = NodeMode::Full;
bool interactive = false;
#if ETH_JSONRPC
int jsonrpc = -1;
#endif
bool bootstrap = false;
bool upnp = true;
bool forceMining = false;
WithExisting killChain = WithExisting::Trust;
bool jit = false;
/// Networking params.
string clientName;
string listenIP;
unsigned short listenPort = 30303;
string publicIP;
string remoteHost;
unsigned short remotePort = 30303;
unsigned peers = 5;
bool bootstrap = false;
/// Mining params
unsigned mining = ~(unsigned)0;
int miners = -1;
bool forceMining = false;
KeyPair us = KeyPair::create();
Address coinbase = us.address();
/// Structured logging params
bool structuredLogging = false;
string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S";
string clientName;
/// Transaction params
TransactionPriority priority = TransactionPriority::Medium;
double etherPrice = 30.679;
double blockFees = 15.0;
// Init defaults
Defaults::get();
// Our address.
KeyPair us = KeyPair::create();
Address coinbase = us.address();
string configFile = getDataDir() + "/config.rlp";
bytes b = contents(configFile);
if (b.size())
@ -255,12 +293,6 @@ int main(int argc, char** argv)
us = KeyPair(config[0].toHash<Secret>());
coinbase = config[1].toHash<Address>();
}
else
{
RLPStream config(2);
config << us.secret() << coinbase;
writeFile(configFile, config.out());
}
for (int i = 1; i < argc; ++i)
{
@ -275,6 +307,37 @@ int main(int argc, char** argv)
remoteHost = argv[++i];
else if ((arg == "-p" || arg == "--port") && i + 1 < argc)
remotePort = (short)atoi(argv[++i]);
else if ((arg == "-I" || arg == "--import") && i + 1 < argc)
{
mode = OperationMode::Import;
filename = argv[++i];
}
else if ((arg == "-E" || arg == "--export") && i + 1 < argc)
{
mode = OperationMode::Export;
filename = argv[++i];
}
else if (arg == "--format" && i + 1 < argc)
{
string m = argv[++i];
if (m == "binary")
exportFormat = Format::Binary;
else if (m == "hex")
exportFormat = Format::Hex;
else if (m == "human")
exportFormat = Format::Human;
else
{
cerr << "Bad " << arg << " option: " << m << endl;
return -1;
}
}
else if (arg == "--to" && i + 1 < argc)
exportTo = argv[++i];
else if (arg == "--from" && i + 1 < argc)
exportFrom = argv[++i];
else if (arg == "--only" && i + 1 < argc)
exportTo = exportFrom = argv[++i];
else if ((arg == "-n" || arg == "--upnp") && i + 1 < argc)
{
string m = argv[++i];
@ -284,7 +347,7 @@ int main(int argc, char** argv)
upnp = false;
else
{
cerr << "Invalid -n/--upnp option: " << m << endl;
cerr << "Bad " << arg << " option: " << m << endl;
return -1;
}
}
@ -301,14 +364,13 @@ int main(int argc, char** argv)
}
catch (BadHexCharacter& _e)
{
cwarn << "invalid hex character, coinbase rejected";
cwarn << boost::diagnostic_information(_e);
break;
cerr << "Bad hex in " << arg << " option: " << argv[i] << endl;
return -1;
}
catch (...)
{
cwarn << "coinbase rejected";
break;
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if ((arg == "-s" || arg == "--secret") && i + 1 < argc)
us = KeyPair(h256(fromHex(argv[++i])));
@ -321,6 +383,7 @@ int main(int argc, char** argv)
else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc)
{
string m = boost::to_lower_copy(string(argv[++i]));
mode = OperationMode::DAGInit;
if (m == "next")
initDAG = PendingBlock;
else if (m == "this")
@ -420,9 +483,9 @@ int main(int argc, char** argv)
{
string m = argv[++i];
if (m == "full")
mode = NodeMode::Full;
nodeMode = NodeMode::Full;
else if (m == "peer")
mode = NodeMode::PeerServer;
nodeMode = NodeMode::PeerServer;
else
{
cerr << "Unknown mode: " << m << endl;
@ -449,17 +512,20 @@ int main(int argc, char** argv)
}
}
{
RLPStream config(2);
config << us.secret() << coinbase;
writeFile(configFile, config.out());
}
// Two codepaths is necessary since named block require database, but numbered
// blocks are superuseful to have when database is already open in another process.
if (initDAG < NoDAGInit)
if (mode == OperationMode::DAGInit && !(initDAG == LatestBlock || initDAG == PendingBlock))
doInitDAG(initDAG);
if (!clientName.empty())
clientName += "/";
cout << credits();
StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat);
VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter);
auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp);
@ -469,18 +535,95 @@ int main(int argc, char** argv)
clientImplString,
dbPath,
killChain,
mode == NodeMode::Full ? set<string>{"eth", "shh"} : set<string>(),
nodeMode == NodeMode::Full ? set<string>{"eth", "shh"} : set<string>(),
netPrefs,
&nodesState,
miners
);
if (initDAG == LatestBlock || initDAG == PendingBlock)
if (mode == OperationMode::DAGInit)
doInitDAG(web3.ethereum()->blockChain().number() + (initDAG == PendingBlock ? 30000 : 0));
auto toNumber = [&](string const& s) -> unsigned {
if (s == "latest")
return web3.ethereum()->number();
if (s.size() == 64 || (s.size() == 66 && s.substr(0, 2) == "0x"))
return web3.ethereum()->blockChain().number(h256(s));
try {
return stol(s);
}
catch (...)
{
cerr << "Bad block number/hash option: " << s << endl;
exit(-1);
}
};
if (mode == OperationMode::Export)
{
ofstream fout(filename, std::ofstream::binary);
ostream& out = (filename.empty() || filename == "--") ? cout : fout;
unsigned last = toNumber(exportTo);
for (unsigned i = toNumber(exportFrom); i <= last; ++i)
{
bytes block = web3.ethereum()->blockChain().block(web3.ethereum()->blockChain().numberHash(i));
switch (exportFormat)
{
case Format::Binary: out.write((char const*)block.data(), block.size()); break;
case Format::Hex: out << toHex(block) << endl; break;
case Format::Human: out << RLP(block) << endl; break;
default:;
}
}
return 0;
}
if (mode == OperationMode::Import)
{
ifstream fin(filename, std::ifstream::binary);
istream& in = (filename.empty() || filename == "--") ? cin : fin;
unsigned alreadyHave = 0;
unsigned good = 0;
unsigned futureTime = 0;
unsigned unknownParent = 0;
unsigned bad = 0;
while (in.peek() != -1)
{
bytes block(8);
in.read((char*)block.data(), 8);
block.resize(RLP(block, RLP::LaisezFaire).actualSize());
in.read((char*)block.data() + 8, block.size() - 8);
try
{
web3.ethereum()->injectBlock(block);
good++;
}
catch (AlreadyHaveBlock const&)
{
alreadyHave++;
}
catch (UnknownParent const&)
{
unknownParent++;
}
catch (FutureTime const&)
{
futureTime++;
}
catch (...)
{
bad++;
}
}
cout << (good + bad + futureTime + unknownParent + alreadyHave) << " total: " << good << " ok, " << alreadyHave << " got, " << futureTime << " future, " << unknownParent << " unknown parent, " << bad << " malformed." << endl;
return 0;
}
cout << credits();
web3.setIdealPeerCount(peers);
std::shared_ptr<eth::BasicGasPricer> gasPricer = make_shared<eth::BasicGasPricer>(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000));
eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr;
eth::Client* c = nodeMode == NodeMode::Full ? web3.ethereum() : nullptr;
StructuredLogger::starting(clientImplString, dev::Version);
if (c)
{
@ -553,10 +696,9 @@ int main(int argc, char** argv)
}
else if (cmd == "connect")
{
string addr;
unsigned port;
iss >> addr >> port;
web3.addNode(p2p::NodeId(), addr + ":" + toString(port ? port : p2p::c_defaultIPPort));
string addrPort;
iss >> addrPort;
web3.addNode(p2p::NodeId(), addrPort);
}
else if (cmd == "netstop")
{

4
evmjit/libevmjit/ExecutionEngine.cpp

@ -88,10 +88,10 @@ void parseOptions()
//cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler");
// FIXME: LLVM workaround:
// Manually select instruction scheduler other than "source".
// Manually select instruction scheduler. Confirmed bad schedulers: source, list-burr, list-hybrid.
// "source" scheduler has a bug: http://llvm.org/bugs/show_bug.cgi?id=22304
auto envLine = std::getenv("EVMJIT");
auto commandLine = std::string{"evmjit "} + (envLine ? envLine : "") + " -pre-RA-sched=list-burr\0";
auto commandLine = std::string{"evmjit "} + (envLine ? envLine : "") + " -pre-RA-sched=list-ilp\0";
static const auto c_maxArgs = 20;
char const* argv[c_maxArgs] = {nullptr, };
auto arg = std::strtok(&*commandLine.begin(), " ");

21
exp/CMakeLists.txt

@ -10,8 +10,27 @@ set(EXECUTABLE exp)
add_executable(${EXECUTABLE} ${SRC_LIST})
target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES})
if (READLINE_FOUND)
target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES})
endif()
if (JSONRPC)
target_link_libraries(${EXECUTABLE} web3jsonrpc)
endif()
target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} ethereum)
target_link_libraries(${EXECUTABLE} p2p)
if (ETHASHCL)
target_link_libraries(${EXECUTABLE} ethash-cl)
target_link_libraries(${EXECUTABLE} ethash)
target_link_libraries(${EXECUTABLE} OpenCL)
endif()
install( TARGETS ${EXECUTABLE} DESTINATION bin)

26
exp/main.cpp

@ -19,18 +19,26 @@
* @date 2014
* Ethereum client.
*/
#if ETH_ETHASHCL
#define __CL_ENABLE_EXCEPTIONS
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS
#include "libethash-cl/cl.hpp"
#endif
#include <functional>
#include <libethereum/AccountDiff.h>
#include <libdevcore/RangeMask.h>
#include <libdevcore/Log.h>
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h>
#include <libdevcore/TransientDirectory.h>
#include <libdevcore/CommonIO.h>
#include <libdevcrypto/TrieDB.h>
#include <libp2p/All.h>
#include <libethereum/DownloadMan.h>
#include <libethcore/Ethasher.h>
#include <libethcore/ProofOfWork.h>
#include <libethereum/All.h>
#include <libethereum/AccountDiff.h>
#include <libethereum/DownloadMan.h>
#include <liblll/All.h>
#include <libwhisper/WhisperPeer.h>
#include <libwhisper/WhisperHost.h>
@ -101,6 +109,18 @@ int main()
#else
int main()
{
#if ETH_ETHASHCL
EthashCL ecl;
BlockInfo genesis = CanonBlockChain::genesis();
genesis.difficulty = 1 << 18;
cdebug << (h256)u256((bigint(1) << 256) / genesis.difficulty);
std::pair<MineInfo, Ethash::Proof> r;
while (!r.first.completed)
r = ecl.mine(genesis, 1000);
cdebug << r.second.mixHash << r.second.nonce;
EthashCL::assignResult(r.second, genesis);
assert(EthashCPU::verify(genesis));
#endif
return 0;
}
#endif

1
libdevcore/CMakeLists.txt

@ -28,6 +28,7 @@ endif()
target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES})
# transitive dependencies for windows executables

2
libdevcore/Common.cpp

@ -27,7 +27,7 @@ using namespace dev;
namespace dev
{
char const* Version = "0.9.6";
char const* Version = "0.9.7";
}

6
libdevcore/CommonIO.cpp

@ -58,7 +58,7 @@ string dev::memDump(bytes const& _bytes, unsigned _width, bool _html)
}
// Don't forget to delete[] later.
bytesRef dev::contentsNew(std::string const& _file)
bytesRef dev::contentsNew(std::string const& _file, bytesRef _dest)
{
std::ifstream is(_file, std::ifstream::binary);
if (!is)
@ -68,8 +68,10 @@ bytesRef dev::contentsNew(std::string const& _file)
streamoff length = is.tellg();
if (length == 0) // return early, MSVC does not like reading 0 bytes
return bytesRef();
if (!_dest.empty() && _dest.size() != (unsigned)length)
return bytesRef();
is.seekg (0, is.beg);
bytesRef ret(new byte[length], length);
bytesRef ret = _dest.empty() ? bytesRef(new byte[length], length) : _dest;
is.read((char*)ret.data(), length);
is.close();
return ret;

2
libdevcore/CommonIO.h

@ -46,7 +46,7 @@ namespace dev
bytes contents(std::string const& _file);
std::string contentsString(std::string const& _file);
/// Retrieve and returns the allocated contents of the given file. If the file doesn't exist or isn't readable, returns nullptr. Don't forget to delete [] when finished.
bytesRef contentsNew(std::string const& _file);
bytesRef contentsNew(std::string const& _file, bytesRef _dest = bytesRef());
/// Write the given binary data into the given file, replacing the file if it pre-exists.
void writeFile(std::string const& _file, bytesConstRef _data);

2
libdevcore/Log.cpp

@ -43,7 +43,7 @@ void dev::simpleDebugOut(std::string const& _s, char const*)
static Mutex s_lock;
Guard l(s_lock);
cout << _s << endl << flush;
cerr << _s << endl << flush;
// helpful to use OutputDebugString on windows
#ifdef _WIN32

2
libdevcore/RLP.cpp

@ -107,7 +107,7 @@ unsigned RLP::actualSize() const
if (isSingleByte())
return 1;
if (isData() || isList())
return payload().data() - m_data.data() + length();
return payloadOffset() + length();
return 0;
}

5
libdevcore/RLP.h

@ -290,7 +290,7 @@ public:
RLPs toList() const;
/// @returns the data payload. Valid for all types.
bytesConstRef payload() const { return isSingleByte() ? m_data.cropped(0, 1) : m_data.cropped(1 + lengthSize()); }
bytesConstRef payload() const { return m_data.cropped(payloadOffset()); }
/// @returns the theoretical size of this item.
/// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work.
@ -309,6 +309,9 @@ private:
/// @returns the size in bytes of the payload, as given by the RLP as opposed to as inferred from m_data.
unsigned length() const;
/// @returns the number of bytes into the data that the payload starts.
unsigned payloadOffset() const { return isSingleByte() ? 0 : (1 + lengthSize()); }
/// @returns the number of data items.
unsigned items() const;

1
libdevcore/RangeMask.h

@ -25,6 +25,7 @@
#include <utility>
#include <vector>
#include <iostream>
#include <assert.h>
namespace dev
{

4
libtestutils/TransientDirectory.cpp → libdevcore/TransientDirectory.cpp

@ -20,11 +20,11 @@
*/
#include <boost/filesystem.hpp>
#include <libdevcore/Exceptions.h>
#include "Exceptions.h"
#include "TransientDirectory.h"
#include "CommonIO.h"
using namespace std;
using namespace dev;
using namespace dev::test;
TransientDirectory::TransientDirectory():
TransientDirectory((boost::filesystem::temp_directory_path() / "eth_transient" / toString(FixedHash<4>::random())).string())

4
libtestutils/TransientDirectory.h → libdevcore/TransientDirectory.h

@ -22,12 +22,9 @@
#pragma once
#include <string>
#include "Common.h"
namespace dev
{
namespace test
{
/**
* @brief temporary directory implementation
@ -48,4 +45,3 @@ private:
};
}
}

12
libdevcore/Worker.cpp

@ -29,11 +29,11 @@ using namespace dev;
void Worker::startWorking()
{
cdebug << "startWorking for thread" << m_name;
cnote << "startWorking for thread" << m_name;
Guard l(x_work);
if (m_work)
return;
cdebug << "Spawning" << m_name;
cnote << "Spawning" << m_name;
m_stop = false;
m_work.reset(new thread([&]()
{
@ -45,21 +45,21 @@ void Worker::startWorking()
this_thread::sleep_for(chrono::milliseconds(m_idleWaitMs));
doWork();
}
cdebug << "Finishing up worker thread";
cnote << "Finishing up worker thread";
doneWorking();
}));
}
void Worker::stopWorking()
{
cdebug << "stopWorking for thread" << m_name;
cnote << "stopWorking for thread" << m_name;
Guard l(x_work);
if (!m_work)
return;
cdebug << "Stopping" << m_name;
cnote << "Stopping" << m_name;
m_stop = true;
m_work->join();
m_work.reset();
cdebug << "Stopped" << m_name;
cnote << "Stopped" << m_name;
}

6
libdevcrypto/Common.cpp

@ -37,9 +37,9 @@ static Secp256k1 s_secp256k1;
bool dev::SignatureStruct::isValid() const
{
if (this->v > 1 ||
this->r >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") ||
this->s >= h256("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"))
if (v > 1 ||
r >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") ||
s >= h256("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"))
return false;
return true;
}

2
libethash/util.h

@ -29,7 +29,7 @@ extern "C" {
#ifdef _MSC_VER
void debugf(const char *str, ...);
#else
#define debugf printf
#define debugf(...) fprintf(stderr, __VA_ARGS__)
#endif
static inline uint32_t min_u32(uint32_t a, uint32_t b)

7
libethcore/BlockInfo.cpp

@ -75,6 +75,13 @@ h256 const& BlockInfo::hash() const
return m_hash;
}
h256 const& BlockInfo::boundary() const
{
if (!m_boundary)
m_boundary = (h256)(u256)((bigint(1) << 256) / difficulty);
return m_boundary;
}
BlockInfo BlockInfo::fromHeader(bytesConstRef _header, Strictness _s, h256 const& _h)
{
BlockInfo ret;

4
libethcore/BlockInfo.h

@ -118,7 +118,7 @@ public:
void clear();
void noteDirty() const { m_hash = m_seedHash = h256(); }
void noteDirty() const { m_hash = m_seedHash = m_boundary = h256(); }
void populateFromHeader(RLP const& _header, Strictness _s = IgnoreNonce, h256 const& _h = h256());
void populate(bytesConstRef _block, Strictness _s = IgnoreNonce, h256 const& _h = h256());
@ -131,6 +131,7 @@ public:
u256 selectGasLimit(BlockInfo const& _parent) const;
h256 const& seedHash() const;
h256 const& hash() const;
h256 const& boundary() const;
/// sha3 of the header only.
h256 headerHash(IncludeNonce _n) const;
@ -139,6 +140,7 @@ public:
private:
mutable h256 m_seedHash;
mutable h256 m_hash; ///< SHA3 hash of the block header! Not serialised.
mutable h256 m_boundary; ///< 2^256 / difficulty
};
inline std::ostream& operator<<(std::ostream& _out, BlockInfo const& _bi)

38
libethcore/Ethasher.cpp

@ -123,6 +123,44 @@ ethash_params Ethasher::params(BlockInfo const& _header)
return params((unsigned)_header.number);
}
void Ethasher::readFull(BlockInfo const& _header, void* _dest)
{
if (!m_fulls.count(_header.seedHash()))
{
// @memoryleak @bug place it on a pile for deletion - perhaps use shared_ptr.
/* if (!m_fulls.empty())
{
delete [] m_fulls.begin()->second.data();
m_fulls.erase(m_fulls.begin());
}*/
try {
boost::filesystem::create_directories(getDataDir("ethash"));
} catch (...) {}
auto info = rlpList(c_ethashRevision, _header.seedHash());
std::string oldMemoFile = getDataDir("ethash") + "/full";
std::string memoFile = getDataDir("ethash") + "/full-R" + toString(c_ethashRevision) + "-" + toHex(_header.seedHash().ref().cropped(0, 8));
if (boost::filesystem::exists(oldMemoFile) && contents(oldMemoFile + ".info") == info)
{
// memofile valid - rename.
boost::filesystem::rename(oldMemoFile, memoFile);
}
IGNORE_EXCEPTIONS(boost::filesystem::remove(oldMemoFile));
IGNORE_EXCEPTIONS(boost::filesystem::remove(oldMemoFile + ".info"));
ethash_params p = params((unsigned)_header.number);
bytesRef r = contentsNew(memoFile, bytesRef((byte*)_dest, p.full_size));
if (!r)
{
auto c = light(_header);
ethash_prep_full(_dest, &p, c);
writeFile(memoFile, bytesConstRef((byte*)_dest, p.full_size));
}
}
}
ethash_params Ethasher::params(unsigned _n)
{
ethash_params p;

2
libethcore/Ethasher.h

@ -56,6 +56,8 @@ public:
static ethash_params params(BlockInfo const& _header);
static ethash_params params(unsigned _n);
void readFull(BlockInfo const& _header, void* _dest);
struct Result
{
h256 value;

146
libethcore/ProofOfWork.cpp

@ -33,32 +33,6 @@
#include <libdevcore/Common.h>
#if ETH_ETHASHCL
#include <libethash-cl/ethash_cl_miner.h>
#define ETHASH_REVISION REVISION
#define ETHASH_DATASET_BYTES_INIT DATASET_BYTES_INIT
#define ETHASH_DATASET_BYTES_GROWTH DATASET_BYTES_GROWTH
#define ETHASH_CACHE_BYTES_INIT CACHE_BYTES_INIT
#define ETHASH_CACHE_BYTES_GROWTH CACHE_BYTES_GROWTH
#define ETHASH_DAGSIZE_BYTES_INIT DAGSIZE_BYTES_INIT
#define ETHASH_DAG_GROWTH DAG_GROWTH
#define ETHASH_EPOCH_LENGTH EPOCH_LENGTH
#define ETHASH_MIX_BYTES MIX_BYTES
#define ETHASH_HASH_BYTES HASH_BYTES
#define ETHASH_DATASET_PARENTS DATASET_PARENTS
#define ETHASH_CACHE_ROUNDS CACHE_ROUNDS
#define ETHASH_ACCESSES ACCESSES
#undef REVISION
#undef DATASET_BYTES_INIT
#undef DATASET_BYTES_GROWTH
#undef CACHE_BYTES_INIT
#undef CACHE_BYTES_GROWTH
#undef DAGSIZE_BYTES_INIT
#undef DAG_GROWTH
#undef EPOCH_LENGTH
#undef MIX_BYTES
#undef HASH_BYTES
#undef DATASET_PARENTS
#undef CACHE_ROUNDS
#undef ACCESSES
#endif
#include "BlockInfo.h"
#include "Ethasher.h"
@ -71,12 +45,12 @@ namespace dev
namespace eth
{
bool EthashCPU::verify(BlockInfo const& _header)
bool EthashPoW::verify(BlockInfo const& _header)
{
return Ethasher::verify(_header);
}
std::pair<MineInfo, EthashCPU::Proof> EthashCPU::mine(BlockInfo const& _header, unsigned _msTimeout, bool _continue, bool _turbo)
std::pair<MineInfo, EthashCPU::Proof> EthashCPU::mine(BlockInfo const& _header, unsigned _msTimeout, bool _continue)
{
Ethasher::Miner m(_header);
@ -93,8 +67,6 @@ std::pair<MineInfo, EthashCPU::Proof> EthashCPU::mine(BlockInfo const& _header,
//
// evaluate until we run out of time
auto startTime = std::chrono::steady_clock::now();
if (!_turbo)
std::this_thread::sleep_for(std::chrono::milliseconds(_msTimeout * 90 / 100));
double best = 1e99; // high enough to be effectively infinity :)
Proof result;
unsigned hashCount = 0;
@ -128,19 +100,19 @@ std::pair<MineInfo, EthashCPU::Proof> EthashCPU::mine(BlockInfo const& _header,
return ret;
}
#if ETH_ETHASHCL
#if ETH_ETHASHCL || !ETH_TRUE
/*
struct ethash_cl_search_hook
{
// reports progress, return true to abort
virtual bool found(uint64_t const* nonces, uint32_t count) = 0;
virtual bool searched(uint64_t start_nonce, uint32_t count) = 0;
};
class ethash_cl_miner
{
public:
struct search_hook
{
// reports progress, return true to abort
virtual bool found(uint64_t const* nonces, uint32_t count) = 0;
virtual bool searched(uint64_t start_nonce, uint32_t count) = 0;
};
ethash_cl_miner();
bool init(ethash_params const& params, const uint8_t seed[32], unsigned workgroup_size = 64);
@ -150,77 +122,87 @@ public:
};
*/
struct EthashCLHook: public ethash_cl_search_hook
struct EthashCLHook: public ethash_cl_miner::search_hook
{
virtual bool found(uint64_t const* _nonces, uint32_t _count)
void abort()
{
if (m_aborted)
return;
cdebug << "Attempting to abort";
m_abort = true;
for (unsigned timeout = 0; timeout < 100 && !m_aborted; ++timeout)
std::this_thread::sleep_for(chrono::milliseconds(30));
if (!m_aborted)
cwarn << "Couldn't abort. Abandoning OpenCL process.";
m_aborted = m_abort = false;
m_found.clear();
}
vector<Nonce> fetchFound() { vector<Nonce> ret; Guard l(x_all); std::swap(ret, m_found); return ret; }
uint64_t fetchTotal() { Guard l(x_all); auto ret = m_total; m_total = 0; return ret; }
protected:
virtual bool found(uint64_t const* _nonces, uint32_t _count) override
{
Guard l(x_all);
for (unsigned i = 0; i < _count; ++i)
found.push_back((Nonce)(u64)_nonces[i]);
if (abort)
{
aborted = true;
return true;
}
return false;
m_found.push_back((Nonce)(u64)_nonces[i]);
m_aborted = true;
cdebug << "Found nonces: " << vector<uint64_t>(_nonces, _nonces + _count);
return true;
}
virtual bool searched(uint64_t _startNonce, uint32_t _count)
virtual bool searched(uint64_t _startNonce, uint32_t _count) override
{
Guard l(x_all);
total += _count;
last = _startNonce + _count;
if (abort)
cdebug << "Searched" << _count << "from" << _startNonce;
m_total += _count;
m_last = _startNonce + _count;
if (m_abort)
{
aborted = true;
m_aborted = true;
return true;
}
return false;
}
vector<Nonce> fetchFound() { vector<Nonce> ret; Guard l(x_all); std::swap(ret, found); return ret; }
uint64_t fetchTotal() { Guard l(x_all); auto ret = total; total = 0; return ret; }
private:
Mutex x_all;
vector<Nonce> found;
uint64_t total;
uint64_t last;
bool abort = false;
bool aborted = false;
vector<Nonce> m_found;
uint64_t m_total;
uint64_t m_last;
bool m_abort = false;
bool m_aborted = true;
};
EthashCL::EthashCL():
m_miner(new ethash_cl_miner),
m_hook(new EthashCLHook)
{
}
EthashCL::~EthashCL()
{
m_hook->abort = true;
for (unsigned timeout = 0; timeout < 100 && !m_hook->aborted; ++timeout)
std::this_thread::sleep_for(chrono::milliseconds(30));
if (!m_hook->aborted)
cwarn << "Couldn't abort. Abandoning OpenCL process.";
}
bool EthashCL::verify(BlockInfo const& _header)
{
return Ethasher::verify(_header);
}
std::pair<MineInfo, Ethash::Proof> EthashCL::mine(BlockInfo const& _header, unsigned _msTimeout, bool, bool)
std::pair<MineInfo, Ethash::Proof> EthashCL::mine(BlockInfo const& _header, unsigned _msTimeout, bool)
{
if (m_lastHeader.seedHash() != _header.seedHash())
if (!m_lastHeader || m_lastHeader.seedHash() != _header.seedHash())
{
m_miner->init(Ethasher::params(_header), _header.seedHash().data());
// TODO: reinit probably won't work when seed changes.
if (m_miner)
m_hook->abort();
m_miner.reset(new ethash_cl_miner);
auto cb = [&](void* d) {
Ethasher::get()->readFull(_header, d);
};
m_miner->init(Ethasher::params(_header), cb, 32);
}
if (m_lastHeader != _header)
{
m_hook->abort();
static std::random_device s_eng;
uint64_t tryNonce = (uint64_t)(u64)(m_last = Nonce::random(s_eng));
m_miner->search(_header.headerHash(WithoutNonce).data(), tryNonce, *m_hook);
auto hh = _header.headerHash(WithoutNonce);
uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)_header.boundary() >> 192);
m_miner->search(hh.data(), upper64OfBoundary, *m_hook);
}
m_lastHeader = _header;
@ -228,10 +210,14 @@ std::pair<MineInfo, Ethash::Proof> EthashCL::mine(BlockInfo const& _header, unsi
auto found = m_hook->fetchFound();
if (!found.empty())
{
h256 mixHash; // ?????
return std::make_pair(MineInfo{0.0, 1e99, 0, true}, EthashCL::Proof((Nonce)(u64)found[0], mixHash));
for (auto const& n: found)
{
auto result = Ethasher::eval(_header, n);
if (result.value < _header.boundary())
return std::make_pair(MineInfo(true), EthashCL::Proof{n, result.mixHash});
}
}
return std::make_pair(MineInfo{0.0, 1e99, 0, false}, EthashCL::Proof());
return std::make_pair(MineInfo(false), EthashCL::Proof());
}
#endif

40
libethcore/ProofOfWork.h

@ -42,6 +42,8 @@ namespace eth
struct MineInfo
{
MineInfo() = default;
MineInfo(bool _completed): completed(_completed) {}
void combine(MineInfo const& _m) { requirement = std::max(requirement, _m.requirement); best = std::min(best, _m.best); hashes += _m.hashes; completed = completed || _m.completed; }
double requirement = 0;
double best = 1e99;
@ -49,7 +51,7 @@ struct MineInfo
bool completed = false;
};
class EthashCPU
class EthashPoW
{
public:
struct Proof
@ -59,36 +61,39 @@ public:
};
static bool verify(BlockInfo const& _header);
std::pair<MineInfo, Proof> mine(BlockInfo const& _header, unsigned _msTimeout = 100, bool _continue = true, bool _turbo = false);
static void assignResult(Proof const& _r, BlockInfo& _header) { _header.nonce = _r.nonce; _header.mixHash = _r.mixHash; }
virtual unsigned defaultTimeout() const { return 100; }
virtual std::pair<MineInfo, Proof> mine(BlockInfo const& _header, unsigned _msTimeout = 100, bool _continue = true) = 0;
};
class EthashCPU: public EthashPoW
{
public:
std::pair<MineInfo, Proof> mine(BlockInfo const& _header, unsigned _msTimeout = 100, bool _continue = true) override;
protected:
Nonce m_last;
};
#if ETH_ETHASHCL
class EthashCL
#if ETH_ETHASHCL || !ETH_TRUE
class EthashCLHook;
class EthashCL: public EthashPoW
{
public:
struct Proof
{
Nonce nonce;
h256 mixHash;
};
EthashCL();
~EthashCL();
static bool verify(BlockInfo const& _header);
std::pair<MineInfo, Proof> mine(BlockInfo const& _header, unsigned _msTimeout = 100, bool _continue = true, bool _turbo = false);
static void assignResult(Proof const& _r, BlockInfo& _header) { _header.nonce = _r.nonce; _header.mixHash = _r.mixHash; }
std::pair<MineInfo, Proof> mine(BlockInfo const& _header, unsigned _msTimeout = 100, bool _continue = true) override;
unsigned defaultTimeout() const override { return 500; }
protected:
Nonce m_last;
BlockInfo m_lastHeader;
Nonce m_mined;
std::unique_ptr<ethash_cl_miner> m_miner;
std::unique_ptr<ethash_cl_search_hook> m_hook;
std::unique_ptr<EthashCLHook> m_hook;
};
using Ethash = EthashCL;
@ -103,8 +108,9 @@ public:
using Proof = Nonce;
static bool verify(BlockInfo const& _header) { return (bigint)(u256)Evaluator::eval(_header.headerHash(WithoutNonce), _header.nonce) <= (bigint(1) << 256) / _header.difficulty; }
inline std::pair<MineInfo, Proof> mine(BlockInfo const& _header, unsigned _msTimeout = 100, bool _continue = true, bool _turbo = false);
inline std::pair<MineInfo, Proof> mine(BlockInfo const& _header, unsigned _msTimeout = 100, bool _continue = true);
static void assignResult(Proof const& _r, BlockInfo& _header) { _header.nonce = _r; }
unsigned defaultTimeout() const { return 100; }
protected:
Nonce m_last;
@ -121,7 +127,7 @@ using SHA3ProofOfWork = ProofOfWorkEngine<SHA3Evaluator>;
using ProofOfWork = Ethash;
template <class Evaluator>
std::pair<MineInfo, typename ProofOfWorkEngine<Evaluator>::Proof> ProofOfWorkEngine<Evaluator>::mine(BlockInfo const& _header, unsigned _msTimeout, bool _continue, bool _turbo)
std::pair<MineInfo, typename ProofOfWorkEngine<Evaluator>::Proof> ProofOfWorkEngine<Evaluator>::mine(BlockInfo const& _header, unsigned _msTimeout, bool _continue)
{
auto headerHashWithoutNonce = _header.headerHash(WithoutNonce);
auto difficulty = _header.difficulty;
@ -138,8 +144,6 @@ std::pair<MineInfo, typename ProofOfWorkEngine<Evaluator>::Proof> ProofOfWorkEng
//
// evaluate until we run out of time
auto startTime = std::chrono::steady_clock::now();
if (!_turbo)
std::this_thread::sleep_for(std::chrono::milliseconds(_msTimeout * 90 / 100));
double best = 1e99; // high enough to be effectively infinity :)
ProofOfWorkEngine<Evaluator>::Proof solution;
unsigned h = 0;

10
libethereum/BlockChain.cpp

@ -240,7 +240,7 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
return;
}
lastHash = bi.hash();
import(b, s.db(), true);
import(b, s.db(), Aversion::ImportOldBlocks);
}
catch (...)
{
@ -334,7 +334,7 @@ tuple<h256s, h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st
return make_tuple(fresh, dead, _bq.doneDrain(badBlocks));
}
pair<h256s, h256> BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force) noexcept
pair<h256s, h256> BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, Aversion _force) noexcept
{
try
{
@ -347,7 +347,7 @@ pair<h256s, h256> BlockChain::attemptImport(bytes const& _block, OverlayDB const
}
}
pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db, Aversion _force)
{
//@tidy This is a behemoth of a method - could do to be split into a few smaller ones.
@ -386,7 +386,7 @@ pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db,
#endif
// Check block doesn't already exist first!
if (isKnown(bi.hash()) && !_force)
if (isKnown(bi.hash()) && _force == Aversion::AvoidOldBlocks)
{
clog(BlockChainNote) << bi.hash() << ": Not new.";
BOOST_THROW_EXCEPTION(AlreadyHaveBlock());
@ -601,7 +601,7 @@ pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db,
m_extrasDB->Put(m_writeOptions, toSlice(h, ExtraTransactionAddress), (ldb::Slice)dev::ref(m_transactionAddresses[h].rlp()));
}
clog(BlockChainNote) << " Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(route);
clog(BlockChainNote) << " Imported and best" << td << " (#" << bi.number << "). Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(route);
noteCanonChanged();
StructuredLogger::chainNewHead(

10
libethereum/BlockChain.h

@ -80,6 +80,12 @@ enum {
using ProgressCallback = std::function<void(unsigned, unsigned)>;
enum class Aversion
{
AvoidOldBlocks,
ImportOldBlocks
};
/**
* @brief Implements the blockchain database. All data this gives is disk-backed.
* @threadsafe
@ -102,11 +108,11 @@ public:
/// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB.
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain.
std::pair<h256s, h256> attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force = false) noexcept;
std::pair<h256s, h256> attemptImport(bytes const& _block, OverlayDB const& _stateDB, Aversion _force = Aversion::AvoidOldBlocks) noexcept;
/// Import block into disk-backed DB
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain.
std::pair<h256s, h256> import(bytes const& _block, OverlayDB const& _stateDB, bool _force = false);
std::pair<h256s, h256> import(bytes const& _block, OverlayDB const& _stateDB, Aversion _force = Aversion::AvoidOldBlocks);
/// Returns true if the given block is known (though not necessarily a part of the canon chain).
bool isKnown(h256 const& _hash) const;

7
libethereum/CMakeLists.txt

@ -25,19 +25,18 @@ else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES})
target_link_libraries(${EXECUTABLE} evm)
target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} whisper)
target_link_libraries(${EXECUTABLE} p2p)
target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES})
target_link_libraries(${EXECUTABLE} secp256k1)
if (ETHASHCL)
target_link_libraries(${EXECUTABLE} ethash-cl)
target_link_libraries(${EXECUTABLE} OpenCL)
endif ()
if (CMAKE_COMPILER_IS_MINGW)

39
libethereum/Client.cpp

@ -259,16 +259,28 @@ void Client::clearPending()
noteChanged(changeds);
}
template <class T>
static string filtersToString(T const& _fs)
{
stringstream ret;
ret << "{";
unsigned i = 0;
for (h256 const& f: _fs)
ret << (i++ ? ", " : "") << (f == PendingChangedFilter ? "pending" : f == ChainChangedFilter ? "chain" : f.abridged());
ret << "}";
return ret.str();
}
void Client::noteChanged(h256Set const& _filters)
{
Guard l(x_filtersWatches);
if (_filters.size())
cnote << "noteChanged(" << _filters << ")";
cnote << "noteChanged(" << filtersToString(_filters) << ")";
// accrue all changes left in each filter into the watches.
for (auto& w: m_watches)
if (_filters.count(w.second.id))
{
cwatch << "!!!" << w.first << w.second.id;
cwatch << "!!!" << w.first << (m_filters.count(w.second.id) ? w.second.id.abridged() : w.second.id == PendingChangedFilter ? "pending" : w.second.id == ChainChangedFilter ? "chain" : "???");
if (m_filters.count(w.second.id)) // Normal filtering watch
w.second.changes += m_filters.at(w.second.id).changes;
else // Special ('pending'/'latest') watch
@ -333,10 +345,10 @@ void Client::setForceMining(bool _enable)
void Client::setMiningThreads(unsigned _threads)
{
stopMining();
#if ETH_ETHASHCL
unsigned t = 1;
#else
auto t = _threads ? _threads : thread::hardware_concurrency();
#if ETH_ETHASHCL || !ETH_TRUE
if (m_turboMining)
t = 1;
#endif
WriteGuard l(x_localMiners);
m_localMiners.clear();
@ -355,6 +367,15 @@ MineProgress Client::miningProgress() const
return ret;
}
uint64_t Client::hashrate() const
{
uint64_t ret = 0;
ReadGuard l(x_localMiners);
for (LocalMiner const& m: m_localMiners)
ret += m.miningProgress().hashes / m.miningProgress().ms;
return ret / 1000;
}
std::list<MineInfo> Client::miningHistory()
{
std::list<MineInfo> ret;
@ -397,7 +418,7 @@ void Client::setupState(State& _s)
_s.commitToMine(m_bc);
}
ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice)
ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice, Address const& _from)
{
ExecutionResult ret;
try
@ -407,10 +428,10 @@ ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256
{
ReadGuard l(x_stateDB);
temp = m_postMine;
temp.addBalance(Address(), _value + _gasPrice * _gas);
temp.addBalance(_from, _value + _gasPrice * _gas);
}
Executive e(temp, LastHashes(), 0);
if (!e.call(_dest, _dest, Address(), _value, _gasPrice, &_data, _gas, Address()))
if (!e.call(_dest, _dest, _from, _value, _gasPrice, &_data, _gas, _from))
e.go();
ret = e.executionResult();
}
@ -522,7 +543,7 @@ void Client::doWork()
clog(ClientChat) << "Live block:" << h.abridged();
for (auto const& th: m_bc.transactionHashes(h))
{
clog(ClientNote) << "Safely dropping transaction " << th;
clog(ClientNote) << "Safely dropping transaction " << th.abridged();
m_tq.drop(th);
}
}

25
libethereum/Client.h

@ -159,7 +159,7 @@ public:
using Interface::call; // to remove warning about hiding virtual function
/// Makes the given call. Nothing is recorded into the state. This cheats by creating a null address and endowing it with a lot of ETH.
ExecutionResult call(Address _dest, bytes const& _data = bytes(), u256 _gas = 125000, u256 _value = 0, u256 _gasPrice = 1 * ether);
ExecutionResult call(Address _dest, bytes const& _data = bytes(), u256 _gas = 125000, u256 _value = 0, u256 _gasPrice = 1 * ether, Address const& _from = Address());
/// Get the remaining gas limit in this block.
virtual u256 gasLimitRemaining() const { return m_postMine.gasLimitRemaining(); }
@ -188,25 +188,27 @@ public:
bool forceMining() const { return m_forceMining; }
/// Enable/disable forcing of mining to happen, even without transactions.
void setForceMining(bool _enable);
/// Are we mining as fast as we can?
/// Are we allowed to GPU mine?
bool turboMining() const { return m_turboMining; }
/// Enable/disable fast mining.
void setTurboMining(bool _enable = true) { m_turboMining = _enable; }
/// Enable/disable GPU mining.
void setTurboMining(bool _enable = true) { bool was = isMining(); stopMining(); m_turboMining = _enable; setMiningThreads(0); if (was) startMining(); }
/// Stops mining and sets the number of mining threads (0 for automatic).
virtual void setMiningThreads(unsigned _threads = 0);
void setMiningThreads(unsigned _threads = 0) override;
/// Get the effective number of mining threads.
virtual unsigned miningThreads() const { ReadGuard l(x_localMiners); return m_localMiners.size(); }
unsigned miningThreads() const override { ReadGuard l(x_localMiners); return m_localMiners.size(); }
/// Start mining.
/// NOT thread-safe - call it & stopMining only from a single thread
virtual void startMining() { startWorking(); { ReadGuard l(x_localMiners); for (auto& m: m_localMiners) m.start(); } }
void startMining() override { startWorking(); { ReadGuard l(x_localMiners); for (auto& m: m_localMiners) m.start(); } }
/// Stop mining.
/// NOT thread-safe
virtual void stopMining() { { ReadGuard l(x_localMiners); for (auto& m: m_localMiners) m.stop(); } }
void stopMining() override { { ReadGuard l(x_localMiners); for (auto& m: m_localMiners) m.stop(); } }
/// Are we mining now?
virtual bool isMining() { { ReadGuard l(x_localMiners); if (!m_localMiners.empty() && m_localMiners[0].isRunning()) return true; } return false; }
bool isMining() const override { { ReadGuard l(x_localMiners); if (!m_localMiners.empty() && m_localMiners[0].isRunning()) return true; } return false; }
/// Are we mining now?
uint64_t hashrate() const override;
/// Check the progress of the mining.
virtual MineProgress miningProgress() const;
MineProgress miningProgress() const override;
/// Get and clear the mining history.
std::list<MineInfo> miningHistory();
@ -229,8 +231,9 @@ public:
protected:
/// InterfaceStub methods
virtual BlockChain& bc() override { return m_bc; }
virtual BlockChain const& bc() const override { return m_bc; }
/// Returns the state object for the full block (i.e. the terminal state) for index _h.
/// Works properly with LatestBlock and PendingBlock.
using ClientBase::asOf;

19
libethereum/ClientBase.cpp

@ -65,14 +65,17 @@ Address ClientBase::submitTransaction(Secret _secret, u256 _endowment, bytes con
}
// TODO: remove try/catch, allow exceptions
ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber)
ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff)
{
ExecutionResult ret;
try
{
State temp = asOf(_blockNumber);
u256 n = temp.transactionsFrom(toAddress(_secret));
Address a = toAddress(_secret);
u256 n = temp.transactionsFrom(a);
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
if (_ff == FudgeFactor::Lenient)
temp.addBalance(a, (u256)(t.gas() * t.gasPrice() + t.value()));
ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted);
}
catch (...)
@ -82,16 +85,19 @@ ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, byt
return ret;
}
ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber)
ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff)
{
ExecutionResult ret;
try
{
State temp = asOf(_blockNumber);
u256 n = temp.transactionsFrom(toAddress(_secret));
Address a = toAddress(_secret);
u256 n = temp.transactionsFrom(a);
// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
Transaction t(_value, _gasPrice, _gas, _data, n, _secret);
if (_ff == FudgeFactor::Lenient)
temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value()));
ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted);
}
catch (...)
@ -101,6 +107,11 @@ ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _da
return ret;
}
void ClientBase::injectBlock(bytes const& _block)
{
bc().import(_block, preMine().db());
}
u256 ClientBase::balanceAt(Address _a, BlockNumber _block) const
{
return asOf(_block).balance(_a);

12
libethereum/ClientBase.h

@ -82,9 +82,10 @@ public:
virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override;
/// Makes the given call. Nothing is recorded into the state.
virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock) override;
virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) override;
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock) override;
/// Makes the given create. Nothing is recorded into the state.
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) override;
using Interface::balanceAt;
using Interface::countAt;
@ -108,7 +109,6 @@ public:
virtual LocalisedLogEntries peekWatch(unsigned _watchId) const override;
virtual LocalisedLogEntries checkWatch(unsigned _watchId) override;
// TODO: switch all the _blockHash arguments to also accept _blockNumber
virtual h256 hashFromNumber(BlockNumber _number) const override;
virtual eth::BlockInfo blockInfo(h256 _hash) const override;
virtual eth::BlockDetails blockDetails(h256 _hash) const override;
@ -124,6 +124,8 @@ public:
virtual eth::Transactions pending() const override;
virtual h256s pendingHashes() const override;
void injectBlock(bytes const& _block);
using Interface::diff;
virtual StateDiff diff(unsigned _txi, h256 _block) const override;
virtual StateDiff diff(unsigned _txi, BlockNumber _block) const override;
@ -144,7 +146,8 @@ public:
virtual unsigned miningThreads() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::miningThreads")); }
virtual void startMining() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::startMining")); }
virtual void stopMining() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::stopMining")); }
virtual bool isMining() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::isMining")); }
virtual bool isMining() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::isMining")); }
virtual uint64_t hashrate() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::hashrate")); }
virtual eth::MineProgress miningProgress() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::miningProgress")); }
virtual std::pair<h256, u256> getWork() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::getWork")); }
virtual bool submitWork(eth::ProofOfWork::Proof const&) override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::submitWork")); }
@ -154,6 +157,7 @@ public:
protected:
/// The interface that must be implemented in any class deriving this.
/// {
virtual BlockChain& bc() = 0;
virtual BlockChain const& bc() const = 0;
virtual State asOf(h256 const& _h) const = 0;
virtual State preMine() const = 0;

18
libethereum/Interface.h

@ -46,6 +46,12 @@ enum class Reaping
Manual
};
enum class FudgeFactor
{
Strict,
Lenient
};
/**
* @brief Main API hub for interfacing with Ethereum.
*/
@ -71,13 +77,13 @@ public:
virtual void flushTransactions() = 0;
/// Makes the given call. Nothing is recorded into the state.
virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) = 0;
ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) { return call(_secret, _value, _dest, _data, _gas, _gasPrice, m_default); }
virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0;
ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, FudgeFactor _ff = FudgeFactor::Strict) { return call(_secret, _value, _dest, _data, _gas, _gasPrice, m_default, _ff); }
/// Does the given creation. Nothing is recorded into the state.
/// @returns the pair of the Address of the created contract together with its code.
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) = 0;
ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) { return create(_secret, _value, _data, _gas, _gasPrice, m_default); }
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0;
ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, FudgeFactor _ff = FudgeFactor::Strict) { return create(_secret, _value, _data, _gas, _gasPrice, m_default, _ff); }
// [STATE-QUERY API]
@ -177,7 +183,9 @@ public:
/// NOT thread-safe
virtual void stopMining() = 0;
/// Are we mining now?
virtual bool isMining() = 0;
virtual bool isMining() const = 0;
/// Current hash rate.
virtual uint64_t hashrate() const = 0;
/// Get hash of the current block to be mined minus the nonce (the 'work hash').
virtual std::pair<h256, u256> getWork() = 0;

4
libethereum/Miner.cpp

@ -34,12 +34,14 @@ LocalMiner::LocalMiner(MinerHost* _host, unsigned _id):
AsyncMiner(_host, _id),
Worker("miner-" + toString(_id))
{
m_pow.reset(_host->turbo() ? new Ethash : (Ethash*)new EthashCPU);
}
void LocalMiner::setup(MinerHost* _host, unsigned _id)
{
AsyncMiner::setup(_host, _id);
setName("miner-" + toString(m_id));
m_pow.reset(_host->turbo() ? new Ethash : (Ethash*)new EthashCPU);
}
void LocalMiner::doWork()
@ -66,7 +68,7 @@ void LocalMiner::doWork()
if (m_miningStatus == Mining)
{
// Mine for a while.
MineInfo mineInfo = m_mineState.mine(100, m_host->turbo());
MineInfo mineInfo = m_mineState.mine(m_pow.get());
{
Guard l(x_mineInfo);

13
libethereum/Miner.h

@ -60,8 +60,8 @@ public:
virtual void setupState(State& _s) = 0; ///< Reset the given State object to the one that should be being mined.
virtual void onProgressed() {} ///< Called once some progress has been made.
virtual void onComplete() {} ///< Called once a block is found.
virtual bool turbo() const = 0; ///< @returns true iff the Miner should mine as fast as possible.
virtual bool force() const = 0; ///< @returns true iff the Miner should mine regardless of the number of transactions.
virtual bool turbo() const = 0; ///< @returns true iff the Miner should use GPU if possible.
};
class Miner
@ -93,7 +93,7 @@ public:
virtual void stop() {}
/// @returns true iff the mining has been start()ed. It may still not be actually mining, depending on the host's turbo() & force().
virtual bool isRunning() { return false; }
virtual bool isRunning() const { return false; }
protected:
MinerHost* m_host = nullptr; ///< Our host.
@ -122,10 +122,10 @@ public:
LocalMiner(MinerHost* _host, unsigned _id = 0);
/// Move-constructor.
LocalMiner(LocalMiner&& _m): Worker((Worker&&)_m) { std::swap(m_host, _m.m_host); }
LocalMiner(LocalMiner&& _m): Worker((Worker&&)_m) { std::swap(m_host, _m.m_host); std::swap(m_pow, _m.m_pow); }
/// Move-assignment.
LocalMiner& operator=(LocalMiner&& _m) { Worker::operator=((Worker&&)_m); std::swap(m_host, _m.m_host); return *this; }
LocalMiner& operator=(LocalMiner&& _m) { Worker::operator=((Worker&&)_m); std::swap(m_host, _m.m_host); std::swap(m_pow, _m.m_pow); return *this; }
/// Destructor. Stops miner.
~LocalMiner() { stop(); }
@ -143,7 +143,7 @@ public:
virtual void noteStateChange() override { m_miningStatus = Preparing; }
/// @returns true iff the mining has been start()ed. It may still not be actually mining, depending on the host's turbo() & force().
bool isRunning() { return isWorking(); }
bool isRunning() const override { return isWorking(); }
/// @returns true if mining is complete.
virtual bool isComplete() const override { return m_miningStatus == Mined; }
@ -167,8 +167,9 @@ private:
enum MiningStatus { Waiting, Preparing, Mining, Mined, Stopping, Stopped };
MiningStatus m_miningStatus = Waiting; ///< TODO: consider mutex/atomic variable.
State m_mineState; ///< The state on which we are mining, generally equivalent to m_postMine.
std::unique_ptr<EthashPoW> m_pow; ///< Our miner.
mutable std::mutex x_mineInfo; ///< Lock for the mining progress & history.
mutable Mutex x_mineInfo; ///< Lock for the mining progress & history.
MineProgress m_mineProgress; ///< What's our progress?
std::list<MineInfo> m_mineHistory; ///< What the history of our mining?
};

38
libethereum/State.cpp

@ -451,7 +451,7 @@ bool State::cull(TransactionQueue& _tq) const
{
try
{
if (i.second.nonce() <= transactionsFrom(i.second.sender()))
if (i.second.nonce() < transactionsFrom(i.second.sender()))
{
_tq.drop(i.first);
ret = true;
@ -543,8 +543,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
// m_currentBlock is assumed to be prepopulated and reset.
BlockInfo bi(_block, _checkNonce ? CheckEverything : IgnoreNonce);
cdebug << "enacting" << BlockInfo::headerHash(_block).abridged() << "==" << bi.hash().abridged() << "on" << m_previousBlock.hash().abridged();
cdebug << m_currentBlock;
#if !ETH_RELEASE
assert(m_previousBlock.hash() == bi.parentHash);
@ -560,9 +558,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
m_currentBlock.verifyInternals(_block);
m_currentBlock.noteDirty();
cdebug << "populated and verified. incoming block hash is" << m_currentBlock.hash().abridged();
cdebug << m_currentBlock;
// cnote << "playback begins:" << m_state.root();
// cnote << m_state;
@ -631,7 +626,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
// Initialise total difficulty calculation.
u256 tdIncrease = m_currentBlock.difficulty;
// Check uncles & apply their rewards to state.
if (rlp[2].itemCount() > 2)
BOOST_THROW_EXCEPTION(TooManyUncles());
@ -686,11 +680,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
BOOST_THROW_EXCEPTION(InvalidGasUsed() << RequirementError(bigint(gasUsed()), bigint(m_currentBlock.gasUsed)));
}
cdebug << m_currentBlock;
auto hh = m_currentBlock.hash();
m_currentBlock.noteDirty();
cdebug << "done enacting. new stateroot is" << m_currentBlock.stateRoot.abridged() << ", hash is" << m_currentBlock.hash().abridged() << " = " << hh;
return tdIncrease;
}
@ -867,33 +856,12 @@ void State::commitToMine(BlockChain const& _bc)
m_committedToMine = true;
}
MineInfo State::mine(unsigned _msTimeout, bool _turbo)
{
// Update difficulty according to timestamp.
m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock);
MineInfo ret;
// TODO: Miner class that keeps dagger between mine calls (or just non-polling mining).
ProofOfWork::Proof r;
tie(ret, r) = m_pow.mine(m_currentBlock, _msTimeout, true, _turbo);
if (!ret.completed)
m_currentBytes.clear();
else
{
ProofOfWork::assignResult(r, m_currentBlock);
cnote << "Completed" << m_currentBlock.headerHash(WithoutNonce).abridged() << m_currentBlock.nonce.abridged() << m_currentBlock.difficulty << ProofOfWork::verify(m_currentBlock);
}
return ret;
}
bool State::completeMine(ProofOfWork::Proof const& _nonce)
{
ProofOfWork::assignResult(_nonce, m_currentBlock);
if (!m_pow.verify(m_currentBlock))
return false;
// if (!m_pow.verify(m_currentBlock))
// return false;
cnote << "Completed" << m_currentBlock.headerHash(WithoutNonce).abridged() << m_currentBlock.nonce.abridged() << m_currentBlock.difficulty << ProofOfWork::verify(m_currentBlock);

22
libethereum/State.h

@ -168,7 +168,25 @@ public:
/// This function is thread-safe. You can safely have other interactions with this object while it is happening.
/// @param _msTimeout Timeout before return in milliseconds.
/// @returns Information on the mining.
MineInfo mine(unsigned _msTimeout = 1000, bool _turbo = false);
template <class ProofOfWork> MineInfo mine(ProofOfWork* _pow)
{
// Update difficulty according to timestamp.
m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock);
MineInfo ret;
typename ProofOfWork::Proof r;
std::tie(ret, r) = _pow->mine(m_currentBlock, _pow->defaultTimeout(), true);
if (!ret.completed)
m_currentBytes.clear();
else
{
ProofOfWork::assignResult(r, m_currentBlock);
cnote << "Completed" << m_currentBlock.headerHash(WithoutNonce).abridged() << m_currentBlock.nonce.abridged() << m_currentBlock.difficulty << ProofOfWork::verify(m_currentBlock);
}
return ret;
}
/** Commit to DB and build the final block if the previous call to mine()'s result is completion.
* Typically looks like:
@ -371,8 +389,6 @@ private:
Address m_ourAddress; ///< Our address (i.e. the address to which fees go).
ProofOfWork m_pow; ///< The PoW mining class.
u256 m_blockReward;
static std::string c_defaultPath;

2
libtestutils/BlockChainLoader.h

@ -22,9 +22,9 @@
#pragma once
#include <string>
#include <json/json.h>
#include <libdevcore/TransientDirectory.h>
#include <libethereum/BlockChain.h>
#include <libethereum/State.h>
#include "TransientDirectory.h"
namespace dev
{

1
libtestutils/FixedClient.h

@ -42,6 +42,7 @@ public:
// stub
virtual void flushTransactions() override {}
virtual eth::BlockChain& bc() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("FixedClient::bc()")); }
virtual eth::BlockChain const& bc() const override { return m_bc; }
using ClientBase::asOf;
virtual eth::State asOf(h256 const& _h) const override;

2
libtestutils/StateLoader.h

@ -22,8 +22,8 @@
#pragma once
#include <json/json.h>
#include <libdevcore/TransientDirectory.h>
#include <libethereum/State.h>
#include "TransientDirectory.h"
namespace dev
{

83
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -26,7 +26,7 @@
#include <jsonrpccpp/common/exception.h>
#include <libdevcore/CommonData.h>
#if ETH_SOLIDITY
#if ETH_SOLIDITY || !ETH_TRUE
#include <libsolidity/CompilerStack.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/SourceReferenceFormatter.h>
@ -38,7 +38,7 @@
#include <libethcore/CommonJS.h>
#include <libwhisper/Message.h>
#include <libwhisper/WhisperHost.h>
#if ETH_SERPENT
#if ETH_SERPENT || !ETH_TRUE
#include <libserpent/funcs.h>
#endif
#include "WebThreeStubServerBase.h"
@ -296,6 +296,11 @@ string WebThreeStubServerBase::eth_coinbase()
return toJS(client()->address());
}
string WebThreeStubServerBase::eth_hashrate()
{
return toJS(client()->hashrate());
}
bool WebThreeStubServerBase::eth_mining()
{
return client()->isMining();
@ -449,63 +454,55 @@ static TransactionSkeleton toTransaction(Json::Value const& _json)
string WebThreeStubServerBase::eth_sendTransaction(Json::Value const& _json)
{
TransactionSkeleton t;
try
{
t = toTransaction(_json);
string ret;
TransactionSkeleton t = toTransaction(_json);
if (!t.from)
t.from = m_accounts->getDefaultTransactAccount();
if (t.creation)
ret = toJS(right160(sha3(rlpList(t.from, client()->countAt(t.from)))));;
if (!t.gasPrice)
t.gasPrice = 10 * dev::eth::szabo; // TODO: should be determined by user somehow.
if (!t.gas)
t.gas = min<u256>(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice);
if (m_accounts->isRealAccount(t.from))
authenticate(t, false);
else if (m_accounts->isProxyAccount(t.from))
authenticate(t, true);
return ret;
}
catch (...)
{
BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
}
string ret;
if (!t.from)
t.from = m_accounts->getDefaultTransactAccount();
if (t.creation)
ret = toJS(right160(sha3(rlpList(t.from, client()->countAt(t.from)))));;
if (!t.gasPrice)
t.gasPrice = 10 * dev::eth::szabo; // TODO: should be determined by user somehow.
if (!t.gas)
t.gas = min<u256>(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice);
if (m_accounts->isRealAccount(t.from))
authenticate(t, false);
else if (m_accounts->isProxyAccount(t.from))
authenticate(t, true);
return ret;
}
string WebThreeStubServerBase::eth_call(Json::Value const& _json, string const& _blockNumber)
{
TransactionSkeleton t;
int number;
try
{
t = toTransaction(_json);
number = jsToBlockNumber(_blockNumber);
TransactionSkeleton t = toTransaction(_json);
if (!t.from)
t.from = m_accounts->getDefaultTransactAccount();
// if (!m_accounts->isRealAccount(t.from))
// return ret;
if (!t.gasPrice)
t.gasPrice = 10 * dev::eth::szabo;
if (!t.gas)
t.gas = client()->gasLimitRemaining();
return toJS(client()->call(m_accounts->secretKey(t.from), t.value, t.to, t.data, t.gas, t.gasPrice, jsToBlockNumber(_blockNumber), FudgeFactor::Lenient).output);
}
catch (...)
{
BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
}
string ret;
if (!t.from)
t.from = m_accounts->getDefaultTransactAccount();
if (!m_accounts->isRealAccount(t.from))
return ret;
if (!t.gasPrice)
t.gasPrice = 10 * dev::eth::szabo;
if (!t.gas)
t.gas = min<u256>(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice);
ret = toJS(client()->call(m_accounts->secretKey(t.from), t.value, t.to, t.data, t.gas, t.gasPrice, number).output);
return ret;
}
bool WebThreeStubServerBase::eth_flush()
@ -610,10 +607,10 @@ Json::Value WebThreeStubServerBase::eth_getCompilers()
{
Json::Value ret(Json::arrayValue);
ret.append("lll");
#if SOLIDITY
#if ETH_SOLIDITY || !TRUE
ret.append("solidity");
#endif
#if SERPENT
#if ETH_SERPENT || !TRUE
ret.append("serpent");
#endif
return ret;
@ -635,7 +632,7 @@ string WebThreeStubServerBase::eth_compileSerpent(string const& _code)
// TODO throw here jsonrpc errors
string res;
(void)_code;
#if SERPENT
#if ETH_SERPENT || !ETH_TRUE
try
{
res = toJS(dev::asBytes(::compile(_code)));
@ -657,7 +654,7 @@ string WebThreeStubServerBase::eth_compileSolidity(string const& _code)
// TOOD throw here jsonrpc errors
(void)_code;
string res;
#if SOLIDITY
#if ETH_SOLIDITY || !ETH_TRUE
dev::solidity::CompilerStack compiler;
try
{

1
libweb3jsonrpc/WebThreeStubServerBase.h

@ -78,6 +78,7 @@ public:
virtual bool net_listening();
virtual std::string eth_protocolVersion();
virtual std::string eth_hashrate();
virtual std::string eth_coinbase();
virtual bool eth_mining();
virtual std::string eth_gasPrice();

7
libweb3jsonrpc/abstractwebthreestubserver.h

@ -18,6 +18,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
this->bindAndAddMethod(jsonrpc::Procedure("net_peerCount", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::net_peerCountI);
this->bindAndAddMethod(jsonrpc::Procedure("net_listening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::net_listeningI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_protocolVersion", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_protocolVersionI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_hashrate", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_hashrateI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_coinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_coinbaseI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_mining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_miningI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_gasPrice", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_gasPriceI);
@ -98,6 +99,11 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
(void)request;
response = this->eth_protocolVersion();
}
inline virtual void eth_hashrateI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->eth_hashrate();
}
inline virtual void eth_coinbaseI(const Json::Value &request, Json::Value &response)
{
(void)request;
@ -309,6 +315,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
virtual std::string net_peerCount() = 0;
virtual bool net_listening() = 0;
virtual std::string eth_protocolVersion() = 0;
virtual std::string eth_hashrate() = 0;
virtual std::string eth_coinbase() = 0;
virtual bool eth_mining() = 0;
virtual std::string eth_gasPrice() = 0;

5
libweb3jsonrpc/spec.json

@ -6,8 +6,9 @@
{ "name": "net_peerCount", "params": [], "order": [], "returns" : "" },
{ "name": "net_listening", "params": [], "order": [], "returns" : false },
{ "name": "eth_protocolVersion", "params": [], "order": [], "returns" : "" },
{ "name": "eth_coinbase", "params": [], "order": [], "returns" : "" },
{ "name": "eth_protocolVersion", "params": [], "order": [], "returns" : "" },
{ "name": "eth_hashrate", "params": [], "order": [], "returns" : "" },
{ "name": "eth_coinbase", "params": [], "order": [], "returns" : "" },
{ "name": "eth_mining", "params": [], "order": [], "returns" : false },
{ "name": "eth_gasPrice", "params": [], "order": [], "returns" : "" },
{ "name": "eth_accounts", "params": [], "order": [], "returns" : [] },

4
mix/InverseMouseArea.cpp

@ -39,11 +39,11 @@ bool InverseMouseArea::eventFilter(QObject* _obj, QEvent* _ev)
{
Q_UNUSED(_obj);
if (this->m_active && _ev->type() == QEvent::MouseButtonPress && !this->contains(static_cast<QMouseEvent*>(_ev)->pos()))
emit clickedOutside();
emit clickedOutside(QPointF(static_cast<QMouseEvent*>(_ev)->pos()));
return false;
}
bool InverseMouseArea::contains(const QPoint& _point) const
bool InverseMouseArea::contains(const QPointF& _point) const
{
if (!this->m_active)
return false;

8
mix/InverseMouseArea.h

@ -41,15 +41,15 @@ public:
void setActive(bool _v);
protected:
void itemChange(ItemChange _c, const ItemChangeData& _v);
bool eventFilter(QObject* _obj, QEvent *_ev);
bool contains(const QPoint& _point) const;
void itemChange(ItemChange _c, const ItemChangeData& _v) override;
bool eventFilter(QObject* _obj, QEvent *_ev) override;
bool contains(const QPointF& _point) const override;
private:
bool m_active;
signals:
void clickedOutside();
void clickedOutside(QPointF _point);
};
}

28
mix/MixClient.cpp

@ -250,7 +250,8 @@ void MixClient::mine()
{
WriteGuard l(x_state);
m_state.commitToMine(bc());
while (!m_state.mine(100, true).completed) {}
ProofOfWork pow;
while (!m_state.mine(&pow).completed) {}
m_state.completeMine();
bc().import(m_state.blockData(), m_stateDB);
m_state.sync(bc());
@ -295,12 +296,15 @@ Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes cons
return address;
}
dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto)
dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto, FudgeFactor _ff)
{
(void)_blockNumber;
Address a = toAddress(_secret);
State temp = asOf(eth::PendingBlock);
u256 n = temp.transactionsFrom(toAddress(_secret));
u256 n = temp.transactionsFrom(a);
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
if (_ff == FudgeFactor::Lenient)
temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value()));
bytes rlp = t.rlp();
WriteGuard lw(x_state); //TODO: lock is required only for last execution state
executeTransaction(t, temp, true, _gasAuto, _secret);
@ -317,22 +321,25 @@ Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes cons
return submitTransaction(_secret, _endowment, _init, _gas, _gasPrice, false);
}
dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber)
dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff)
{
return call(_secret, _value, _dest, _data, _gas, _gasPrice, _blockNumber,false);
return call(_secret, _value, _dest, _data, _gas, _gasPrice, _blockNumber, false, _ff);
}
dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber)
dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff)
{
(void)_blockNumber;
u256 n;
Address a = toAddress(_secret);
State temp;
{
ReadGuard lr(x_state);
temp = asOf(eth::PendingBlock);
n = temp.transactionsFrom(toAddress(_secret));
n = temp.transactionsFrom(a);
}
Transaction t(_value, _gasPrice, _gas, _data, n, _secret);
if (_ff == FudgeFactor::Lenient)
temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value()));
bytes rlp = t.rlp();
WriteGuard lw(x_state); //TODO: lock is required only for last execution state
executeTransaction(t, temp, true, false, _secret);
@ -385,11 +392,16 @@ void MixClient::stopMining()
//no-op
}
bool MixClient::isMining()
bool MixClient::isMining() const
{
return false;
}
uint64_t MixClient::hashrate() const
{
return 0;
}
eth::MineProgress MixClient::miningProgress() const
{
return eth::MineProgress();

16
mix/MixClient.h

@ -55,19 +55,20 @@ public:
void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) override;
Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) override;
dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber = eth::PendingBlock) override;
dev::eth::ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock) override;
dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override;
dev::eth::ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override;
void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, bool _gasAuto);
Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice, bool _gasAuto);
dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto);
dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto, eth::FudgeFactor _ff = eth::FudgeFactor::Strict);
void setAddress(Address _us) override;
void setMiningThreads(unsigned _threads) override;
unsigned miningThreads() const override;
void startMining() override;
void stopMining() override;
bool isMining() override;
bool isMining() const override;
uint64_t hashrate() const override;
eth::MineProgress miningProgress() const override;
std::pair<h256, u256> getWork() override { return std::pair<h256, u256>(); }
bool submitWork(eth::ProofOfWork::Proof const&) override { return false; }
@ -79,11 +80,10 @@ public:
std::vector<KeyPair> userAccounts() { return m_userAccounts; }
protected:
virtual dev::eth::BlockChain& bc() { return *m_bc; }
/// InterfaceStub methods
virtual dev::eth::State asOf(h256 const& _block) const override;
/// ClientBase methods
using ClientBase::asOf;
virtual dev::eth::State asOf(h256 const& _block) const override;
virtual dev::eth::BlockChain& bc() { return *m_bc; }
virtual dev::eth::BlockChain const& bc() const override { return *m_bc; }
virtual dev::eth::State preMine() const override { ReadGuard l(x_state); return m_startState; }
virtual dev::eth::State postMine() const override { ReadGuard l(x_state); return m_state; }

1
mix/qml/Application.qml

@ -29,6 +29,7 @@ ApplicationWindow {
property alias clientModel: clientModel;
property alias projectModel: projectModel;
property alias appService: appService;
property bool trackLastProject: true;
ApplicationService {
id: appService

52
mix/qml/CodeEditorView.qml

@ -46,31 +46,36 @@ Item {
else
{
editorListModel.set(openDocCount, document);
editors.itemAt(openDocCount).visible = true;
doLoadDocument(editors.itemAt(openDocCount).item, editorListModel.get(openDocCount))
doLoadDocument(editors.itemAt(openDocCount).item, editorListModel.get(openDocCount), false)
loadComplete();
}
openDocCount++;
}
function doLoadDocument(editor, document) {
function doLoadDocument(editor, document, create) {
var data = fileIo.readFile(document.path);
editor.onLoadComplete.connect(function() {
loadComplete();
});
editor.onEditorTextChanged.connect(function() {
documentEdit(document.documentId);
if (document.isContract)
codeModel.registerCodeChange(document.documentId, editor.getText());
});
editor.onBreakpointsChanged.connect(function() {
if (document.isContract)
breakpointsChanged(document.documentId);
});
editor.setText(data, document.syntaxMode);
editor.onIsCleanChanged.connect(function() {
isCleanChanged(editor.isClean, document.documentId);
});
if (create)
{
editor.onLoadComplete.connect(function() {
codeEditorView.loadComplete();
});
editor.onEditorTextChanged.connect(function() {
documentEdit(editor.document.documentId);
if (editor.document.isContract)
codeModel.registerCodeChange(editor.document.documentId, editor.getText());
});
editor.onBreakpointsChanged.connect(function() {
if (editor.document.isContract)
breakpointsChanged(editor.document.documentId);
});
editor.onIsCleanChanged.connect(function() {
isCleanChanged(editor.isClean, editor.document.documentId);
});
}
editor.document = document;
editor.sourceName = document.documentId;
editor.setText(data, document.syntaxMode);
editor.changeGeneration();
}
function getEditor(documentId) {
@ -192,9 +197,6 @@ Item {
}
onProjectClosed: {
for (var i = 0; i < editorListModel.count; i++)
editors.itemAt(i).visible = false;
//editorListModel.clear();
currentDocumentId = "";
openDocCount = 0;
}
@ -234,7 +236,7 @@ Item {
property variant item
property variant doc
onYes: {
doLoadDocument(item, doc);
doLoadDocument(item, doc, false);
resetEditStatus(doc.documentId);
}
}
@ -251,7 +253,7 @@ Item {
asynchronous: true
anchors.fill: parent
source: appService.haveWebEngine ? "WebCodeEditor.qml" : "CodeEditor.qml"
visible: (index >= 0 && index < editorListModel.count && currentDocumentId === editorListModel.get(index).documentId)
visible: (index >= 0 && index < openDocCount && currentDocumentId === editorListModel.get(index).documentId)
property bool changed: false
onVisibleChanged: {
loadIfNotLoaded()
@ -271,7 +273,7 @@ Item {
loadIfNotLoaded()
}
onLoaded: {
doLoadDocument(loader.item, editorListModel.get(index))
doLoadDocument(loader.item, editorListModel.get(index), true)
}
Connections

4
mix/qml/DebugInfoList.qml

@ -40,11 +40,9 @@ ColumnLayout {
height: 25
id: header
Image {
source: "qrc:/qml/img/opentriangleindicator.png"
source: "img/closedtriangleindicator.png"
width: 15
height: 15
sourceSize.width: 15
sourceSize.height: 15
id: storageImgArrow
}

109
mix/qml/Debugger.qml

@ -4,6 +4,7 @@ import QtQuick.Controls.Styles 1.1
import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.1
import Qt.labs.settings 1.0
import QtGraphicalEffects 1.0
import "js/Debugger.js" as Debugger
import "js/ErrorLocationFormater.js" as ErrorLocationFormater
import "."
@ -206,8 +207,8 @@ Rectangle {
anchors.top: parent.top
anchors.topMargin: 15
anchors.left: parent.left;
anchors.leftMargin: machineStates.sideMargin
width: debugScrollArea.width - machineStates.sideMargin * 2 - 20;
anchors.leftMargin: machineStates.sideMargin
width: debugScrollArea.width - machineStates.sideMargin * 2 - 20 ;
spacing: machineStates.sideMargin
Rectangle {
@ -218,27 +219,26 @@ Rectangle {
color: "transparent"
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.fill: parent
color: "transparent"
width: parent.width * 0.4
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.fill: parent
id: jumpButtons
spacing: 3
layoutDirection: Qt.LeftToRight
StepActionImage
{
id: playAction
enabledStateImg: "qrc:/qml/img/play_button.png"
disableStateImg: "qrc:/qml/img/play_button.png"
buttonLeft: true
onClicked: projectModel.stateListModel.runState(transactionLog.selectedStateIndex)
width: 30
height: 30
width: 23
buttonShortcut: "Ctrl+Shift+F8"
buttonTooltip: qsTr("Start Debugging")
visible: true
Layout.alignment: Qt.AlignLeft
}
StepActionImage
@ -247,8 +247,7 @@ Rectangle {
enabledStateImg: "qrc:/qml/img/stop_button2x.png"
disableStateImg: "qrc:/qml/img/stop_button2x.png"
onClicked: Debugger.init(null);
width: 30
height: 30
width: 23
buttonShortcut: "Ctrl+Shift+F9"
buttonTooltip: qsTr("Stop Debugging")
visible: true
@ -260,8 +259,7 @@ Rectangle {
enabledStateImg: "qrc:/qml/img/jumpoutback.png"
disableStateImg: "qrc:/qml/img/jumpoutbackdisabled.png"
onClicked: Debugger.runBack()
width: 30
height: 30
width: 23
buttonShortcut: "Ctrl+Shift+F5"
buttonTooltip: qsTr("Run Back")
visible: false
@ -273,8 +271,7 @@ Rectangle {
enabledStateImg: "qrc:/qml/img/jumpoutback.png"
disableStateImg: "qrc:/qml/img/jumpoutbackdisabled.png"
onClicked: Debugger.stepOutBack()
width: 30
height: 30
width: 23
buttonShortcut: "Ctrl+Shift+F11"
buttonTooltip: qsTr("Step Out Back")
}
@ -285,8 +282,7 @@ Rectangle {
enabledStateImg: "qrc:/qml/img/jumpintoback.png"
disableStateImg: "qrc:/qml/img/jumpintobackdisabled.png"
onClicked: Debugger.stepIntoBack()
width: 30
height: 30
width: 23
buttonShortcut: "Ctrl+F11"
buttonTooltip: qsTr("Step Into Back")
}
@ -297,8 +293,7 @@ Rectangle {
enabledStateImg: "qrc:/qml/img/jumpoverback.png"
disableStateImg: "qrc:/qml/img/jumpoverbackdisabled.png"
onClicked: Debugger.stepOverBack()
width: 30
height: 30
width: 23
buttonShortcut: "Ctrl+F10"
buttonTooltip: qsTr("Step Over Back")
}
@ -309,8 +304,7 @@ Rectangle {
enabledStateImg: "qrc:/qml/img/jumpoverforward.png"
disableStateImg: "qrc:/qml/img/jumpoverforwarddisabled.png"
onClicked: Debugger.stepOverForward()
width: 30
height: 30
width: 23
buttonShortcut: "F10"
buttonTooltip: qsTr("Step Over Forward")
}
@ -321,8 +315,7 @@ Rectangle {
enabledStateImg: "qrc:/qml/img/jumpintoforward.png"
disableStateImg: "qrc:/qml/img/jumpintoforwarddisabled.png"
onClicked: Debugger.stepIntoForward()
width: 30
height: 30
width: 23
buttonShortcut: "F11"
buttonTooltip: qsTr("Step Into Forward")
}
@ -333,10 +326,10 @@ Rectangle {
enabledStateImg: "qrc:/qml/img/jumpoutforward.png"
disableStateImg: "qrc:/qml/img/jumpoutforwarddisabled.png"
onClicked: Debugger.stepOutForward()
width: 30
height: 30
width: 45
buttonShortcut: "Shift+F11"
buttonTooltip: qsTr("Step Out Forward")
buttonRight: true
}
StepActionImage
@ -345,41 +338,44 @@ Rectangle {
enabledStateImg: "qrc:/qml/img/jumpoutforward.png"
disableStateImg: "qrc:/qml/img/jumpoutforwarddisabled.png"
onClicked: Debugger.runForward()
width: 30
height: 30
width: 45
buttonShortcut: "Ctrl+F5"
buttonTooltip: qsTr("Run Forward")
visible: false
buttonRight: true
}
}
}
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
width: parent.width * 0.6
color: "transparent"
Slider {
id: statesSlider
anchors.fill: parent
tickmarksEnabled: true
stepSize: 1.0
onValueChanged: Debugger.jumpTo(value);
style: SliderStyle {
groove: Rectangle {
implicitHeight: 3
color: "#7da4cd"
radius: 8
}
handle: Rectangle {
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
implicitWidth: 10
implicitHeight: 10
radius: 12
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
color: "transparent"
Layout.fillWidth: true
Layout.minimumWidth: parent.width * 0.2
Layout.alignment: Qt.AlignRight
Slider {
id: statesSlider
anchors.fill: parent
tickmarksEnabled: true
stepSize: 1.0
onValueChanged: Debugger.jumpTo(value);
style: SliderStyle {
groove: Rectangle {
implicitHeight: 3
color: "#7da4cd"
radius: 8
}
handle: Rectangle {
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
implicitWidth: 10
implicitHeight: 10
radius: 12
}
}
}
}
}
@ -480,7 +476,7 @@ Rectangle {
anchors.top : parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
height: parent.height //- 2 * stateListContainer.border.width
height: parent.height
color: "transparent"
ColumnLayout
{
@ -520,7 +516,6 @@ Rectangle {
title : qsTr("Stack")
itemDelegate: Item {
id: renderedItem
//height: 25
width: parent.width
RowLayout
{

2
mix/qml/ProjectModel.qml

@ -76,7 +76,7 @@ Item {
Connections {
target: mainApplication
onLoaded: {
if (projectSettings.lastProjectPath && projectSettings.lastProjectPath !== "")
if (mainApplication.trackLastProject && projectSettings.lastProjectPath && projectSettings.lastProjectPath !== "")
projectModel.loadProject(projectSettings.lastProjectPath)
}
}

11
mix/qml/StatesComboBox.qml

@ -99,11 +99,10 @@ Rectangle {
}
MouseArea {
id: selectorArea
anchors.fill: parent
onClicked: {
if (outsideClick.trigerred)
outsideClick.trigerred = false;
else if (statesCombo.state === "")
if (statesCombo.state === "")
statesCombo.state = "dropDown";
}
}
@ -133,13 +132,13 @@ Rectangle {
InverseMouseArea
{
property bool trigerred: false
id: outsideClick
anchors.fill: parent
active: false
onClickedOutside: {
trigerred = true;
statesCombo.hideDropDown()
var p = selectorArea.mapFromItem(null, _point.x, _point.y);
if (!selectorArea.contains(Qt.point(p.x, p.y)))
statesCombo.hideDropDown()
}
}

21
mix/qml/StatusPane.qml

@ -230,13 +230,26 @@ Rectangle {
Button
{
z: 4
anchors.right: parent.right
anchors.rightMargin: 9
anchors.verticalCenter: parent.verticalCenter
anchors.centerIn: parent
id: goToLineBtn
text: ""
iconSource: "qrc:/qml/img/signerroricon32.png"
width: 30
height: 30
action: goToCompilationError
style: ButtonStyle {
background: Rectangle {
color: "transparent"
Image {
source: "qrc:/qml/img/warningicon.png"
height: 30
width: 30
sourceSize.width: 30
sourceSize.height: 30
anchors.centerIn: parent
}
}
}
}
}
}

122
mix/qml/StepActionImage.qml

@ -4,15 +4,22 @@ import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
Rectangle {
id: buttonActionContainer
color: "transparent"
property string disableStateImg
property string enabledStateImg
property string buttonTooltip
property string buttonShortcut
property bool buttonLeft
property bool buttonRight
signal clicked
color: "transparent"
width: 35
height: 24
function enabled(state)
{
buttonAction.enabled = state;
@ -22,29 +29,104 @@ Rectangle {
debugImage.source = disableStateImg;
}
Button
{
anchors.fill: parent
id: debugImg
/* iconSource: enabledStateImg
*/ action: buttonAction
Rectangle {
color: "#DCDADA"
width: 10
height: 24
radius: 4
x: 0
visible: buttonLeft
Rectangle {
anchors {
left: parent.left
right: parent.right
top: parent.top
bottom: parent.bottom
bottomMargin:debugImg.pressed? 0 : 1;
topMargin:debugImg.pressed? 1 : 0;
}
color: "#FCFBFC"
radius: 3
}
}
Image {
id: debugImage
source: enabledStateImg
anchors.centerIn: parent
fillMode: Image.PreserveAspectFit
width: 15
height: 15
Rectangle {
color: "#DCDADA"
width: 10
height: 24
radius: 4
x: 25
visible: buttonRight
Rectangle {
anchors {
left: parent.left
right: parent.right
top: parent.top
bottom: parent.bottom
bottomMargin:debugImg.pressed? 0 : 1;
topMargin:debugImg.pressed? 1 : 0;
}
color: "#FCFBFC"
radius: 3
}
}
Action {
tooltip: buttonTooltip
id: buttonAction
shortcut: buttonShortcut
onTriggered: {
buttonActionContainer.clicked();
Rectangle {
id: contentRectangle
width: 25
height: 24
color: "#DCDADA"
x: 5
Rectangle {
anchors {
left: parent.left
right: parent.right
top: parent.top
bottom: parent.bottom
bottomMargin:debugImg.pressed? 0 : 1;
topMargin:debugImg.pressed? 1 : 0;
}
color: "#FCFBFC"
Image {
id: debugImage
source: enabledStateImg
anchors.centerIn: parent
anchors.topMargin: debugImg.pressed? 1 : 0;
fillMode: Image.PreserveAspectFit
width: 15
height: 15
}
}
Button {
anchors.fill: parent
id: debugImg
action: buttonAction
style: Rectangle {
color: "transparent"
}
}
Action {
tooltip: buttonTooltip
id: buttonAction
shortcut: buttonShortcut
onTriggered: {
// contentRectangle.anchors.bottomMargin = 0
// contentRectangle.anchors.topMargin = 1
buttonActionContainer.clicked();
}
}
}
}

2
mix/qml/WebCodeEditor.qml

@ -18,6 +18,7 @@ Item {
property bool unloaded: false
property var currentBreakpoints: []
property string sourceName
property var document
function setText(text, mode) {
currentText = text;
@ -117,6 +118,7 @@ Item {
codeModel.onCompilationError.connect(compilationError);
}
parent.changeGeneration();
loadComplete();
}
}

12
mix/qml/html/cm/solarized.css

@ -154,8 +154,10 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png
}
/*
Active line. Negative margin compensates left padding of the text in the
view-port
*/
.cm-s-solarized.cm-s-dark .CodeMirror-activeline-background {
background: rgba(255, 255, 255, 0.10);
@ -166,20 +168,24 @@ view-port
/* Code execution */
.CodeMirror-exechighlight {
background: #eee8d5;
border-bottom: double 1px #94A2A2;
}
/* Error annotation */
.CodeMirror-errorannotation {
border-bottom: 1px solid #b58900;
border-bottom: 1px solid #DD3330;
margin-bottom: 4px;
}
.CodeMirror-errorannotation-context {
font-family: monospace;
font-size: small;
color: #586e75;
color: #EEE9D5;
background: #b58900;
padding: 2px;
text-shadow: none !important;
border-top: solid 2px #063742;
}
span.CodeMirror-selectedtext { color: #586e75 !important; }

BIN
mix/qml/img/closedtriangleindicator.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 422 B

After

Width:  |  Height:  |  Size: 242 B

BIN
mix/qml/img/closedtriangleindicator@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

BIN
mix/qml/img/opentriangleindicator.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 425 B

After

Width:  |  Height:  |  Size: 257 B

BIN
mix/qml/img/opentriangleindicator@2x.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 836 B

After

Width:  |  Height:  |  Size: 429 B

BIN
mix/qml/img/signerroricon32.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

BIN
mix/qml/img/warningicon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

BIN
mix/qml/img/warningicon@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

3
mix/qml/js/ProjectModel.js

@ -124,7 +124,8 @@ function loadProject(path) {
for(var i = 0; i < projectData.files.length; i++) {
addFile(projectData.files[i]);
}
projectSettings.lastProjectPath = path;
if (mainApplication.trackLastProject)
projectSettings.lastProjectPath = path;
projectLoading(projectData);
projectLoaded()

5
mix/res.qrc

@ -20,6 +20,7 @@
<file>qml/img/bugiconactive.png</file>
<file>qml/img/bugiconinactive.png</file>
<file>qml/img/closedtriangleindicator.png</file>
<file>qml/img/closedtriangleindicator@2x.png</file>
<file>qml/img/closedtriangleindicator_filesproject.png</file>
<file>qml/img/console.png</file>
<file>qml/img/copy.png</file>
@ -43,6 +44,7 @@
<file>qml/img/note.png</file>
<file>qml/img/openedfolder.png</file>
<file>qml/img/opentriangleindicator.png</file>
<file>qml/img/opentriangleindicator@2x.png</file>
<file>qml/img/opentriangleindicator_filesproject.png</file>
<file>qml/img/plus.png</file>
<file>qml/img/projecticon.png</file>
@ -63,6 +65,7 @@
<file>qml/img/copyiconactive.png</file>
<file>qml/img/searchicon.png</file>
<file>qml/img/stop_button2x.png</file>
<file>qml/img/signerroricon32.png</file>
<file>qml/img/warningicon.png</file>
<file>qml/img/warningicon@2x.png</file>
</qresource>
</RCC>

8
mix/test/qml/TestMain.qml

@ -30,18 +30,20 @@ TestCase
Application
{
id: mainApplication
trackLastProject: false
}
function newProject()
{
waitForRendering(mainApplication.mainContent, 10000);
mainApplication.projectModel.createProject();
var projectDlg = mainApplication.projectModel.newProjectDialog;
wait(30);
projectDlg.projectTitle = "TestProject";
projectDlg.pathFieldText = "/tmp/MixTest"; //TODO: get platform temp path
projectDlg.acceptAndClose();
wait(30);
wait(1);
if (!ts.waitForSignal(mainApplication.codeModel, "compilationComplete()", 5000))
fail("new contract not compiled");
}
function editContract(c)
@ -55,7 +57,7 @@ TestCase
function editHtml(c)
{
mainApplication.projectModel.openDocument("index.html");
wait(1);
ts.waitForSignal(mainApplication.mainContent.codeEditor, "loadComplete()", 5000);
mainApplication.mainContent.codeEditor.getEditor("index.html").setText(c);
ts.keyPressChar(mainApplication, "S", Qt.ControlModifier, 200); //Ctrl+S
}

1
mix/test/qml/js/TestDebugger.js

@ -75,7 +75,6 @@ function test_constructorParameters()
ts.typeString("442", transactionDialog);
transactionDialog.acceptAndClose();
mainApplication.projectModel.stateDialog.model.addTransaction();
ts.waitForRendering(transactionDialog, 3000);
transactionDialog.selectFunction("getZ");
transactionDialog.acceptAndClose();
mainApplication.projectModel.stateDialog.acceptAndClose();

1
test/TestUtils.cpp

@ -22,6 +22,7 @@
#include <thread>
#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>
#include <libtestutils/Common.h>
#include <libtestutils/BlockChainLoader.h>
#include <libtestutils/FixedClient.h>
#include "TestUtils.h"

9
test/blockchain.cpp

@ -22,7 +22,7 @@
#include <boost/filesystem.hpp>
#include <libdevcrypto/FileSystem.h>
#include <libtestutils/TransientDirectory.h>
#include <libdevcore/TransientDirectory.h>
#include <libethereum/CanonBlockChain.h>
#include "TestHelper.h"
@ -192,7 +192,8 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
state.sync(bc, txs, gp);
state.commitToMine(bc);
MineInfo info;
for (info.completed = false; !info.completed; info = state.mine()) {}
ProofOfWork pow;
for (info.completed = false; !info.completed; info = state.mine(&pow)) {}
state.completeMine();
}
catch (Exception const& _e)
@ -577,7 +578,7 @@ void overwriteBlockHeader(BlockInfo& _currentBlockHeader, mObject& _blObj)
std::pair<MineInfo, Ethash::Proof> ret;
while (!ProofOfWork::verify(_currentBlockHeader))
{
ret = pow.mine(_currentBlockHeader, 1000, true, true);
ret = pow.mine(_currentBlockHeader, 1000, true);
Ethash::assignResult(ret.second, _currentBlockHeader);
}
}
@ -623,7 +624,7 @@ void updatePoW(BlockInfo& _bi)
std::pair<MineInfo, Ethash::Proof> ret;
while (!ProofOfWork::verify(_bi))
{
ret = pow.mine(_bi, 10000, true, true);
ret = pow.mine(_bi, 10000, true);
Ethash::assignResult(ret.second, _bi);
}
_bi.noteDirty();

2
test/state.cpp

@ -218,6 +218,8 @@ BOOST_AUTO_TEST_CASE(stCreateTest)
BOOST_AUTO_TEST_CASE(stRandom)
{
test::Options::get(); // parse command line options, e.g. to enable JIT
string testPath = dev::test::getTestPath();
testPath += "/StateTests/RandomTests";

5
test/stateOriginal.cpp

@ -68,7 +68,8 @@ BOOST_AUTO_TEST_CASE(Complex)
// Mine to get some ether!
s.commitToMine(bc);
while (!s.mine(100, true).completed) {}
ProofOfWork pow;
while (!s.mine(&pow).completed) {}
s.completeMine();
bc.attemptImport(s.blockData(), stateDB);
@ -88,7 +89,7 @@ BOOST_AUTO_TEST_CASE(Complex)
// Mine to get some ether and set in stone.
s.commitToMine(bc);
s.commitToMine(bc);
while (!s.mine(100, true).completed) {}
while (!s.mine(&pow).completed) {}
s.completeMine();
bc.attemptImport(s.blockData(), stateDB);

2
test/vm.cpp

@ -524,6 +524,8 @@ BOOST_AUTO_TEST_CASE(vmInputLimitsLightTest)
BOOST_AUTO_TEST_CASE(vmRandom)
{
test::Options::get(); // parse command line options, e.g. to enable JIT
string testPath = getTestPath();
testPath += "/VMTests/RandomTests";

10
test/webthreestubclient.h

@ -72,6 +72,16 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_hashrate() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_hashrate",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_coinbase() throw (jsonrpc::JsonRpcException)
{
Json::Value p;

Loading…
Cancel
Save