Browse Source

Merge remote-tracking branch 'upstream/develop' into evmjit_stack

Conflicts:
	evmjit/libevmjit/BasicBlock.cpp
	evmjit/libevmjit/BasicBlock.h
cl-refactor
Paweł Bylica 9 years ago
parent
commit
25cd835b47
  1. 1
      .gitignore
  2. 4
      BuildInfo.h.in
  3. 284
      CMakeLists.txt
  4. 2
      README.md
  5. 133
      alethzero/AllAccounts.cpp
  6. 60
      alethzero/AllAccounts.h
  7. 134
      alethzero/AllAccounts.ui
  8. 71
      alethzero/BrainWallet.cpp
  9. 44
      alethzero/BrainWallet.h
  10. 136
      alethzero/BrainWallet.ui
  11. 22
      alethzero/CMakeLists.txt
  12. 3
      alethzero/Connect.cpp
  13. 14
      alethzero/Connect.h
  14. 15
      alethzero/Context.cpp
  15. 11
      alethzero/Context.h
  16. 2
      alethzero/DappHost.cpp
  17. 8
      alethzero/DappHost.h
  18. 13
      alethzero/DappLoader.cpp
  19. 11
      alethzero/DappLoader.h
  20. 3
      alethzero/Debugger.cpp
  21. 9
      alethzero/Debugger.h
  22. 8
      alethzero/DownloadView.cpp
  23. 13
      alethzero/DownloadView.h
  24. 6
      alethzero/ExportState.cpp
  25. 16
      alethzero/ExportState.h
  26. 96
      alethzero/LogPanel.cpp
  27. 64
      alethzero/LogPanel.h
  28. 99
      alethzero/LogPanel.ui
  29. 392
      alethzero/Main.ui
  30. 71
      alethzero/MainFace.cpp
  31. 118
      alethzero/MainFace.h
  32. 416
      alethzero/MainWin.cpp
  33. 99
      alethzero/MainWin.h
  34. 7
      alethzero/MiningView.cpp
  35. 15
      alethzero/MiningView.h
  36. 5
      alethzero/NatspecHandler.cpp
  37. 8
      alethzero/NatspecHandler.h
  38. 3
      alethzero/OurWebThreeStubServer.cpp
  39. 31
      alethzero/OurWebThreeStubServer.h
  40. 132
      alethzero/Transact.cpp
  41. 28
      alethzero/Transact.h
  42. 7
      alethzero/Transact.ui
  43. 4
      alethzero/WebPage.cpp
  44. 13
      alethzero/WebPage.h
  45. 2
      alethzero/main.cpp
  46. 2
      cmake/EthDependencies.cmake
  47. 2
      cmake/EthExecutableHelper.cmake
  48. 71
      cmake/scripts/macdeployfix.sh
  49. 1017
      eth/main.cpp
  50. 107
      ethkey/KeyAux.h
  51. 1
      ethminer/CMakeLists.txt
  52. 3
      ethrpctest/CommandLineInterface.cpp
  53. 20
      ethvm/main.cpp
  54. 20
      evmjit/CMakeLists.txt
  55. 14
      evmjit/include/evmjit/JIT-c.h
  56. 2
      evmjit/libevmjit-cpp/Env.cpp
  57. 14
      evmjit/libevmjit-cpp/JitVM.cpp
  58. 2
      evmjit/libevmjit/BasicBlock.h
  59. 2
      evmjit/libevmjit/Compiler.cpp
  60. 10
      evmjit/libevmjit/CompilerHelper.h
  61. 2
      evmjit/libevmjit/Ext.cpp
  62. 2
      evmjit/libevmjit/Ext.h
  63. 6
      evmjit/libevmjit/JIT-c.cpp
  64. 2
      evmjit/libevmjit/preprocessor/llvm_includes_start.h
  65. 12
      exp/main.cpp
  66. 8
      extdep/getstuff.bat
  67. 5
      libdevcore/Base64.h
  68. 10
      libdevcore/CMakeLists.txt
  69. 4
      libdevcore/Common.cpp
  70. 41
      libdevcore/Common.h
  71. 7
      libdevcore/CommonData.cpp
  72. 20
      libdevcore/CommonData.h
  73. 17
      libdevcore/CommonIO.cpp
  74. 2
      libdevcore/CommonIO.h
  75. 11
      libdevcore/CommonJS.h
  76. 2
      libdevcore/Exceptions.h
  77. 4
      libdevcore/FileSystem.cpp
  78. 2
      libdevcore/FixedHash.cpp
  79. 95
      libdevcore/FixedHash.h
  80. 5
      libdevcore/Guards.h
  81. 5
      libdevcore/Log.h
  82. 9
      libdevcore/SHA3.cpp
  83. 19
      libdevcore/SHA3.h
  84. 2
      libdevcore/TransientDirectory.cpp
  85. 7
      libdevcore/Worker.h
  86. 34
      libdevcore/vector_ref.h
  87. 2
      libdevcrypto/AES.h
  88. 6
      libdevcrypto/CMakeLists.txt
  89. 137
      libdevcrypto/Common.cpp
  90. 73
      libdevcrypto/Common.h
  91. 18
      libdevcrypto/CryptoPP.cpp
  92. 6
      libdevcrypto/CryptoPP.h
  93. 2
      libdevcrypto/ECDHE.cpp
  94. 4
      libdevcrypto/ECDHE.h
  95. 67
      libdevcrypto/SecretStore.cpp
  96. 14
      libdevcrypto/SecretStore.h
  97. 5036
      libdevcrypto/WordList.cpp
  98. 31
      libdevcrypto/WordList.h
  99. 80
      libethash-cl/ethash_cl_miner.cpp
  100. 5
      libethcore/ABI.h

1
.gitignore

@ -39,7 +39,6 @@ extdep/download
*.pyc
# MacOS Development
.DS_Store
# CocoaPods

4
BuildInfo.h.in

@ -1,7 +1,7 @@
#pragma once
#define ETH_PROJECT_VERSION "@PROJECT_VERSION@"
#define ETH_COMMIT_HASH @ETH_COMMIT_HASH@
#define ETH_CLEAN_REPO @ETH_CLEAN_REPO@
#define ETH_BUILD_TYPE @ETH_BUILD_TYPE@
#define ETH_BUILD_PLATFORM @ETH_BUILD_PLATFORM@
#define ETH_BUILD_PLATFORM @ETH_BUILD_PLATFORM@

284
CMakeLists.txt

@ -1,7 +1,14 @@
# cmake global
cmake_minimum_required(VERSION 2.8.12)
project(ethereum)
set(PROJECT_VERSION "0.9.40")
if (${CMAKE_VERSION} VERSION_GREATER 3.0)
cmake_policy(SET CMP0042 OLD) # fix MACOSX_RPATH
cmake_policy(SET CMP0048 NEW) # allow VERSION argument in project()
project(ethereum VERSION ${PROJECT_VERSION})
else()
project(ethereum)
endif()
set(CMAKE_AUTOMOC ON)
@ -22,29 +29,123 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
######################################################################################################
# user defined, defaults
# Normally, set(...CACHE...) creates cache variables, but does not modify them.
option(VMTRACE "VM tracing and run-time checks (useful for cross-implementation VM debugging)" OFF)
option(PARANOID "Additional run-time checks" OFF)
option(JSONRPC "Build with jsonprc. default on" ON)
option(FATDB "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." OFF)
option(USENPM "Use npm to recompile ethereum.js if it was changed" OFF)
option(PROFILING "Build in support for profiling" OFF)
option(ROCKSDB "Use rocksdb rather than leveldb" OFF)
set(BUNDLE "none" CACHE STRING "Predefined bundle of software to build (none, full, user, tests, minimal).")
option(MINER "Build the CLI miner component" ON)
option(ETHKEY "Build the CLI key manager component" ON)
option(SOLIDITY "Build the Solidity language components" ON)
option(SERPENT "Build the Serpent language components" ON)
option(TOOLS "Build the tools components" ON)
option(GUI "Build GUI components (AlethZero, Mix)" ON)
option(TESTS "Build the tests." ON)
option(NOBOOST "No use of boost macros in test functions" OFF)
option(EVMJIT "Build just-in-time compiler for EVM code (requires LLVM)" OFF)
option(ETHASHCL "Build in support for GPU mining via OpenCL" ON)
option(JSCONSOLE "Build in javascript console" ON)
option(FRONTIER "Build for Frontier network" OFF)
# note: The value "default" which provides the defaults is just a fake value
# which lets us keep the default values of all build options and is set at
# the beginning of this file.
# TODO: Abstract into something sensible and move into a function.
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(DECENT_PLATFORM OFF)
else ()
set(DECENT_PLATFORM ON)
endif ()
#defaults:
set(D_CMAKE_BUILD_TYPE "RelWithDebInfo")
set(D_SERPENT ${DECENT_PLATFORM})
set(D_SOLIDITY ON)
set(D_USENPM OFF)
set(D_GUI ON)
set(D_TOOLS ON)
set(D_TESTS ON)
set(D_FATDB ON)
set(D_ETHASHCL ON)
set(D_EVMJIT ON)
set(D_JSCONSOLE ON)
set(D_JSONRPC ON)
set(D_VMTRACE OFF)
set(D_PARANOID OFF)
set(D_PROFILING OFF)
set(D_ROCKSDB OFF)
set(D_NOBOOST OFF)
set(D_OLYMPIC OFF)
set(D_MINER ON)
set(D_ETHKEY ON)
if (BUNDLE STREQUAL "minimal")
set(D_SERPENT OFF)
set(D_SOLIDITY OFF)
set(D_USENPM OFF)
set(D_GUI OFF)
set(D_TOOLS ON)
set(D_TESTS OFF)
elseif (BUNDLE STREQUAL "full")
set(D_SERPENT ${DECENT_PLATFORM})
set(D_SOLIDITY ON)
set(D_USENPM ON)
set(D_GUI ON)
set(D_TOOLS ON)
set(D_TESTS ON)
set(D_FATDB ON)
elseif (BUNDLE STREQUAL "cli")
set(D_SERPENT ${DECENT_PLATFORM})
set(D_SOLIDITY ON)
set(D_USENPM ON)
set(D_GUI OFF)
set(D_TOOLS ON)
set(D_TESTS ON)
set(D_FATDB ON)
elseif (BUNDLE STREQUAL "core")
set(D_SERPENT OFF)
set(D_SOLIDITY ON)
set(D_USENPM OFF)
set(D_GUI ON)
set(D_TOOLS ON)
set(D_TESTS OFF)
set(D_FATDB ON)
elseif (BUNDLE STREQUAL "tests")
set(D_SERPENT ${DECENT_PLATFORM})
set(D_SOLIDITY ON)
set(D_USENPM OFF)
set(D_GUI OFF)
set(D_TOOLS OFF)
set(D_TESTS ON)
set(D_FATDB ON)
elseif (BUNDLE STREQUAL "user")
set(D_SERPENT OFF)
set(D_SOLIDITY OFF)
set(D_USENPM OFF)
set(D_GUI ON)
set(D_TOOLS ON)
set(D_TESTS OFF)
elseif (BUNDLE STREQUAL "wallet")
set(D_SERPENT OFF)
set(D_SOLIDITY OFF)
set(D_USENPM OFF)
set(D_GUI OFF)
set(D_TOOLS OFF)
set(D_TESTS OFF)
set(D_ETHKEY ON)
set(D_MINER OFF)
set(D_ETHASHCL ON)
elseif (BUNDLE STREQUAL "miner")
set(D_SERPENT OFF)
set(D_SOLIDITY OFF)
set(D_USENPM OFF)
set(D_GUI OFF)
set(D_TOOLS OFF)
set(D_TESTS OFF)
set(D_ETHKEY OFF)
set(D_MINER ON)
set(D_ETHASHCL ON)
elseif (BUNDLE STREQUAL "release") # release builds
set(D_SERPENT ${DECENT_PLATFORM})
set(D_SOLIDITY ON)
set(D_USENPM OFF)
set(D_GUI ON)
set(D_TOOLS ON)
set(D_TESTS OFF)
set(D_FATDB OFF)
set(D_ETHASHCL ON)
set(D_EVMJIT ON)
set(D_JSCONSOLE ON)
set(D_JSONRPC ON)
set(D_CMAKE_BUILD_TYPE "Release")
endif ()
if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
set(CMAKE_BUILD_TYPE ${D_CMAKE_BUILD_TYPE})
endif ()
# propagates CMake configuration options to the compiler
function(configureProject)
@ -88,7 +189,9 @@ function(configureProject)
add_definitions(-DNOBOOST)
endif()
if (FRONTIER)
if (OLYMPIC)
add_definitions(-DETH_OLYMPIC)
else()
add_definitions(-DETH_FRONTIER)
endif()
@ -136,6 +239,7 @@ function(createBuildInfo)
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND ${CMAKE_COMMAND} -DETH_SOURCE_DIR="${CMAKE_SOURCE_DIR}" -DETH_DST_DIR="${CMAKE_BINARY_DIR}"
-DETH_BUILD_TYPE="${_cmake_build_type}" -DETH_BUILD_PLATFORM="${ETH_BUILD_PLATFORM}"
-DPROJECT_VERSION="${PROJECT_VERSION}"
-P "${ETH_SCRIPTS_DIR}/buildinfo.cmake"
)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
@ -170,24 +274,11 @@ if (HEADLESS)
set(GUI OFF)
endif ()
# TODO: Abstract into something sensible and move into a function.
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(DECENT_PLATFORM OFF)
else ()
set(DECENT_PLATFORM ON)
endif ()
macro(eth_format_option O)
if (${${O}})
set(${O} ON)
else()
set(${O} OFF)
endif()
endmacro()
macro(eth_format_option_on_decent_platform O)
if (${${O}})
set(${O} ${DECENT_PLATFORM})
elseif ("${${O}}" STREQUAL "" AND ${D_${O}})
set(${O} ON)
else()
set(${O} OFF)
endif()
@ -212,8 +303,8 @@ eth_format_option(TOOLS)
eth_format_option(ETHKEY)
eth_format_option(ETHASHCL)
eth_format_option(JSCONSOLE)
eth_format_option(FRONTIER)
eth_format_option_on_decent_platform(SERPENT)
eth_format_option(OLYMPIC)
eth_format_option(SERPENT)
if (JSCONSOLE)
set(JSONRPC ON)
@ -223,94 +314,8 @@ if (GUI)
set(JSONRPC ON)
endif()
# note: The value "default" which provides the defaults is just a fake value
# which lets us keep the default values of all build options and is set at
# the beginning of this file.
if (BUNDLE STREQUAL "minimal")
set(SERPENT OFF)
set(SOLIDITY OFF)
set(USENPM OFF)
set(GUI OFF)
set(TOOLS ON)
set(TESTS OFF)
elseif (BUNDLE STREQUAL "full")
set(SERPENT ${DECENT_PLATFORM})
set(SOLIDITY ON)
set(USENPM ON)
set(GUI ON)
set(TOOLS ON)
set(TESTS ON)
set(FATDB ON)
elseif (BUNDLE STREQUAL "cli")
set(SERPENT ${DECENT_PLATFORM})
set(SOLIDITY ON)
set(USENPM ON)
set(GUI OFF)
set(TOOLS ON)
set(TESTS ON)
set(FATDB ON)
elseif (BUNDLE STREQUAL "core")
set(SERPENT OFF)
set(SOLIDITY ON)
set(USENPM OFF)
set(GUI ON)
set(TOOLS ON)
set(TESTS OFF)
set(FATDB ON)
elseif (BUNDLE STREQUAL "tests")
set(SERPENT ${DECENT_PLATFORM})
set(SOLIDITY ON)
set(USENPM OFF)
set(GUI OFF)
set(TOOLS OFF)
set(TESTS ON)
set(FATDB ON)
elseif (BUNDLE STREQUAL "user")
set(SERPENT OFF)
set(SOLIDITY OFF)
set(USENPM OFF)
set(GUI ON)
set(TOOLS ON)
set(TESTS OFF)
elseif (BUNDLE STREQUAL "wallet")
set(SERPENT OFF)
set(SOLIDITY OFF)
set(USENPM OFF)
set(GUI OFF)
set(TOOLS OFF)
set(TESTS OFF)
set(ETHKEY ON)
set(MINER OFF)
set(ETHASHCL ON)
elseif (BUNDLE STREQUAL "miner")
set(SERPENT OFF)
set(SOLIDITY OFF)
set(USENPM OFF)
set(GUI OFF)
set(TOOLS OFF)
set(TESTS OFF)
set(ETHKEY OFF)
set(MINER ON)
set(ETHASHCL ON)
elseif (BUNDLE STREQUAL "release")
set(SERPENT OFF)
set(SOLIDITY ON)
set(USENPM OFF)
set(GUI ON)
set(TOOLS ON)
set(TESTS OFF)
set(FATDB OFF)
set(ETHASHCL ON)
set(EVMJIT ON)
set(JSCONSOLE ON)
set(JSONRPC ON)
endif ()
# Default CMAKE_BUILD_TYPE to "Release".
set(CMAKE_BUILD_TYPE CACHE STRING "Release")
if ("x${CMAKE_BUILD_TYPE}" STREQUAL "x")
set(CMAKE_BUILD_TYPE "Release")
endif ()
# Default CMAKE_BUILD_TYPE accordingly.
set(CMAKE_BUILD_TYPE CACHE STRING ${D_CMAKE_BUILD_TYPE})
# Default TARGET_PLATFORM to ${CMAKE_SYSTEM_NAME}
# change this once we support cross compiling
@ -339,7 +344,7 @@ message("-- FATDB Full database exploring ${FATDB}")
message("-- JSONRPC JSON-RPC support ${JSONRPC}")
message("-- USENPM Javascript source building ${USENPM}")
message("-- ROCKSDB Prefer rocksdb to leveldb ${ROCKSDB}")
message("-- FRONTIER Default to the Frontier network ${FRONTIER}")
message("-- OLYMPIC Default to the Olympic network ${OLYMPIC}")
message("------------------------------------------------------------- components")
message("-- MINER Build miner ${MINER}")
message("-- ETHKEY Build wallet tools ${ETHKEY}")
@ -374,9 +379,14 @@ else()
endif()
if (EVMJIT)
if (CMAKE_SYSTEM_NAME STREQUAL "Windows" AND NOT DEFINED LLVM_DIR)
set(LLVM_DIR "${CMAKE_SOURCE_DIR}/extdep/install/windows/x64/share/llvm/cmake")
if (NOT DEFINED LLVM_DIR)
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(LLVM_DIR "${CMAKE_SOURCE_DIR}/extdep/install/windows/x64/share/llvm/cmake")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(LLVM_DIR "/usr/local/opt/llvm/share/llvm/cmake")
endif()
endif()
set(EVMJIT_CPP TRUE) # include CPP-JIT connector
add_subdirectory(evmjit)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
@ -517,12 +527,12 @@ endif ()
if (WIN32)
# packaging stuff
include(InstallRequiredSystemLibraries)
set(CPACK_PACKAGE_NAME "Ethereum (++)")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The Ethereum (++) Toolset")
set(CPACK_PACKAGE_NAME "Ethereum")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The Ethereum Toolset")
set(CPACK_PACKAGE_VENDOR "ethereum.org")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VERSION "0.9.34")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_GENERATOR "NSIS")
# seems to be not working
# set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/alethzero/alethzero.bmp")
@ -547,7 +557,7 @@ if (WIN32)
set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION}")
endif()
set(CPACK_NSIS_DISPLAY_NAME "Ethereum (++)")
set(CPACK_NSIS_DISPLAY_NAME "Ethereum")
set(CPACK_NSIS_HELP_LINK "https://github.com/ethereum/cpp-ethereum")
set(CPACK_NSIS_URL_INFO_ABOUT "https://github.com/ethereum/cpp-ethereum")
set(CPACK_NSIS_CONTACT "ethereum.org")

2
README.md

@ -24,7 +24,7 @@ Ethereum is based on a design in an original whitepaper by Vitalik Buterin. This
- *LianaHus* (**Liana Husikyan**) Solidity
- *chfast* (**Paweł Bylica**) EVMJIT
- *cubedro* (**Marian Oancea**) web3.js
- *gluk250* (**Vlad Gluhovsky**) Whisper
- *gluk256* (**Vlad Gluhovsky**) Whisper
- *programmerTim* (**Tim Hughes**) libethash-cl
And let's not forget: Caktux (neth, ongoing CI), Eric Lombrozo (original MinGW32 cross-compilation), Marko Simovic (original CI).

133
alethzero/AllAccounts.cpp

@ -0,0 +1,133 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AllAccounts.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "AllAccounts.h"
#include <sstream>
#include <QClipboard>
#include <libdevcore/Log.h>
#include <libdevcore/SHA3.h>
#include <libevmcore/Instruction.h>
#include <libethereum/Client.h>
#include "ui_AllAccounts.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
AllAccounts::AllAccounts(MainFace* _m):
Plugin(_m, "AllAccounts"),
m_ui(new Ui::AllAccounts)
{
dock(Qt::RightDockWidgetArea, "All Accounts")->setWidget(new QWidget());
m_ui->setupUi(dock()->widget());
installWatches();
refresh();
connect(m_ui->accounts, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), SLOT(on_accounts_currentItemChanged()));
connect(m_ui->accounts, SIGNAL(doubleClicked(QModelIndex)), SLOT(on_accounts_doubleClicked()));
connect(m_ui->refreshAccounts, SIGNAL(clicked()), SLOT(refresh()));
connect(m_ui->accountsFilter, SIGNAL(textChanged(QString)), SLOT(onAllChange()));
connect(m_ui->showBasic, SIGNAL(toggled(bool)), SLOT(onAllChange()));
connect(m_ui->showContracts, SIGNAL(toggled(bool)), SLOT(onAllChange()));
connect(m_ui->onlyNamed, SIGNAL(toggled(bool)), SLOT(onAllChange()));
}
AllAccounts::~AllAccounts()
{
}
void AllAccounts::installWatches()
{
main()->installWatch(ChainChangedFilter, [=](LocalisedLogEntries const&){ onAllChange(); });
main()->installWatch(PendingChangedFilter, [=](LocalisedLogEntries const&){ onAllChange(); });
}
void AllAccounts::refresh()
{
DEV_TIMED_FUNCTION;
#if ETH_FATDB || !ETH_TRUE
cwatch << "refreshAccounts()";
m_ui->accounts->clear();
bool showContract = m_ui->showContracts->isChecked();
bool showBasic = m_ui->showBasic->isChecked();
bool onlyNamed = m_ui->onlyNamed->isChecked();
auto as = ethereum()->addresses();
sort(as.begin(), as.end());
for (auto const& i: as)
{
bool isContract = (ethereum()->codeHashAt(i) != EmptySHA3);
if (!((showContract && isContract) || (showBasic && !isContract)))
continue;
string r = static_cast<Context*>(main())->render(i);
if (onlyNamed && !(r.find('"') != string::npos || r.substr(0, 2) == "XE"))
continue;
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), m_ui->accounts))
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size));
}
#endif
m_ui->refreshAccounts->setEnabled(false);
}
void AllAccounts::onAllChange()
{
m_ui->refreshAccounts->setEnabled(true);
}
void AllAccounts::on_accounts_currentItemChanged()
{
m_ui->accountInfo->clear();
if (auto item = m_ui->accounts->currentItem())
{
auto hba = item->data(Qt::UserRole).toByteArray();
assert(hba.size() == 20);
auto address = h160((byte const*)hba.data(), h160::ConstructFromPointer);
stringstream s;
try
{
auto storage = ethereum()->storageAt(address);
for (auto const& i: storage)
s << "@" << showbase << hex << main()->prettyU256(i.first) << "&nbsp;&nbsp;&nbsp;&nbsp;" << showbase << hex << main()->prettyU256(i.second) << "<br/>";
s << "<h4>Body Code (" << sha3(ethereum()->codeAt(address)).abridged() << ")</h4>" << disassemble(ethereum()->codeAt(address));
s << ETH_HTML_DIV(ETH_HTML_MONO) << toHex(ethereum()->codeAt(address)) << "</div>";
s << "<h4>Creation Addresses (" << ethereum()->countAt(address) << "+)</h4>";
for (auto i = 0; i < 5; ++i)
s << ETH_HTML_DIV(ETH_HTML_MONO) << toAddress(address, ethereum()->countAt(address) + i).hex() << "</div>";
m_ui->accountInfo->appendHtml(QString::fromStdString(s.str()));
}
catch (dev::InvalidTrie)
{
m_ui->accountInfo->appendHtml("Corrupted trie.");
}
m_ui->accountInfo->moveCursor(QTextCursor::Start);
}
}
void AllAccounts::on_accounts_doubleClicked()
{
if (m_ui->accounts->count())
{
auto hba = m_ui->accounts->currentItem()->data(Qt::UserRole).toByteArray();
auto h = Address((byte const*)hba.data(), Address::ConstructFromPointer);
qApp->clipboard()->setText(QString::fromStdString(toHex(h.asArray())));
}
}

60
alethzero/AllAccounts.h

@ -0,0 +1,60 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AllAccounts.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <QListWidget>
#include <QPlainTextEdit>
#include "MainFace.h"
namespace Ui
{
class AllAccounts;
}
namespace dev
{
namespace az
{
class AllAccounts: public QObject, public Plugin
{
Q_OBJECT
public:
AllAccounts(MainFace* _m);
~AllAccounts();
private slots:
void on_accounts_currentItemChanged();
void on_accounts_doubleClicked();
void onAllChange();
void refresh();
private:
void installWatches();
Ui::AllAccounts* m_ui;
};
}
}

134
alethzero/AllAccounts.ui

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AllAccounts</class>
<widget class="QWidget" name="AllAccounts">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLineEdit" name="accountsFilter">
<property name="placeholderText">
<string>Filter...</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showBasic">
<property name="text">
<string>Basic</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showContracts">
<property name="text">
<string>Contracts</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="onlyNamed">
<property name="text">
<string>Only Named</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="refreshAccounts">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QSplitter" name="splitter_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QListWidget" name="accounts">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QPlainTextEdit" name="accountInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

71
alethzero/BrainWallet.cpp

@ -0,0 +1,71 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file BrainWallet.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "BrainWallet.h"
#include <QMenu>
#include <QDialog>
#include <boost/random/random_device.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <libdevcore/Log.h>
#include <libdevcrypto/WordList.h>
#include <libethcore/KeyManager.h>
#include <libethereum/Client.h>
#include "ui_BrainWallet.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
BrainWallet::BrainWallet(MainFace* _m):
Plugin(_m, "BrainWallet")
{
QAction* a = new QAction("New Brain Wallet...", main());
QMenu* m = _m->findChild<QMenu*>("menuTools");
m->addSeparator();
m->addAction(a);
connect(a, SIGNAL(triggered()), SLOT(create()));
}
BrainWallet::~BrainWallet()
{
}
void BrainWallet::create()
{
QDialog d;
Ui_BrainWallet u;
u.setupUi(&d);
d.setWindowTitle("New Brain Wallet");
connect(u.generate, &QPushButton::clicked, [&](){
boost::random_device d;
boost::random::uniform_int_distribution<unsigned> pickWord(0, WordList.size() - 1);
QString t;
for (int i = 0; i < 13; ++i)
t += (t.size() ? " " : "") + QString::fromStdString(WordList[pickWord(d)]);
u.seed->setPlainText(t);
});
if (d.exec() == QDialog::Accepted)
{
main()->keyManager().importBrain(u.seed->toPlainText().trimmed().toStdString(), u.name->text().toStdString(), u.hint->toPlainText().toStdString());
main()->noteKeysChanged();
}
}

44
alethzero/BrainWallet.h

@ -0,0 +1,44 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file BrainWallet.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include "MainFace.h"
namespace dev
{
namespace az
{
class BrainWallet: public QObject, public Plugin
{
Q_OBJECT
public:
BrainWallet(MainFace* _m);
~BrainWallet();
private slots:
void create();
};
}
}

136
alethzero/BrainWallet.ui

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BrainWallet</class>
<widget class="QDialog" name="BrainWallet">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>511</width>
<height>508</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;WARNING: Brain wallets, or human-entropic seeds, are practically and cryptographically insecure. They're a terrible idea for protecteding anything of value and this functionality is here only as a toy.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;That said, if you're intent on using one, make the phrase as long and random as you can. If you're sensible, you'll ask the internet for a list of words to memorise and use those. Write the phrase down on paper and bury it under an oak tree or something - if you forget it, you're screwed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="name">
<property name="placeholderText">
<string>Please name of this account here e.g. My Brain Wallet</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="seed">
<property name="placeholderText">
<string>Write your seed phrase here. Make it long and random. Don't ever forget it. If you want it to have any chance at being secure, ask a machine to select 13 dictionary words at random.</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;You can leave a hint here if you want; don't rely on it or there's little point in it being a &lt;span style=&quot; font-style:italic;&quot;&gt;brain&lt;/span&gt; wallet.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="hint">
<property name="placeholderText">
<string>An optional hint for the text above.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="generate">
<property name="text">
<string>&amp;Generate</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="create">
<property name="text">
<string>&amp;Create</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>create</sender>
<signal>clicked()</signal>
<receiver>BrainWallet</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>462</x>
<y>484</y>
</hint>
<hint type="destinationlabel">
<x>449</x>
<y>504</y>
</hint>
</hints>
</connection>
<connection>
<sender>cancel</sender>
<signal>clicked()</signal>
<receiver>BrainWallet</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>381</x>
<y>483</y>
</hint>
<hint type="destinationlabel">
<x>351</x>
<y>506</y>
</hint>
</hints>
</connection>
</connections>
</ui>

22
alethzero/CMakeLists.txt

@ -20,8 +20,14 @@ include_directories(BEFORE ..)
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
find_package (Qt5WebEngine QUIET)
find_package (Qt5WebEngineWidgets QUIET)
find_package (Qt5WebEngine)
find_package (Qt5WebEngineWidgets)
if (APPLE)
# TODO: remove indirect dependencies once macdeployqt is fixed
find_package (Qt5WebEngineCore)
find_package (Qt5DBus)
find_package (Qt5PrintSupport)
endif()
qt5_wrap_ui(ui_Main.h Main.ui)
qt5_wrap_ui(ui_Connect.h Connect.ui)
@ -31,6 +37,11 @@ qt5_wrap_ui(ui_ExportState.h ExportState.ui)
qt5_wrap_ui(ui_GetPassword.h GetPassword.ui)
qt5_wrap_ui(ui_GasPricing.h GasPricing.ui)
# Extensions
qt5_wrap_ui(ui_AllAccounts.h AllAccounts.ui)
qt5_wrap_ui(ui_LogPanel.h LogPanel.ui)
qt5_wrap_ui(ui_BrainWallet.h BrainWallet.ui)
file(GLOB HEADERS "*.h")
if (APPLE)
@ -42,7 +53,7 @@ endif ()
# eth_add_executable is defined in cmake/EthExecutableHelper.cmake
eth_add_executable(${EXECUTABLE}
ICON alethzero
UI_RESOURCES alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui
UI_RESOURCES alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui AllAccounts.ui LogPanel.ui BrainWallet.ui
WIN_RESOURCES alethzero.rc
)
@ -52,6 +63,11 @@ target_link_libraries(${EXECUTABLE} Qt5::Core)
target_link_libraries(${EXECUTABLE} Qt5::Widgets)
target_link_libraries(${EXECUTABLE} Qt5::WebEngine)
target_link_libraries(${EXECUTABLE} Qt5::WebEngineWidgets)
if (APPLE)
target_link_libraries(${EXECUTABLE} Qt5::WebEngineCore)
target_link_libraries(${EXECUTABLE} Qt5::DBus)
target_link_libraries(${EXECUTABLE} Qt5::PrintSupport)
endif()
target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} ethereum)
target_link_libraries(${EXECUTABLE} evm)

3
alethzero/Connect.cpp

@ -20,9 +20,10 @@
*/
#include "Connect.h"
#include <libp2p/Host.h>
#include "ui_Connect.h"
using namespace dev;
using namespace az;
Connect::Connect(QWidget *parent) :
QDialog(parent),

14
alethzero/Connect.h

@ -25,9 +25,16 @@
#include <QList>
namespace Ui { class Connect; }
namespace dev { namespace p2p { class Host; } }
class Connect : public QDialog
namespace dev
{
namespace p2p { class Host; }
namespace az
{
class Connect: public QDialog
{
Q_OBJECT
@ -53,3 +60,6 @@ public:
private:
Ui::Connect* ui;
};
}
}

15
alethzero/Context.cpp

@ -25,7 +25,8 @@
#include <libethcore/Common.h>
using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace eth;
using namespace az;
NatSpecFace::~NatSpecFace()
{
@ -35,7 +36,7 @@ Context::~Context()
{
}
void setValueUnits(QComboBox* _units, QSpinBox* _value, u256 _v)
void dev::az::setValueUnits(QComboBox* _units, QSpinBox* _value, u256 _v)
{
initUnits(_units);
_units->setCurrentIndex(0);
@ -47,30 +48,30 @@ void setValueUnits(QComboBox* _units, QSpinBox* _value, u256 _v)
_value->setValue((unsigned)_v);
}
u256 fromValueUnits(QComboBox* _units, QSpinBox* _value)
u256 dev::az::fromValueUnits(QComboBox* _units, QSpinBox* _value)
{
return _value->value() * units()[units().size() - 1 - _units->currentIndex()].first;
}
void initUnits(QComboBox* _b)
void dev::az::initUnits(QComboBox* _b)
{
for (auto n = (unsigned)units().size(); n-- != 0; )
_b->addItem(QString::fromStdString(units()[n].second), n);
}
vector<KeyPair> keysAsVector(QList<KeyPair> const& keys)
vector<KeyPair> dev::az::keysAsVector(QList<KeyPair> const& keys)
{
auto list = keys.toStdList();
return {begin(list), end(list)};
}
bool sourceIsSolidity(string const& _source)
bool dev::az::sourceIsSolidity(string const& _source)
{
// TODO: Improve this heuristic
return (_source.substr(0, 8) == "contract" || _source.substr(0, 5) == "//sol");
}
bool sourceIsSerpent(string const& _source)
bool dev::az::sourceIsSerpent(string const& _source)
{
// TODO: Improve this heuristic
return (_source.substr(0, 5) == "//ser");

11
alethzero/Context.h

@ -30,7 +30,13 @@
class QComboBox;
class QSpinBox;
namespace dev { namespace eth { struct StateDiff; class KeyManager; } }
namespace dev
{
namespace eth { struct StateDiff; class KeyManager; }
namespace az
{
#define ETH_HTML_SMALL "font-size: small; "
#define ETH_HTML_MONO "font-family: Ubuntu Mono, Monospace, Lucida Console, Courier New; font-weight: bold; "
@ -69,7 +75,10 @@ public:
virtual std::string render(dev::Address const& _a) const = 0;
virtual dev::Secret retrieveSecret(dev::Address const& _a) const = 0;
virtual dev::eth::KeyManager& keyManager() = 0;
virtual void noteKeysChanged() = 0;
virtual dev::u256 gasPrice() const = 0;
};
}
}

2
alethzero/DappHost.cpp

@ -24,8 +24,8 @@
#include <microhttpd.h>
#include <boost/algorithm/string.hpp>
#include <libdevcore/Common.h>
using namespace dev;
using namespace az;
DappHost::DappHost(int _port, int _threads):
m_port(_port),

8
alethzero/DappHost.h

@ -29,6 +29,12 @@
struct MHD_Daemon;
struct MHD_Connection;
namespace dev
{
namespace az
{
/// DApp web server. Servers web content, resolves paths by hashes
class DappHost
{
@ -60,3 +66,5 @@ private:
std::map<QString, ManifestEntry const*> m_entriesByPath;
};
}
}

13
alethzero/DappLoader.cpp

@ -34,12 +34,12 @@
#include <libethereum/Client.h>
#include <libwebthree/WebThree.h>
#include "DappLoader.h"
using namespace dev;
using namespace dev::eth;
using namespace dev::crypto;
using namespace az;
using namespace eth;
using namespace crypto;
QString contentsOfQResource(std::string const& res);
namespace dev { namespace az { QString contentsOfQResource(std::string const& res); } }
DappLoader::DappLoader(QObject* _parent, WebThreeDirect* _web3, Address _nameReg):
QObject(_parent), m_web3(_web3), m_nameReg(_nameReg)
@ -130,14 +130,14 @@ void DappLoader::downloadComplete(QNetworkReply* _reply)
h256 expected = m_uriHashes[requestUrl];
bytes package(reinterpret_cast<unsigned char const*>(data.constData()), reinterpret_cast<unsigned char const*>(data.constData() + data.size()));
Secp256k1PP dec;
dec.decrypt(expected, package);
dec.decrypt(Secret(expected), package);
h256 got = sha3(package);
if (got != expected)
{
//try base64
data = QByteArray::fromBase64(data);
package = bytes(reinterpret_cast<unsigned char const*>(data.constData()), reinterpret_cast<unsigned char const*>(data.constData() + data.size()));
dec.decrypt(expected, package);
dec.decrypt(Secret(expected), package);
got = sha3(package);
if (got != expected)
throw dev::Exception() << errinfo_comment("Dapp content hash does not match");
@ -145,6 +145,7 @@ void DappLoader::downloadComplete(QNetworkReply* _reply)
RLP rlp(package);
loadDapp(rlp);
bytesRef(&package).cleanse(); // TODO: replace with bytesSec once the crypto API is up to it.
}
catch (...)
{

11
alethzero/DappLoader.h

@ -33,9 +33,12 @@
namespace dev
{
class WebThreeDirect;
class RLP;
}
class WebThreeDirect;
class RLP;
namespace az
{
struct ManifestEntry
{
@ -104,3 +107,5 @@ private:
std::string m_sessionKey;
};
}
}

3
alethzero/Debugger.cpp

@ -29,7 +29,8 @@
#include "ui_Debugger.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace az;
using namespace eth;
Debugger::Debugger(Context* _c, QWidget* _parent):
QDialog(_parent),

9
alethzero/Debugger.h

@ -32,6 +32,12 @@
namespace Ui { class Debugger; }
namespace dev
{
namespace az
{
struct WorldState
{
uint64_t steps;
@ -101,3 +107,6 @@ private:
DebugSession m_session;
Context* m_context;
};
}
}

8
alethzero/DownloadView.cpp

@ -20,15 +20,14 @@
*/
#include "DownloadView.h"
#include <QtWidgets>
#include <QtCore>
#include <libethereum/DownloadMan.h>
#include "Grapher.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace az;
using namespace eth;
SyncView::SyncView(QWidget* _p): QWidget(_p)
{
@ -176,9 +175,6 @@ void SyncView::paintEvent(QPaintEvent*)
progress2 = hProgress2;
label = hLabel;
}
else if (rect().height() / rect().width() > 5)
{
}
else
{
progress = pieProgress;

13
alethzero/DownloadView.h

@ -31,9 +31,13 @@
#include <libethereum/Client.h>
#endif
namespace dev { namespace eth {
class Client;
}}
namespace dev
{
namespace eth { class Client; }
namespace az
{
class SyncView: public QWidget
{
@ -54,3 +58,6 @@ private:
unsigned m_lastSyncCount = 0;
bool m_wasEstimate = false;
};
}
}

6
alethzero/ExportState.cpp

@ -25,10 +25,10 @@
#include <libethereum/Client.h>
#include "MainWin.h"
#include "ui_ExportState.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace az;
using namespace eth;
ExportStateDialog::ExportStateDialog(Main* _parent):
QDialog(_parent),
@ -46,7 +46,7 @@ ExportStateDialog::~ExportStateDialog()
{
}
dev::eth::Client* ExportStateDialog::ethereum() const
Client* ExportStateDialog::ethereum() const
{
return m_main->ethereum();
}

16
alethzero/ExportState.h

@ -26,7 +26,14 @@
#include <libethcore/Common.h>
namespace Ui { class ExportState; }
namespace dev { namespace eth { class Client; } }
namespace dev
{
namespace eth { class Client; }
namespace az
{
class Main;
@ -44,7 +51,7 @@ private slots:
void on_saveButton_clicked();
private:
dev::eth::Client* ethereum() const;
eth::Client* ethereum() const;
void fillBlocks();
void fillContracts();
void generateJSON();
@ -53,5 +60,8 @@ private:
std::unique_ptr<Ui::ExportState> ui;
Main* m_main;
int m_recentBlocks = 0;
dev::eth::BlockNumber m_block = dev::eth::LatestBlock;
eth::BlockNumber m_block = eth::LatestBlock;
};
}
}

96
alethzero/LogPanel.cpp

@ -0,0 +1,96 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file LogPanel.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "LogPanel.h"
#include <sstream>
#include <QClipboard>
#include <QSettings>
#include <libdevcore/Log.h>
#include <libdevcore/SHA3.h>
#include <libevmcore/Instruction.h>
#include <libethereum/Client.h>
#include "ui_LogPanel.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
static QString filterOutTerminal(QString _s)
{
return _s.replace(QRegExp("\x1b\\[(\\d;)?\\d+m"), "");
}
LogPanel::LogPanel(MainFace* _m):
Plugin(_m, "LogPanel"),
m_ui(new Ui::LogPanel)
{
dock(Qt::RightDockWidgetArea, "Log")->setWidget(new QWidget);
m_ui->setupUi(dock()->widget());
connect(m_ui->verbosity, SIGNAL(valueChanged(int)), SLOT(on_verbosity_valueChanged()));
g_logPost = [=](string const& s, char const* c)
{
simpleDebugOut(s, c);
m_logLock.lock();
m_logHistory.append(filterOutTerminal(QString::fromStdString(s)) + "\n");
m_logChanged = true;
m_logLock.unlock();
};
startTimer(100);
on_verbosity_valueChanged();
}
LogPanel::~LogPanel()
{
// Must do this here since otherwise m_ethereum'll be deleted (and therefore clearWatches() called by the destructor)
// *after* the client is dead.
g_logPost = simpleDebugOut;
}
void LogPanel::readSettings(QSettings const& _s)
{
m_ui->verbosity->setValue(_s.value("verbosity", 1).toInt());
}
void LogPanel::writeSettings(QSettings& _s)
{
_s.setValue("verbosity", m_ui->verbosity->value());
}
void LogPanel::timerEvent(QTimerEvent*)
{
if (m_logChanged)
{
m_logLock.lock();
m_logChanged = false;
m_ui->log->appendPlainText(m_logHistory.mid(0, m_logHistory.length() - 1));
m_logHistory.clear();
m_logLock.unlock();
}
}
void LogPanel::on_verbosity_valueChanged()
{
g_logVerbosity = m_ui->verbosity->value();
m_ui->verbosityLabel->setText(QString::number(g_logVerbosity));
}

64
alethzero/LogPanel.h

@ -0,0 +1,64 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file LogPanel.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <QMutex>
#include <QString>
#include <QPair>
#include <QList>
#include "MainFace.h"
namespace Ui
{
class LogPanel;
}
namespace dev
{
namespace az
{
class LogPanel: public QObject, public Plugin
{
Q_OBJECT
public:
LogPanel(MainFace* _m);
~LogPanel();
private slots:
void on_verbosity_valueChanged();
private:
void timerEvent(QTimerEvent*) override;
void readSettings(QSettings const&) override;
void writeSettings(QSettings&) override;
Ui::LogPanel* m_ui;
QMutex m_logLock;
QString m_logHistory;
bool m_logChanged = true;
};
}
}

99
alethzero/LogPanel.ui

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LogPanel</class>
<widget class="QWidget" name="LogPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>834</width>
<height>265</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPlainTextEdit" name="log">
<property name="font">
<font>
<family>Ubuntu Mono</family>
</font>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="lineWrapMode">
<enum>QPlainTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="spacing">
<number>6</number>
</property>
<item>
<widget class="QSlider" name="verbosity">
<property name="maximum">
<number>20</number>
</property>
<property name="value">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBothSides</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="verbosityLabel">
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>20</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

392
alethzero/Main.ui

@ -135,13 +135,13 @@
<height>24</height>
</rect>
</property>
<widget class="QMenu" name="menu_File">
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="quit"/>
</widget>
<widget class="QMenu" name="menu_Network">
<widget class="QMenu" name="menuNetwork">
<property name="title">
<string>&amp;Network</string>
</property>
@ -153,7 +153,7 @@
<addaction name="connect"/>
<addaction name="hermitMode"/>
</widget>
<widget class="QMenu" name="menu_Tools">
<widget class="QMenu" name="menuTools">
<property name="title">
<string>&amp;Tools</string>
</property>
@ -175,13 +175,13 @@
<addaction name="separator"/>
<addaction name="exportState"/>
</widget>
<widget class="QMenu" name="menu_Help">
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>&amp;Help</string>
</property>
<addaction name="about"/>
</widget>
<widget class="QMenu" name="menu_Debug">
<widget class="QMenu" name="menuSpecial">
<property name="title">
<string>&amp;Special</string>
</property>
@ -202,7 +202,7 @@
<addaction name="confirm"/>
<addaction name="rewindChain"/>
</widget>
<widget class="QMenu" name="menu_View">
<widget class="QMenu" name="menuView">
<property name="title">
<string>&amp;View</string>
</property>
@ -223,23 +223,24 @@
<addaction name="debugCurrent"/>
<addaction name="debugDumpState"/>
<addaction name="debugDumpStatePre"/>
<addaction name="dumpBlockState"/>
</widget>
<widget class="QMenu" name="menu_Config">
<widget class="QMenu" name="menuConfig">
<property name="title">
<string>&amp;Config</string>
</property>
<addaction name="gasPrices"/>
<addaction name="sentinel"/>
</widget>
<addaction name="menu_File"/>
<addaction name="menu_View"/>
<addaction name="menu_Network"/>
<addaction name="menu_Tools"/>
<addaction name="menuFile"/>
<addaction name="menuView"/>
<addaction name="menuNetwork"/>
<addaction name="menuTools"/>
<addaction name="menuWhispe"/>
<addaction name="menuDebug"/>
<addaction name="menu_Config"/>
<addaction name="menu_Help"/>
<addaction name="menu_Debug"/>
<addaction name="menuConfig"/>
<addaction name="menuHelp"/>
<addaction name="menuSpecial"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QDockWidget" name="dockWidget_3">
@ -382,96 +383,6 @@
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_4">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Log</string>
</property>
<attribute name="dockWidgetArea">
<number>8</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_4">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPlainTextEdit" name="log">
<property name="font">
<font>
<family>Ubuntu Mono</family>
</font>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="lineWrapMode">
<enum>QPlainTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QSlider" name="verbosity">
<property name="maximum">
<number>20</number>
</property>
<property name="value">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBothSides</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="verbosityLabel">
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>20</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
@ -587,128 +498,6 @@
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_accounts">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Accounts</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_6">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLineEdit" name="accountsFilter">
<property name="placeholderText">
<string>Filter...</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showBasic">
<property name="text">
<string>Basic</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showContracts">
<property name="text">
<string>Contracts</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="onlyNamed">
<property name="text">
<string>Only Named</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="refreshAccounts">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QSplitter" name="splitter_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QListWidget" name="accounts">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QPlainTextEdit" name="accountInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="blockChainDockWidget">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
@ -852,7 +641,7 @@
<number>0</number>
</property>
<item>
<widget class="MiningView" name="miningView" native="true"/>
<widget class="dev::az::MiningView" name="miningView" native="true"/>
</item>
</layout>
</widget>
@ -1151,7 +940,7 @@ font-size: 14pt</string>
<number>0</number>
</property>
<item>
<widget class="SyncView" name="downloadView" native="true"/>
<widget class="dev::az::SyncView" name="downloadView" native="true"/>
</item>
</layout>
</widget>
@ -1202,40 +991,37 @@ font-size: 14pt</string>
</attribute>
<widget class="QWidget" name="dockWidgetContents_14">
<layout class="QGridLayout" name="gridLayout_4">
<item row="2" column="4">
<widget class="QSpinBox" name="shhWork">
<property name="suffix">
<string> ms</string>
</property>
<property name="minimum">
<number>1</number>
<item row="4" column="0" rowspan="2">
<widget class="QLabel" name="label_8">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>1000</number>
<property name="text">
<string>Data</string>
</property>
<property name="value">
<number>50</number>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_9">
<item row="2" column="2" colspan="2">
<widget class="QLabel" name="label5_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Topic</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
<string>Work to Prove</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="4">
<widget class="QPlainTextEdit" name="shhTopic">
<item row="5" column="1" colspan="4">
<widget class="QPlainTextEdit" name="shhData">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
@ -1250,8 +1036,8 @@ font-size: 14pt</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="4">
<widget class="QPlainTextEdit" name="shhData">
<item row="3" column="1" colspan="4">
<widget class="QPlainTextEdit" name="shhTopic">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
@ -1266,36 +1052,26 @@ font-size: 14pt</string>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="QPushButton" name="post">
<property name="text">
<string>Post</string>
<item row="1" column="1" colspan="4">
<widget class="QComboBox" name="shhFrom">
<property name="editable">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label5_5">
<item row="3" column="0">
<widget class="QLabel" name="label_9">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TTL</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label5_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<string>Topic</string>
</property>
<property name="text">
<string>From</string>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
@ -1312,13 +1088,6 @@ font-size: 14pt</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="4">
<widget class="QComboBox" name="shhFrom">
<property name="editable">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1" colspan="4">
<widget class="QComboBox" name="shhTo">
<property name="editable">
@ -1326,22 +1095,6 @@ font-size: 14pt</string>
</property>
</widget>
</item>
<item row="4" column="0" rowspan="2">
<widget class="QLabel" name="label_8">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Data</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="shhTtl">
<property name="suffix">
@ -1355,8 +1108,8 @@ font-size: 14pt</string>
</property>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QLabel" name="label5_6">
<item row="2" column="0">
<widget class="QLabel" name="label5_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@ -1364,7 +1117,43 @@ font-size: 14pt</string>
</sizepolicy>
</property>
<property name="text">
<string>Work to Prove</string>
<string>TTL</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label5_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>From</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QSpinBox" name="shhWork">
<property name="suffix">
<string> ms</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="QPushButton" name="post">
<property name="text">
<string>Post</string>
</property>
</widget>
</item>
@ -1819,17 +1608,22 @@ font-size: 14pt</string>
<string>&amp;Hermit Mode</string>
</property>
</action>
<action name="dumpBlockState">
<property name="text">
<string>Dump &amp;Block State as JSON...</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>MiningView</class>
<class>dev::az::MiningView</class>
<extends>QWidget</extends>
<header>MiningView.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>SyncView</class>
<class>dev::az::SyncView</class>
<extends>QWidget</extends>
<header>DownloadView.h</header>
<container>1</container>
@ -1848,9 +1642,7 @@ font-size: 14pt</string>
<tabstop>shhTopic</tabstop>
<tabstop>shhWork</tabstop>
<tabstop>shhData</tabstop>
<tabstop>log</tabstop>
<tabstop>post</tabstop>
<tabstop>verbosity</tabstop>
<tabstop>tabWidget</tabstop>
<tabstop>urlEdit</tabstop>
<tabstop>listenIP</tabstop>

71
alethzero/MainFace.cpp

@ -0,0 +1,71 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MainFace.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "MainFace.h"
using namespace std;
using namespace dev;
using namespace az;
Plugin::Plugin(MainFace* _f, std::string const& _name):
m_main(_f),
m_name(_name)
{
_f->adoptPlugin(this);
}
QDockWidget* Plugin::dock(Qt::DockWidgetArea _area, QString _title)
{
if (_title.isEmpty())
_title = QString::fromStdString(m_name);
if (!m_dock)
{
m_dock = new QDockWidget(_title, m_main);
m_main->addDockWidget(_area, m_dock);
m_dock->setFeatures(QDockWidget::AllDockWidgetFeatures | QDockWidget::DockWidgetVerticalTitleBar);
}
return m_dock;
}
void Plugin::addToDock(Qt::DockWidgetArea _area, QDockWidget* _dockwidget, Qt::Orientation _orientation)
{
m_main->addDockWidget(_area, _dockwidget, _orientation);
}
void Plugin::addAction(QAction* _a)
{
m_main->addAction(_a);
}
void MainFace::adoptPlugin(Plugin* _p)
{
m_plugins[_p->name()] = shared_ptr<Plugin>(_p);
}
void MainFace::killPlugins()
{
m_plugins.clear();
}
void MainFace::allChange()
{
for (auto const& p: m_plugins)
p.second->onAllChange();
}

118
alethzero/MainFace.h

@ -0,0 +1,118 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MainFace.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <memory>
#include <map>
#include <string>
#include <functional>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QAction>
#include <QtWidgets/QDockWidget>
#include <libevm/ExtVMFace.h>
#include "Context.h"
class QSettings;
namespace dev
{
class WebThreeDirect;
namespace eth { class Client; class LogFilter; }
namespace shh { class WhisperHost; }
namespace az
{
class Plugin;
using WatchHandler = std::function<void(dev::eth::LocalisedLogEntries const&)>;
class AccountNamer
{
public:
virtual std::string toName(Address const&) const { return std::string(); }
virtual Address toAddress(std::string const&) const { return Address(); }
virtual Addresses knownAddresses() const { return Addresses(); }
};
class MainFace: public QMainWindow, public Context
{
public:
explicit MainFace(QWidget* _parent = nullptr): QMainWindow(_parent) {}
void adoptPlugin(Plugin* _p);
void killPlugins();
void allChange();
// TODO: tidy - all should be references that throw if module unavailable.
// TODO: provide a set of available web3 modules.
virtual dev::WebThreeDirect* web3() const = 0;
virtual dev::eth::Client* ethereum() const = 0;
virtual std::shared_ptr<dev::shh::WhisperHost> whisper() const = 0;
virtual unsigned installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f) = 0;
virtual unsigned installWatch(dev::h256 const& _tf, WatchHandler const& _f) = 0;
// Account naming API
virtual void install(AccountNamer* _adopt) = 0;
virtual void uninstall(AccountNamer* _kill) = 0;
virtual void noteAddressesChanged() = 0;
protected:
template <class F> void forEach(F const& _f) { for (auto const& p: m_plugins) _f(p.second); }
std::shared_ptr<Plugin> takePlugin(std::string const& _name) { auto it = m_plugins.find(_name); std::shared_ptr<Plugin> ret; if (it != m_plugins.end()) { ret = it->second; m_plugins.erase(it); } return ret; }
private:
std::unordered_map<std::string, std::shared_ptr<Plugin>> m_plugins;
};
class Plugin
{
public:
Plugin(MainFace* _f, std::string const& _name);
virtual ~Plugin() {}
std::string const& name() const { return m_name; }
dev::WebThreeDirect* web3() const { return m_main->web3(); }
dev::eth::Client* ethereum() const { return m_main->ethereum(); }
std::shared_ptr<dev::shh::WhisperHost> whisper() const { return m_main->whisper(); }
MainFace* main() { return m_main; }
QDockWidget* dock(Qt::DockWidgetArea _area = Qt::RightDockWidgetArea, QString _title = QString());
void addToDock(Qt::DockWidgetArea _area, QDockWidget* _dockwidget, Qt::Orientation _orientation);
void addAction(QAction* _a);
virtual void onAllChange() {}
virtual void readSettings(QSettings const&) {}
virtual void writeSettings(QSettings&) {}
private:
MainFace* m_main = nullptr;
std::string m_name;
QDockWidget* m_dock = nullptr;
};
}
}

416
alethzero/MainWin.cpp

@ -74,41 +74,20 @@
#include "DappHost.h"
#include "WebPage.h"
#include "ExportState.h"
#include "AllAccounts.h"
#include "LogPanel.h"
#include "BrainWallet.h"
#include "ui_Main.h"
#include "ui_GetPassword.h"
#include "ui_GasPricing.h"
using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace dev::eth;
using namespace az;
using namespace p2p;
using namespace eth;
namespace js = json_spirit;
string Main::fromRaw(h256 _n, unsigned* _inc)
{
if (_n)
{
string s((char const*)_n.data(), 32);
auto l = s.find_first_of('\0');
if (!l)
return string();
if (l != string::npos)
{
auto p = s.find_first_not_of('\0', l);
if (!(p == string::npos || (_inc && p == 31)))
return string();
if (_inc)
*_inc = (byte)s[31];
s.resize(l);
}
for (auto i: s)
if (i < 32)
return string();
return s;
}
return string();
}
QString contentsOfQResource(string const& res)
QString dev::az::contentsOfQResource(string const& res)
{
QFile file(QString::fromStdString(res));
if (!file.open(QFile::ReadOnly))
@ -121,13 +100,8 @@ QString contentsOfQResource(string const& res)
Address c_newConfig = Address("c6d9d2cd449a754c494264e1809c50e34d64562b");
//Address c_nameReg = Address("ddd1cea741d548f90d86fb87a3ae6492e18c03a1");
static QString filterOutTerminal(QString _s)
{
return _s.replace(QRegExp("\x1b\\[(\\d;)?\\d+m"), "");
}
Main::Main(QWidget *parent) :
QMainWindow(parent),
Main::Main(QWidget* _parent):
MainFace(_parent),
ui(new Ui::Main),
m_transact(nullptr),
m_dappLoader(nullptr),
@ -136,6 +110,7 @@ Main::Main(QWidget *parent) :
QtWebEngine::initialize();
setWindowFlags(Qt::Window);
ui->setupUi(this);
std::string dbPath = getDataDir();
for (int i = 1; i < qApp->arguments().size(); ++i)
{
@ -146,6 +121,8 @@ Main::Main(QWidget *parent) :
resetNetwork(eth::Network::Olympic);
else if (arg == "--genesis-json" && i + 1 < qApp->arguments().size())
CanonBlockChain<Ethash>::setGenesis(contentsString(qApp->arguments()[++i].toStdString()));
else if ((arg == "--db-path" || arg == "-d") && i + 1 < qApp->arguments().size())
dbPath = qApp->arguments()[++i].toStdString();
}
if (c_network == eth::Network::Olympic)
@ -153,16 +130,6 @@ Main::Main(QWidget *parent) :
else if (c_network == eth::Network::Frontier)
setWindowTitle("AlethZero Frontier");
g_logPost = [=](string const& s, char const* c)
{
simpleDebugOut(s, c);
m_logLock.lock();
m_logHistory.append(filterOutTerminal(QString::fromStdString(s)) + "\n");
m_logChanged = true;
m_logLock.unlock();
// ui->log->addItem(QString::fromStdString(s));
};
// Open Key Store
bool opened = false;
if (m_keyManager.exists())
@ -192,7 +159,7 @@ Main::Main(QWidget *parent) :
QMessageBox::warning(nullptr, "Try again", "You entered two different passwords - please enter the same password twice.", QMessageBox::Ok);
}
m_keyManager.create(password.toStdString());
m_keyManager.import(Secret::random(), "Default identity");
m_keyManager.import(ICAP::createDirect(), "Default identity");
}
#if ETH_DEBUG
@ -200,8 +167,8 @@ Main::Main(QWidget *parent) :
#endif
m_servers.append(QString::fromStdString(Host::pocHost() + ":30303"));
if (!dev::contents(getDataDir() + "/genesis.json").empty())
CanonBlockChain<Ethash>::setGenesis(contentsString(getDataDir() + "/genesis.json"));
if (!dev::contents(dbPath + "/genesis.json").empty())
CanonBlockChain<Ethash>::setGenesis(contentsString(dbPath + "/genesis.json"));
cerr << "State root: " << CanonBlockChain<Ethash>::genesis().stateRoot() << endl;
auto block = CanonBlockChain<Ethash>::createGenesisBlock();
@ -212,7 +179,6 @@ Main::Main(QWidget *parent) :
cerr << "Client database version: " << c_databaseVersion << endl;
ui->configDock->close();
on_verbosity_valueChanged();
statusBar()->addPermanentWidget(ui->cacheUsage);
statusBar()->addPermanentWidget(ui->balance);
@ -226,14 +192,14 @@ Main::Main(QWidget *parent) :
QSettings s("ethereum", "alethzero");
m_networkConfig = s.value("peers").toByteArray();
bytesConstRef network((byte*)m_networkConfig.data(), m_networkConfig.size());
m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir(), WithExisting::Trust, {"eth"/*, "shh"*/}, p2p::NetworkPreferences(), network));
m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), dbPath, WithExisting::Trust, {"eth"/*, "shh"*/}, p2p::NetworkPreferences(), network));
ui->blockCount->setText(QString("PV%1.%2 D%3 %4-%5 v%6").arg(eth::c_protocolVersion).arg(eth::c_minorProtocolVersion).arg(c_databaseVersion).arg(QString::fromStdString(ethereum()->sealEngine()->name())).arg(ethereum()->sealEngine()->revision()).arg(dev::Version));
m_httpConnector.reset(new jsonrpc::HttpServer(SensibleHttpPort, "", "", dev::SensibleHttpThreads));
auto w3ss = new OurWebThreeStubServer(*m_httpConnector, this);
m_server.reset(w3ss);
auto sessionKey = w3ss->newSession(SessionPermissions{{Priviledge::Admin}});
auto sessionKey = w3ss->newSession(SessionPermissions{{Privilege::Admin}});
connect(&*m_server, SIGNAL(onNewId(QString)), SLOT(addNewId(QString)));
m_server->setIdentities(keysAsVector(owned()));
m_server->StartListening();
@ -265,7 +231,7 @@ Main::Main(QWidget *parent) :
ethereum()->setDefault(LatestBlock);
m_vmSelectionGroup = new QActionGroup{ui->menu_Debug};
m_vmSelectionGroup = new QActionGroup{ui->menuDebug};
m_vmSelectionGroup->addAction(ui->vmInterpreter);
m_vmSelectionGroup->addAction(ui->vmJIT);
m_vmSelectionGroup->addAction(ui->vmSmart);
@ -288,9 +254,6 @@ Main::Main(QWidget *parent) :
connect(ui->blockChainDockWidget, &QDockWidget::visibilityChanged, [=]() { refreshBlockChain(); });
#if !ETH_FATDB
removeDockWidget(ui->dockWidget_accounts);
#endif
installWatches();
startTimer(100);
@ -298,19 +261,69 @@ Main::Main(QWidget *parent) :
QSettings s("ethereum", "alethzero");
if (s.value("splashMessage", true).toBool())
{
QMessageBox::information(this, "Here Be Dragons!", "This is proof-of-concept software. The project as a whole is not even at the alpha-testing stage. It is here to show you, if you have a technical bent, the sort of thing that might be possible down the line.\nPlease don't blame us if it does something unexpected or if you're underwhelmed with the user-experience. We have great plans for it in terms of UX down the line but right now we just want to get the groundwork sorted. We welcome contributions, be they in code, testing or documentation!\nAfter you close this message it won't appear again.");
QMessageBox::information(this, "Here Be Dragons!", "This is beta software: it is not yet at the release stage.\nPlease don't blame us if it does something unexpected or if you're underwhelmed with the user-experience. We have great plans for it in terms of UX down the line but right now we just want to make sure everything works roughly as expected. We welcome contributions, be they in code, testing or documentation!\nAfter you close this message it won't appear again.");
s.setValue("splashMessage", false);
}
}
#if ETH_FATDB
loadPlugin<dev::az::AllAccounts>();
#endif
loadPlugin<dev::az::LogPanel>();
loadPlugin<dev::az::BrainWallet>();
}
Main::~Main()
{
m_httpConnector->StopListening();
// save all settings here so we don't have to explicitly finalise plugins.
// NOTE: as soon as plugin finalisation means anything more than saving settings, this will
// need to be rethought into something more like:
// forEach([&](shared_ptr<Plugin> const& p){ finalisePlugin(p.get()); });
writeSettings();
// Must do this here since otherwise m_ethereum'll be deleted (and therefore clearWatches() called by the destructor)
// *after* the client is dead.
g_logPost = simpleDebugOut;
}
string Main::fromRaw(h256 const&_n, unsigned* _inc)
{
if (_n)
{
string s((char const*)_n.data(), 32);
auto l = s.find_first_of('\0');
if (!l)
return string();
if (l != string::npos)
{
auto p = s.find_first_not_of('\0', l);
if (!(p == string::npos || (_inc && p == 31)))
return string();
if (_inc)
*_inc = (byte)s[31];
s.resize(l);
}
for (auto i: s)
if (i < 32)
return string();
return s;
}
return string();
}
void Main::install(AccountNamer* _adopt)
{
m_namers.insert(_adopt);
refreshAll();
}
void Main::uninstall(AccountNamer* _kill)
{
m_namers.erase(_kill);
refreshAll();
}
void Main::noteAddressesChanged()
{
refreshAll();
}
bool Main::confirm() const
@ -360,8 +373,7 @@ void Main::refreshWhisper()
void Main::addNewId(QString _ids)
{
Secret _id = jsToSecret(_ids.toStdString());
KeyPair kp(_id);
KeyPair kp(jsToSecret(_ids.toStdString()));
m_myIdentities.push_back(kp);
m_server->setIdentities(keysAsVector(owned()));
refreshWhisper();
@ -397,7 +409,7 @@ NetworkPreferences Main::netPrefs() const
ret = NetworkPreferences(listenIP, ui->port->value(), ui->upnp->isChecked());
ret.discovery = m_privateChain.isEmpty() && !ui->hermitMode->isChecked();
ret.pin = m_privateChain.isEmpty() || ui->hermitMode->isChecked();
ret.pin = !ret.discovery;
return ret;
}
@ -415,7 +427,7 @@ unsigned Main::installWatch(LogFilter const& _tf, WatchHandler const& _f)
return ret;
}
unsigned Main::installWatch(dev::h256 _tf, WatchHandler const& _f)
unsigned Main::installWatch(h256 const& _tf, WatchHandler const& _f)
{
auto ret = ethereum()->installWatch(_tf, Reaping::Manual);
m_handlers[ret] = _f;
@ -523,7 +535,6 @@ void Main::onNewBlock()
// update blockchain dependent views.
refreshBlockCount();
refreshBlockChain();
ui->refreshAccounts->setEnabled(true);
// We must update balances since we can't filter updates to basic accounts.
refreshBalances();
@ -535,7 +546,6 @@ void Main::onNewPending()
// update any pending-transaction dependent views.
refreshPending();
ui->refreshAccounts->setEnabled(true);
}
void Main::on_forceMining_triggered()
@ -645,6 +655,13 @@ std::string Main::pretty(dev::Address const& _a) const
if (!n.empty())
return n;
}
for (auto i: m_namers)
{
auto n = i->toName(_a);
if (!n.empty())
return n;
}
return string();
}
@ -677,6 +694,11 @@ pair<Address, bytes> Main::fromString(std::string const& _n) const
if (a)
return make_pair(a, bytes());
}
for (auto i: m_namers)
if (auto a = i->toAddress(_n))
return make_pair(a, bytes());
if (n.size() == 40)
{
try
@ -765,6 +787,11 @@ void Main::writeSettings()
s.setValue("identities", b);
}
forEach([&](std::shared_ptr<Plugin> p)
{
p->writeSettings(s);
});
s.setValue("askPrice", QString::fromStdString(toString(static_cast<TrivialGasPricer*>(ethereum()->gasPricer().get())->ask())));
s.setValue("bidPrice", QString::fromStdString(toString(static_cast<TrivialGasPricer*>(ethereum()->gasPricer().get())->bid())));
s.setValue("upnp", ui->upnp->isChecked());
@ -775,14 +802,12 @@ void Main::writeSettings()
s.setValue("paranoia", ui->paranoia->isChecked());
s.setValue("natSpec", ui->natSpec->isChecked());
s.setValue("showAll", ui->showAll->isChecked());
s.setValue("showAllAccounts", ui->showAllAccounts->isChecked());
s.setValue("clientName", ui->clientName->text());
s.setValue("idealPeers", ui->idealPeers->value());
s.setValue("listenIP", ui->listenIP->text());
s.setValue("port", ui->port->value());
s.setValue("url", ui->urlEdit->text());
s.setValue("privateChain", m_privateChain);
s.setValue("verbosity", ui->verbosity->value());
if (auto vm = m_vmSelectionGroup->checkedAction())
s.setValue("vm", vm->text());
@ -846,37 +871,27 @@ void Main::readSettings(bool _skipGeometry)
restoreGeometry(s.value("geometry").toByteArray());
restoreState(s.value("windowState").toByteArray());
{
QByteArray b = s.value("address").toByteArray();
if (!b.isEmpty())
{
h256 k;
for (unsigned i = 0; i < b.size() / sizeof(Secret); ++i)
{
memcpy(&k, b.data() + i * sizeof(Secret), sizeof(Secret));
if (!m_keyManager.hasAccount(KeyPair(k).address()))
m_keyManager.import(k, "Imported (UNSAFE) key.");
}
}
}
{
m_myIdentities.clear();
QByteArray b = s.value("identities").toByteArray();
if (!b.isEmpty())
{
h256 k;
Secret k;
for (unsigned i = 0; i < b.size() / sizeof(Secret); ++i)
{
memcpy(&k, b.data() + i * sizeof(Secret), sizeof(Secret));
memcpy(k.writable().data(), b.data() + i * sizeof(Secret), sizeof(Secret));
if (!count(m_myIdentities.begin(), m_myIdentities.end(), KeyPair(k)))
m_myIdentities.append(KeyPair(k));
}
}
}
static_cast<TrivialGasPricer*>(ethereum()->gasPricer().get())->setAsk(u256(s.value("askPrice", "500000000000").toString().toStdString()));
static_cast<TrivialGasPricer*>(ethereum()->gasPricer().get())->setBid(u256(s.value("bidPrice", "500000000000").toString().toStdString()));
forEach([&](std::shared_ptr<Plugin> p)
{
p->readSettings(s);
});
static_cast<TrivialGasPricer*>(ethereum()->gasPricer().get())->setAsk(u256(s.value("askPrice", QString::fromStdString(toString(c_defaultGasPrice))).toString().toStdString()));
static_cast<TrivialGasPricer*>(ethereum()->gasPricer().get())->setBid(u256(s.value("bidPrice", QString::fromStdString(toString(c_defaultGasPrice))).toString().toStdString()));
ui->upnp->setChecked(s.value("upnp", true).toBool());
ui->forcePublicIP->setText(s.value("forceAddress", "").toString());
@ -889,7 +904,6 @@ void Main::readSettings(bool _skipGeometry)
ui->paranoia->setChecked(s.value("paranoia", false).toBool());
ui->natSpec->setChecked(s.value("natSpec", true).toBool());
ui->showAll->setChecked(s.value("showAll", false).toBool());
ui->showAllAccounts->setChecked(s.value("showAllAccounts", false).toBool());
ui->clientName->setText(s.value("clientName", "").toString());
if (ui->clientName->text().isEmpty())
ui->clientName->setText(QInputDialog::getText(nullptr, "Enter identity", "Enter a name that will identify you on the peer network"));
@ -898,7 +912,6 @@ void Main::readSettings(bool _skipGeometry)
ui->port->setValue(s.value("port", ui->port->value()).toInt());
ui->nameReg->setText(s.value("nameReg", "").toString());
setPrivateChain(s.value("privateChain", "").toString());
ui->verbosity->setValue(s.value("verbosity", 1).toInt());
#if ETH_EVMJIT // We care only if JIT is enabled. Otherwise it can cause misconfiguration.
auto vmName = s.value("vm").toString();
@ -961,7 +974,7 @@ void Main::on_importKey_triggered()
bytes b = fromHex(s.toStdString());
if (b.size() == 32)
{
auto k = KeyPair(h256(b));
auto k = KeyPair(Secret(bytesConstRef(&b)));
if (!m_keyManager.hasAccount(k.address()))
{
QString s = QInputDialog::getText(this, "Import Account Key", "Enter this account's name");
@ -1017,46 +1030,18 @@ void Main::on_claimPresale_triggered()
QString s = QFileDialog::getOpenFileName(this, "Claim Account Contents", QDir::homePath(), "JSON Files (*.json);;All Files (*)");
try
{
js::mValue val;
json_spirit::read_string(asString(dev::contents(s.toStdString())), val);
auto obj = val.get_obj();
if (obj["encseed"].type() == js::str_type)
{
auto encseed = fromHex(obj["encseed"].get_str());
KeyPair k;
for (bool gotit = false; !gotit;)
{
gotit = true;
k = KeyPair::fromEncryptedSeed(&encseed, QInputDialog::getText(this, "Enter Password", "Enter the wallet's passphrase", QLineEdit::Password).toStdString());
if (obj["ethaddr"].type() == js::str_type)
{
Address a(obj["ethaddr"].get_str());
Address b = k.address();
if (a != b)
{
if (QMessageBox::warning(this, "Password Wrong", "Could not import the secret key: the password you gave appears to be wrong.", QMessageBox::Retry, QMessageBox::Cancel) == QMessageBox::Cancel)
return;
else
gotit = false;
}
}
}
cnote << k.address();
if (!m_keyManager.hasAccount(k.address()))
ethereum()->submitTransaction(k.sec(), ethereum()->balanceAt(k.address()) - gasPrice() * c_txGas, m_beneficiary, {}, c_txGas, gasPrice());
else
QMessageBox::warning(this, "Already Have Key", "Could not import the secret key: we already own this account.");
}
KeyPair k = m_keyManager.presaleSecret(dev::contentsString(s.toStdString()), [&](bool){ return QInputDialog::getText(this, "Enter Password", "Enter the wallet's passphrase", QLineEdit::Password).toStdString(); });
cnote << k.address();
if (!m_keyManager.hasAccount(k.address()))
ethereum()->submitTransaction(k.sec(), ethereum()->balanceAt(k.address()) - gasPrice() * c_txGas, m_beneficiary, {}, c_txGas, gasPrice());
else
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("encseed type is not js::str_type") );
QMessageBox::warning(this, "Already Have Key", "Could not import the secret key: we already own this account.");
}
catch (dev::eth::PasswordUnknown&) {}
catch (...)
{
cerr << "Unhandled exception!" << endl <<
boost::current_exception_diagnostic_information();
QMessageBox::warning(this, "Key File Invalid", "Could not find secret key definition. This is probably not an Ethereum key file.");
}
}
@ -1068,7 +1053,7 @@ void Main::on_exportKey_triggered()
auto hba = ui->ourAccounts->currentItem()->data(Qt::UserRole).toByteArray();
Address h((byte const*)hba.data(), Address::ConstructFromPointer);
Secret s = retrieveSecret(h);
QMessageBox::information(this, "Export Account Key", "Secret key to account " + QString::fromStdString(render(h) + " is:\n" + s.hex()));
QMessageBox::information(this, "Export Account Key", "Secret key to account " + QString::fromStdString(render(h) + " is:\n" + s.makeInsecure().hex()));
}
}
@ -1086,7 +1071,10 @@ void Main::on_usePrivate_triggered()
bool ok;
pc = QInputDialog::getText(this, "Enter Name", "Enter the name of your private chain", QLineEdit::Normal, QString("NewChain-%1").arg(time(0)), &ok);
if (!ok)
{
ui->usePrivate->setChecked(false);
return;
}
}
setPrivateChain(pc);
}
@ -1190,7 +1178,7 @@ void Main::setBeneficiary(Address const& _b)
ui->ourAccounts->item(i)->setCheckState(h == _b ? Qt::Checked : Qt::Unchecked);
}
m_beneficiary = _b;
ethereum()->setAddress(_b);
ethereum()->setBeneficiary(_b);
}
void Main::on_ourAccounts_itemClicked(QListWidgetItem* _i)
@ -1220,7 +1208,7 @@ void Main::refreshBalances()
for (auto const& address: m_keyManager.accounts())
{
u256 b = ethereum()->balanceAt(address);
QListWidgetItem* li = new QListWidgetItem(QString("%4 %2: %1 [%3]").arg(formatBalance(b).c_str()).arg(QString::fromStdString(render(address))).arg((unsigned)ethereum()->countAt(address)).arg(QString::fromStdString(m_keyManager.accountName(address))), ui->ourAccounts);
QListWidgetItem* li = new QListWidgetItem(QString("<%5> %4 %2: %1 [%3]").arg(formatBalance(b).c_str()).arg(QString::fromStdString(render(address))).arg((unsigned)ethereum()->countAt(address)).arg(QString::fromStdString(m_keyManager.accountName(address))).arg(m_keyManager.haveKey(address) ? "KEY" : "BRAIN"), ui->ourAccounts);
li->setData(Qt::UserRole, QByteArray((char const*)address.data(), Address::size));
li->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
li->setCheckState(m_beneficiary == address ? Qt::Checked : Qt::Unchecked);
@ -1280,8 +1268,8 @@ void Main::refreshAll()
refreshBlockChain();
refreshBlockCount();
refreshPending();
ui->refreshAccounts->setEnabled(true);
refreshBalances();
allChange();
}
void Main::refreshPending()
@ -1306,57 +1294,6 @@ void Main::refreshPending()
}
}
void Main::on_accountsFilter_textChanged()
{
ui->refreshAccounts->setEnabled(true);
}
void Main::on_showBasic_toggled()
{
ui->refreshAccounts->setEnabled(true);
}
void Main::on_showContracts_toggled()
{
ui->refreshAccounts->setEnabled(true);
}
void Main::on_onlyNamed_toggled()
{
ui->refreshAccounts->setEnabled(true);
}
void Main::on_refreshAccounts_clicked()
{
refreshAccounts();
}
void Main::refreshAccounts()
{
DEV_TIMED_FUNCTION;
#if ETH_FATDB || !ETH_TRUE
cwatch << "refreshAccounts()";
ui->accounts->clear();
bool showContract = ui->showContracts->isChecked();
bool showBasic = ui->showBasic->isChecked();
bool onlyNamed = ui->onlyNamed->isChecked();
auto as = ethereum()->addresses();
sort(as.begin(), as.end());
for (auto const& i: as)
{
bool isContract = (ethereum()->codeHashAt(i) != EmptySHA3);
if (!((showContract && isContract) || (showBasic && !isContract)))
continue;
string r = render(i);
if (onlyNamed && !(r.find('"') != string::npos || r.substr(0, 2) == "XE"))
continue;
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), ui->accounts))
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size));
}
#endif
ui->refreshAccounts->setEnabled(false);
}
void Main::refreshBlockCount()
{
auto d = ethereum()->blockChain().details();
@ -1539,15 +1476,6 @@ void Main::timerEvent(QTimerEvent*)
if ((interval / 100 % 2 == 0 && m_webThree->ethereum()->isSyncing()) || interval == 1000)
ui->downloadView->update();
if (m_logChanged)
{
m_logLock.lock();
m_logChanged = false;
ui->log->appendPlainText(m_logHistory.mid(0, m_logHistory.length() - 1));
m_logHistory.clear();
m_logLock.unlock();
}
// refresh peer list every 1000ms, reset counter
if (interval == 1000)
{
@ -1765,7 +1693,7 @@ void Main::on_blocks_currentItemChanged()
s << "<div>D/TD: <b>" << info.difficulty() << "</b>/<b>" << details.totalDifficulty << "</b> = 2^" << log2((double)info.difficulty()) << "/2^" << log2((double)details.totalDifficulty) << "</div>";
s << "&nbsp;&emsp;&nbsp;Children: <b>" << details.children.size() << "</b></div>";
s << "<div>Gas used/limit: <b>" << info.gasUsed() << "</b>/<b>" << info.gasLimit() << "</b>" << "</div>";
s << "<div>Beneficiary: <b>" << htmlEscaped(pretty(info.coinbaseAddress())) << " " << info.coinbaseAddress() << "</b>" << "</div>";
s << "<div>Beneficiary: <b>" << htmlEscaped(pretty(info.beneficiary())) << " " << info.beneficiary() << "</b>" << "</div>";
s << "<div>Seed hash: <b>" << info.seedHash() << "</b>" << "</div>";
s << "<div>Mix hash: <b>" << info.mixHash() << "</b>" << "</div>";
s << "<div>Nonce: <b>" << info.nonce() << "</b>" << "</div>";
@ -1798,7 +1726,7 @@ void Main::on_blocks_currentItemChanged()
s << line << "Hash: <b>" << uncle.hash() << "</b>" << "</div>";
s << line << "Parent: <b>" << uncle.parentHash() << "</b>" << "</div>";
s << line << "Number: <b>" << uncle.number() << "</b>" << "</div>";
s << line << "Coinbase: <b>" << htmlEscaped(pretty(uncle.coinbaseAddress())) << " " << uncle.coinbaseAddress() << "</b>" << "</div>";
s << line << "Coinbase: <b>" << htmlEscaped(pretty(uncle.beneficiary())) << " " << uncle.beneficiary() << "</b>" << "</div>";
s << line << "Seed hash: <b>" << uncle.seedHash() << "</b>" << "</div>";
s << line << "Mix hash: <b>" << uncle.mixHash() << "</b>" << "</div>";
s << line << "Nonce: <b>" << uncle.nonce() << "</b>" << "</div>";
@ -1888,7 +1816,8 @@ void Main::on_debugCurrent_triggered()
unsigned txi = item->data(Qt::UserRole + 1).toInt();
bytes t = ethereum()->blockChain().transaction(h, txi);
State s(ethereum()->state(txi, h));
Executive e(s, ethereum()->blockChain());
BlockInfo bi(ethereum()->blockChain().info(h));
Executive e(s, ethereum()->blockChain(), EnvInfo(bi));
Debugger dw(this, this);
dw.populate(e, Transaction(t, CheckTransaction::Everything));
dw.exec();
@ -1896,51 +1825,71 @@ void Main::on_debugCurrent_triggered()
}
}
void Main::debugDumpState(int _add)
std::string minHex(h256 const& _h)
{
unsigned i = 0;
for (; i < 31 && !_h[i]; ++i) {}
return toHex(_h.ref().cropped(i));
}
void Main::on_dumpBlockState_triggered()
{
#if ETH_FATDB || !ETH_TRUE
if (auto item = ui->blocks->currentItem())
{
auto hba = item->data(Qt::UserRole).toByteArray();
assert(hba.size() == 32);
auto h = h256((byte const*)hba.data(), h256::ConstructFromPointer);
if (!item->data(Qt::UserRole + 1).isNull())
QString fn = QFileDialog::getSaveFileName(this, "Select file to output state dump");
ofstream f(fn.toStdString());
if (f.is_open())
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output state dump");
ofstream f(fn.toStdString());
if (f.is_open())
f << "{" << endl;
// js::mObject s;
State state = ethereum()->block(h).state();
int fi = 0;
for (pair<Address, u256> const& i: state.addresses())
{
unsigned txi = item->data(Qt::UserRole + 1).toInt();
f << ethereum()->state(txi + _add, h) << endl;
f << (fi++ ? "," : "") << "\"" << i.first.hex() << "\": { ";
f << "\"balance\": \"" << toString(i.second) << "\", ";
if (state.codeHash(i.first) != EmptySHA3)
{
f << "\"codeHash\": \"" << state.codeHash(i.first).hex() << "\", ";
f << "\"storage\": {";
int fj = 0;
for (pair<u256, u256> const& j: state.storage(i.first))
f << (fj++ ? "," : "") << "\"" << minHex(j.first) << "\":\"" << minHex(j.second) << "\"";
f << "}, ";
}
f << "\"nonce\": \"" << toString(state.transactionsFrom(i.first)) << "\"";
f << "}" << endl; // end account
if (!(fi % 100))
f << flush;
}
f << "}";
}
}
#endif
}
void Main::on_accounts_currentItemChanged()
void Main::debugDumpState(int _add)
{
ui->accountInfo->clear();
if (auto item = ui->accounts->currentItem())
if (auto item = ui->blocks->currentItem())
{
auto hba = item->data(Qt::UserRole).toByteArray();
assert(hba.size() == 20);
auto address = h160((byte const*)hba.data(), h160::ConstructFromPointer);
assert(hba.size() == 32);
auto h = h256((byte const*)hba.data(), h256::ConstructFromPointer);
stringstream s;
try
{
auto storage = ethereum()->storageAt(address);
for (auto const& i: storage)
s << "@" << showbase << hex << prettyU256(i.first) << "&nbsp;&nbsp;&nbsp;&nbsp;" << showbase << hex << prettyU256(i.second) << "<br/>";
s << "<h4>Body Code (" << sha3(ethereum()->codeAt(address)).abridged() << ")</h4>" << disassemble(ethereum()->codeAt(address));
s << ETH_HTML_DIV(ETH_HTML_MONO) << toHex(ethereum()->codeAt(address)) << "</div>";
ui->accountInfo->appendHtml(QString::fromStdString(s.str()));
}
catch (dev::InvalidTrie)
if (!item->data(Qt::UserRole + 1).isNull())
{
ui->accountInfo->appendHtml("Corrupted trie.");
QString fn = QFileDialog::getSaveFileName(this, "Select file to output state dump");
ofstream f(fn.toStdString());
if (f.is_open())
{
unsigned txi = item->data(Qt::UserRole + 1).toInt();
f << ethereum()->state(txi + _add, h) << endl;
}
}
ui->accountInfo->moveCursor(QTextCursor::Start);
}
}
@ -1962,16 +1911,6 @@ void Main::on_ourAccounts_doubleClicked()
m_logHistory.clear();
}*/
void Main::on_accounts_doubleClicked()
{
if (ui->accounts->count())
{
auto hba = ui->accounts->currentItem()->data(Qt::UserRole).toByteArray();
auto h = Address((byte const*)hba.data(), Address::ConstructFromPointer);
qApp->clipboard()->setText(QString::fromStdString(toHex(h.asArray())));
}
}
static shh::Topics topicFromText(QString _s)
{
shh::BuildTopic ret;
@ -2106,18 +2045,12 @@ void Main::on_connect_triggered()
}
}
void Main::on_verbosity_valueChanged()
{
g_logVerbosity = ui->verbosity->value();
ui->verbosityLabel->setText(QString::number(g_logVerbosity));
}
void Main::on_mine_triggered()
{
if (ui->mine->isChecked())
{
// EthashAux::computeFull(ethereum()->blockChain().number());
ethereum()->setAddress(m_beneficiary);
ethereum()->setBeneficiary(m_beneficiary);
ethereum()->startMining();
}
else
@ -2382,3 +2315,22 @@ void Main::pageLoaded(QByteArray const& _content, QString const& _mimeType, QUrl
{
ui->webView->page()->setContent(_content, _mimeType, _uri);
}
void Main::initPlugin(Plugin* _p)
{
QSettings s("ethereum", "alethzero");
_p->readSettings(s);
}
void Main::finalisePlugin(Plugin* _p)
{
QSettings s("ethereum", "alethzero");
_p->writeSettings(s);
}
void Main::unloadPlugin(string const& _name)
{
shared_ptr<Plugin> p = takePlugin(_name);
if (p)
finalisePlugin(p.get());
}

99
alethzero/MainWin.h

@ -26,7 +26,6 @@
#endif
#include <map>
#include <QtNetwork/QNetworkAccessManager>
#include <QtCore/QAbstractListModel>
#include <QtCore/QMutex>
@ -42,6 +41,7 @@
#include "Transact.h"
#include "NatspecHandler.h"
#include "Connect.h"
#include "MainFace.h"
class QListWidgetItem;
class QActionGroup;
@ -50,26 +50,32 @@ namespace Ui {
class Main;
}
namespace dev { namespace eth {
class Client;
class State;
}}
namespace jsonrpc {
class HttpServer;
}
class QWebEnginePage;
namespace dev
{
namespace eth
{
class Client;
class State;
}
namespace az
{
class OurWebThreeStubServer;
class DappLoader;
class DappHost;
struct Dapp;
using WatchHandler = std::function<void(dev::eth::LocalisedLogEntries const&)>;
QString contentsOfQResource(std::string const& res);
class Main: public QMainWindow, public Context
class Main: public MainFace
{
Q_OBJECT
@ -77,27 +83,33 @@ public:
explicit Main(QWidget *parent = 0);
~Main();
dev::WebThreeDirect* web3() const { return m_webThree.get(); }
dev::eth::Client* ethereum() const { return m_webThree->ethereum(); }
std::shared_ptr<dev::shh::WhisperHost> whisper() const { return m_webThree->whisper(); }
WebThreeDirect* web3() const override { return m_webThree.get(); }
eth::Client* ethereum() const override { return m_webThree->ethereum(); }
std::shared_ptr<shh::WhisperHost> whisper() const override { return m_webThree->whisper(); }
bool confirm() const;
NatSpecFace* natSpec() { return &m_natSpecDB; }
std::string pretty(dev::Address const& _a) const override;
std::string prettyU256(dev::u256 const& _n) const override;
std::string prettyU256(u256 const& _n) const override;
std::string render(dev::Address const& _a) const override;
std::pair<dev::Address, dev::bytes> fromString(std::string const& _a) const override;
std::string renderDiff(dev::eth::StateDiff const& _d) const override;
std::pair<Address, bytes> fromString(std::string const& _a) const override;
std::string renderDiff(eth::StateDiff const& _d) const override;
QList<dev::KeyPair> owned() const { return m_myIdentities; }
QList<KeyPair> owned() const { return m_myIdentities; }
dev::u256 gasPrice() const override;
u256 gasPrice() const override;
dev::eth::KeyManager& keyManager() override { return m_keyManager; }
eth::KeyManager& keyManager() override { return m_keyManager; }
void noteKeysChanged() override { refreshBalances(); }
bool doConfirm();
dev::Secret retrieveSecret(dev::Address const& _address) const override;
Secret retrieveSecret(Address const& _address) const override;
// Account naming API.
void install(AccountNamer* _adopt) override;
void uninstall(AccountNamer* _kill) override;
void noteAddressesChanged() override;
public slots:
void load(QString _file);
@ -131,7 +143,6 @@ private slots:
// View
void on_refresh_triggered();
void on_showAll_triggered() { refreshBlockChain(); }
void on_showAllAccounts_triggered() { refreshAccounts(); }
void on_preview_triggered();
// Account management
@ -144,13 +155,6 @@ private slots:
void on_claimPresale_triggered();
void on_exportKey_triggered();
// Account pane
void on_accountsFilter_textChanged();
void on_showBasic_toggled();
void on_showContracts_toggled();
void on_onlyNamed_toggled();
void on_refreshAccounts_clicked();
// Tools
void on_newTransaction_triggered();
void on_loadJS_triggered();
@ -159,16 +163,10 @@ private slots:
// Stuff concerning the blocks/transactions/accounts panels
void on_ourAccounts_itemClicked(QListWidgetItem* _i);
void on_ourAccounts_doubleClicked();
void on_accounts_doubleClicked();
void on_accounts_currentItemChanged();
void on_transactionQueue_currentItemChanged();
void on_blockChainFilter_textChanged();
void on_blocks_currentItemChanged();
// Logging
// void on_log_doubleClicked();
void on_verbosity_valueChanged();
// Misc
void on_urlEdit_returnPressed();
void on_jsInput_returnPressed();
@ -193,6 +191,7 @@ private slots:
void on_debugCurrent_triggered();
void on_debugDumpState_triggered() { debugDumpState(1); }
void on_debugDumpStatePre_triggered() { debugDumpState(0); }
void on_dumpBlockState_triggered();
// Whisper
void on_newIdentity_triggered();
@ -214,13 +213,18 @@ signals:
void poll();
private:
template <class P> void loadPlugin() { Plugin* p = new P(this); initPlugin(p); }
void initPlugin(Plugin* _p);
void finalisePlugin(Plugin* _p);
void unloadPlugin(std::string const& _name);
void debugDumpState(int _add);
dev::p2p::NetworkPreferences netPrefs() const;
p2p::NetworkPreferences netPrefs() const;
QString lookup(QString const& _n) const;
dev::Address getNameReg() const;
dev::Address getCurrencies() const;
Address getNameReg() const;
Address getCurrencies() const;
void updateFee();
void readSettings(bool _skipGeometry = false);
@ -228,8 +232,8 @@ private:
void setPrivateChain(QString const& _private, bool _forceConfigure = false);
unsigned installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f);
unsigned installWatch(dev::h256 _tf, WatchHandler const& _f);
unsigned installWatch(eth::LogFilter const& _tf, WatchHandler const& _f) override;
unsigned installWatch(h256 const& _tf, WatchHandler const& _f) override;
void uninstallWatch(unsigned _w);
void keysChanged();
@ -254,16 +258,15 @@ private:
void refreshAll();
void refreshPending();
void refreshAccounts();
void refreshBlockCount();
void refreshBalances();
void setBeneficiary(dev::Address const& _b);
void setBeneficiary(Address const& _b);
std::string getPassword(std::string const& _title, std::string const& _for, std::string* _hint = nullptr, bool* _ok = nullptr);
std::unique_ptr<Ui::Main> ui;
std::unique_ptr<dev::WebThreeDirect> m_webThree;
std::unique_ptr<WebThreeDirect> m_webThree;
std::map<unsigned, WatchHandler> m_handlers;
unsigned m_nameRegFilter = (unsigned)-1;
@ -272,8 +275,8 @@ private:
QByteArray m_networkConfig;
QStringList m_servers;
QList<dev::KeyPair> m_myIdentities;
dev::eth::KeyManager m_keyManager;
QList<KeyPair> m_myIdentities;
eth::KeyManager m_keyManager;
QString m_privateChain;
dev::Address m_nameReg;
dev::Address m_beneficiary;
@ -281,14 +284,11 @@ private:
QActionGroup* m_vmSelectionGroup = nullptr;
QList<QPair<QString, QString>> m_consoleHistory;
QMutex m_logLock;
QString m_logHistory;
bool m_logChanged = true;
std::unique_ptr<jsonrpc::HttpServer> m_httpConnector;
std::unique_ptr<OurWebThreeStubServer> m_server;
static std::string fromRaw(dev::h256 _n, unsigned* _inc = nullptr);
static std::string fromRaw(h256 const& _n, unsigned* _inc = nullptr);
NatspecHandler m_natSpecDB;
Transact* m_transact;
@ -297,4 +297,9 @@ private:
QWebEnginePage* m_webPage;
Connect m_connect;
std::unordered_set<AccountNamer*> m_namers;
};
}
}

7
alethzero/MiningView.cpp

@ -28,17 +28,12 @@
using namespace std;
using namespace lb;
// do *not* use eth since unsigned conflicts with Qt's global unit definition
// using namespace dev;
using namespace dev::az;
using namespace dev::eth;
// types
using dev::eth::MineInfo;
using dev::eth::WorkingProgress;
// functions
using dev::toString;
using dev::trimFront;

15
alethzero/MiningView.h

@ -31,9 +31,16 @@
#include <libethereum/Client.h>
#endif
namespace dev { namespace eth {
namespace dev
{
namespace eth
{
struct MineInfo;
}}
}
namespace az
{
class MiningView: public QWidget
{
@ -59,3 +66,7 @@ private:
double m_lastBest = 1e31;
bool m_haveReset = false;
};
}
}

5
alethzero/NatspecHandler.cpp

@ -30,7 +30,8 @@
#include <libdevcore/SHA3.h>
#include <libethereum/Defaults.h>
using namespace dev;
using namespace dev::eth;
using namespace az;
using namespace eth;
using namespace std;
namespace fs = boost::filesystem;
@ -38,7 +39,7 @@ NatspecHandler::NatspecHandler()
{
string path = Defaults::dbPath();
fs::create_directories(path);
fs::permissions(path, fs::owner_all);
DEV_IGNORE_EXCEPTIONS(fs::permissions(path, fs::owner_all));
ldb::Options o;
o.create_if_missing = true;
ldb::DB::Open(o, path + "/natspec", &m_db);

8
alethzero/NatspecHandler.h

@ -27,6 +27,11 @@
#include <libdevcore/FixedHash.h>
#include "Context.h"
namespace dev
{
namespace az
{
class NatspecHandler: public NatSpecFace
{
public:
@ -52,3 +57,6 @@ class NatspecHandler: public NatSpecFace
ldb::DB* m_db = nullptr;
Json::Reader m_reader;
};
}
}

3
alethzero/OurWebThreeStubServer.cpp

@ -27,7 +27,8 @@
#include "MainWin.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace az;
using namespace eth;
OurWebThreeStubServer::OurWebThreeStubServer(
jsonrpc::AbstractServerConnector& _conn,

31
alethzero/OurWebThreeStubServer.h

@ -27,9 +27,15 @@
#include <libweb3jsonrpc/WebThreeStubServer.h>
#include <libweb3jsonrpc/AccountHolder.h>
namespace dev
{
namespace az
{
class Main;
class OurAccountHolder: public QObject, public dev::eth::AccountHolder
class OurAccountHolder: public QObject, public eth::AccountHolder
{
Q_OBJECT
@ -47,27 +53,24 @@ protected:
private:
bool showAuthenticationPopup(std::string const& _title, std::string const& _text);
bool showCreationNotice(dev::eth::TransactionSkeleton const& _t, bool _toProxy);
bool showSendNotice(dev::eth::TransactionSkeleton const& _t, bool _toProxy);
bool showUnknownCallNotice(dev::eth::TransactionSkeleton const& _t, bool _toProxy);
bool showCreationNotice(eth::TransactionSkeleton const& _t, bool _toProxy);
bool showSendNotice(eth::TransactionSkeleton const& _t, bool _toProxy);
bool showUnknownCallNotice(eth::TransactionSkeleton const& _t, bool _toProxy);
bool validateTransaction(dev::eth::TransactionSkeleton const& _t, bool _toProxy);
bool validateTransaction(eth::TransactionSkeleton const& _t, bool _toProxy);
std::queue<dev::eth::TransactionSkeleton> m_queued;
dev::Mutex x_queued;
std::queue<eth::TransactionSkeleton> m_queued;
Mutex x_queued;
Main* m_main;
};
class OurWebThreeStubServer: public QObject, public dev::WebThreeStubServer
class OurWebThreeStubServer: public QObject, public WebThreeStubServer
{
Q_OBJECT
public:
OurWebThreeStubServer(
jsonrpc::AbstractServerConnector& _conn,
Main* main
);
OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, Main* main);
virtual std::string shh_newIdentity() override;
@ -77,3 +80,7 @@ signals:
private:
Main* m_main;
};
}
}

132
alethzero/Transact.cpp

@ -28,6 +28,7 @@
#include <boost/algorithm/string.hpp>
#include <QFileDialog>
#include <QMessageBox>
#include <QClipboard>
#include <liblll/Compiler.h>
#include <liblll/CodeFragment.h>
#if ETH_SOLIDITY || !ETH_TRUE
@ -40,7 +41,6 @@
#include <libethereum/Client.h>
#include <libethereum/Utility.h>
#include <libethcore/KeyManager.h>
#if ETH_SERPENT
#include <libserpent/funcs.h>
#include <libserpent/util.h>
@ -49,7 +49,8 @@
#include "ui_Transact.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace az;
using namespace eth;
Transact::Transact(Context* _c, QWidget* _parent):
QDialog(_parent),
@ -118,6 +119,11 @@ u256 Transact::gasPrice() const
return ui->gasPrice->value() * units()[units().size() - 1 - ui->gasPriceUnits->currentIndex()].first;
}
Address Transact::to() const
{
return m_context->fromString(ui->destination->currentText().toStdString()).first;
}
u256 Transact::total() const
{
return value() + fee();
@ -133,7 +139,7 @@ void Transact::updateDestination()
if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1)
ui->destination->addItem(s);
for (int i = 0; i < ui->destination->count(); ++i)
if (ui->destination->itemText(i) != "(Create Contract)" && !m_context->fromString(ui->destination->itemText(i).toStdString()).first)
if (ui->destination->itemText(i) != "(Create Contract)" && !to())
ui->destination->removeItem(i--);
}
@ -181,10 +187,26 @@ void Transact::on_destination_currentTextChanged(QString)
else
ui->calculatedName->setText("Create Contract");
rejigData();
// updateFee();
// updateFee();
}
void Transact::on_copyUnsigned_clicked()
{
auto a = fromAccount();
u256 nonce = ui->autoNonce->isChecked() ? ethereum()->countAt(a, PendingBlock) : ui->nonce->value();
Transaction t;
if (isCreation())
// If execution is a contract creation, add Natspec to
// a local Natspec LEVELDB
t = Transaction(value(), gasPrice(), ui->gas->value(), m_data, nonce);
else
// TODO: cache like m_data.
t = Transaction(value(), gasPrice(), ui->gas->value(), to(), m_data, nonce);
qApp->clipboard()->setText(QString::fromStdString(toHex(t.rlp())));
}
static std::string toString(TransactionException _te)
/*static std::string toString(TransactionException _te)
{
switch (_te)
{
@ -201,7 +223,7 @@ static std::string toString(TransactionException _te)
case TransactionException::StackUnderflow: return "VM Error: Stack underflow";
default:; return std::string();
}
}
}*/
#if ETH_SOLIDITY
static string getFunctionHashes(dev::solidity::CompilerStack const& _compiler, string const& _contractName)
@ -301,6 +323,54 @@ string Transact::natspecNotice(Address _to, bytes const& _data)
return "Destination not a contract.";
}
Address Transact::toAccount()
{
return isCreation() ? Address() : m_context->fromString(ui->destination->currentText().toStdString()).first;
}
GasRequirements Transact::determineGasRequirements()
{
// Determine the minimum amount of gas we need to play...
qint64 baseGas = (qint64)Transaction::gasRequired(m_data, 0);
Address from = fromAccount();
Address to = toAccount();
ExecutionResult lastGood;
bool haveUpperBound = false;
qint64 lowerBound = baseGas;
qint64 upperBound = (qint64)ethereum()->gasLimitRemaining();
for (unsigned i = 0; i < 20 && ((haveUpperBound && upperBound - lowerBound > 100) || !haveUpperBound); ++i) // get to with 100.
{
qint64 mid = haveUpperBound ? (lowerBound + upperBound) / 2 : upperBound;
cdebug << "Trying" << mid;
ExecutionResult er;
if (isCreation())
er = ethereum()->create(from, value(), m_data, mid, gasPrice(), ethereum()->getDefault(), FudgeFactor::Lenient);
else
er = ethereum()->call(from, value(), to, m_data, mid, gasPrice(), ethereum()->getDefault(), FudgeFactor::Lenient);
cdebug << toString(er.excepted);
if (er.excepted == TransactionException::OutOfGas || er.excepted == TransactionException::OutOfGasBase || er.excepted == TransactionException::OutOfGasIntrinsic || er.codeDeposit == CodeDeposit::Failed)
{
lowerBound = mid;
if (!haveUpperBound)
upperBound *= 2;
}
else
{
lastGood = er;
if (haveUpperBound)
upperBound = mid;
else
haveUpperBound = true;
}
}
// Dry-run execution to determine gas requirement and any execution errors
// (qint64)(er.gasUsed + er.gasRefunded + c_callStipend);
return GasRequirements{upperBound, baseGas, upperBound - baseGas, (qint64)lastGood.gasRefunded, lastGood};
}
void Transact::rejigData()
{
if (!ethereum())
@ -348,56 +418,44 @@ void Transact::rejigData()
htmlInfo += "<h4>Hex</h4>" + QString(ETH_HTML_DIV(ETH_HTML_MONO)) + QString::fromStdString(toHex(m_data)) + "</div>";
// Determine the minimum amount of gas we need to play...
qint64 baseGas = (qint64)Transaction::gasRequired(m_data, 0);
qint64 gasNeeded = 0;
auto gasReq = determineGasRequirements();
htmlInfo = QString("<div class=\"info\"><span class=\"icon\">INFO</span> Gas required: %1 total = %2 base, %3 exec [%4 refunded later]</div>").arg(gasReq.neededGas).arg(gasReq.baseGas).arg(gasReq.executionGas).arg(gasReq.refundedGas) + htmlInfo;
if (b < value() + baseGas * gasPrice())
if (b < value() + gasReq.baseGas * gasPrice())
{
// Not enough - bail.
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Account doesn't contain enough for paying even the basic amount of gas required.</div>");
return;
}
else
gasNeeded = (qint64)min<bigint>(ethereum()->gasLimitRemaining(), ((b - value()) / max<u256>(gasPrice(), 1)));
// Dry-run execution to determine gas requirement and any execution errors
Address to;
ExecutionResult er;
if (isCreation())
er = ethereum()->create(s, value(), m_data, gasNeeded, gasPrice());
else
if (gasReq.neededGas > m_ethereum->gasLimitRemaining())
{
// TODO: cache like m_data.
to = m_context->fromString(ui->destination->currentText().toStdString()).first;
er = ethereum()->call(s, value(), to, m_data, gasNeeded, gasPrice());
// Not enough - bail.
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Gas remaining in block isn't enough to allow the gas required.</div>");
return;
}
gasNeeded = (qint64)(er.gasUsed + er.gasRefunded + c_callStipend);
htmlInfo = QString("<div class=\"info\"><span class=\"icon\">INFO</span> Gas required: %1 total = %2 base, %3 exec [%4 refunded later]</div>").arg(gasNeeded).arg(baseGas).arg(gasNeeded - baseGas).arg((qint64)er.gasRefunded) + htmlInfo;
if (er.excepted != TransactionException::None)
if (gasReq.er.excepted != TransactionException::None)
{
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> " + QString::fromStdString(toString(er.excepted)) + "</div>");
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> " + QString::fromStdString(toString(gasReq.er.excepted)) + "</div>");
return;
}
if (er.codeDeposit == CodeDeposit::Failed)
if (gasReq.er.codeDeposit == CodeDeposit::Failed)
{
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(er.gasForDeposit)) + " GAS &lt; " + QString::fromStdString(toString(er.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte</div>");
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(gasReq.er.gasForDeposit)) + " GAS &lt; " + QString::fromStdString(toString(gasReq.er.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte</div>");
return;
}
// Add Natspec information
if (!isCreation())
htmlInfo = "<div class=\"info\"><span class=\"icon\">INFO</span> " + QString::fromStdString(natspecNotice(to, m_data)).toHtmlEscaped() + "</div>" + htmlInfo;
htmlInfo = "<div class=\"info\"><span class=\"icon\">INFO</span> " + QString::fromStdString(natspecNotice(toAccount(), m_data)).toHtmlEscaped() + "</div>" + htmlInfo;
// Update gas
if (ui->gas->value() == ui->gas->minimum())
{
ui->gas->setMinimum(gasNeeded);
ui->gas->setValue(gasNeeded);
ui->gas->setMinimum(gasReq.neededGas);
ui->gas->setValue(gasReq.neededGas);
}
else
ui->gas->setMinimum(gasNeeded);
ui->gas->setMinimum(gasReq.neededGas);
updateFee();
@ -500,13 +558,13 @@ void Transact::on_debug_clicked()
try
{
State st(ethereum()->postState());
Block postState(ethereum()->postState());
Transaction t = isCreation() ?
Transaction(value(), gasPrice(), ui->gas->value(), m_data, st.transactionsFrom(from)) :
Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText().toStdString()).first, m_data, st.transactionsFrom(from));
Transaction(value(), gasPrice(), ui->gas->value(), m_data, postState.transactionsFrom(from)) :
Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText().toStdString()).first, m_data, postState.transactionsFrom(from));
t.forceSender(from);
Debugger dw(m_context, this);
Executive e(st, ethereum()->blockChain(), 0);
Executive e(postState, ethereum()->blockChain(), 0);
dw.populate(e, t);
dw.exec();
}

28
alethzero/Transact.h

@ -30,8 +30,24 @@
#include "Context.h"
namespace Ui { class Transact; }
namespace dev { namespace eth { class Client; } }
namespace dev { namespace solidity { class CompilerStack; } }
namespace dev
{
namespace eth { class Client; }
namespace solidity { class CompilerStack; }
namespace az
{
struct GasRequirements
{
qint64 neededGas;
qint64 baseGas;
qint64 executionGas;
qint64 refundedGas;
dev::eth::ExecutionResult er;
};
class Transact: public QDialog
{
@ -54,6 +70,7 @@ private slots:
void on_gasPrice_valueChanged(int) { updateFee(); rejigData(); }
void on_data_textChanged() { rejigData(); }
void on_optimize_clicked() { rejigData(); }
void on_copyUnsigned_clicked();
void on_send_clicked();
void on_debug_clicked();
void on_cancel_clicked() { close(); }
@ -64,6 +81,7 @@ private:
void updateNonce();
dev::Address fromAccount();
dev::Address toAccount();
void updateDestination();
void updateFee();
bool isCreation() const;
@ -71,6 +89,8 @@ private:
dev::u256 total() const;
dev::u256 value() const;
dev::u256 gasPrice() const;
dev::Address to() const;
GasRequirements determineGasRequirements();
std::string natspecNotice(dev::Address _to, dev::bytes const& _data);
dev::Secret findSecret(dev::u256 _totalReq) const;
@ -86,3 +106,7 @@ private:
NatSpecFace* m_natSpecDB = nullptr;
bool m_allGood = false;
};
}
}

7
alethzero/Transact.ui

@ -254,6 +254,13 @@
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QPushButton" name="copyUnsigned">
<property name="text">
<string>Copy &amp;Unsigned</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>

4
alethzero/WebPage.cpp

@ -20,8 +20,10 @@
*/
#include "WebPage.h"
using namespace dev;
using namespace az;
void WebPage::javaScriptConsoleMessage(QWebEnginePage::JavaScriptConsoleMessageLevel _level, const QString& _message, int _lineNumber, const QString& _sourceID)
void WebPage::javaScriptConsoleMessage(QWebEnginePage::JavaScriptConsoleMessageLevel _level, QString const& _message, int _lineNumber, QString const& _sourceID)
{
QString prefix = _level == QWebEnginePage::ErrorMessageLevel ? "error" : _level == QWebEnginePage::WarningMessageLevel ? "warning" : "";
emit consoleMessage(QString("%1(%2:%3):%4").arg(prefix).arg(_sourceID).arg(_lineNumber).arg(_message));

13
alethzero/WebPage.h

@ -27,14 +27,25 @@
#include <QtWebEngineWidgets/QWebEnginePage>
#pragma GCC diagnostic pop
namespace dev
{
namespace az
{
class WebPage: public QWebEnginePage
{
Q_OBJECT
public:
WebPage(QObject* _parent): QWebEnginePage(_parent) { }
WebPage(QObject* _parent): QWebEnginePage(_parent) {}
signals:
void consoleMessage(QString const& _msg);
protected:
void javaScriptConsoleMessage(QWebEnginePage::JavaScriptConsoleMessageLevel _level, const QString& _message, int _lineNumber, const QString& _sourceID) override;
};
}
}

2
alethzero/main.cpp

@ -5,7 +5,7 @@ int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Q_INIT_RESOURCE(js);
Main w;
dev::az::Main w;
w.show();
return a.exec();

2
cmake/EthDependencies.cmake

@ -213,7 +213,7 @@ elseif (UNIX)
endif()
find_package(Boost 1.54.0 REQUIRED COMPONENTS thread date_time system regex chrono filesystem unit_test_framework program_options)
find_package(Boost 1.54.0 REQUIRED COMPONENTS thread date_time system regex chrono filesystem unit_test_framework program_options random)
message(" - boost header: ${Boost_INCLUDE_DIRS}")
message(" - boost lib : ${Boost_LIBRARIES}")

2
cmake/EthExecutableHelper.cmake

@ -95,7 +95,7 @@ macro(eth_install_executable EXECUTABLE)
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
COMMAND ${MACDEPLOYQT_APP} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app -executable=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents/MacOS/${EXECUTABLE} ${eth_qml_dir}
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
COMMAND sh ${CMAKE_SOURCE_DIR}/macdeployfix.sh ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents
COMMAND sh ${CMAKE_SOURCE_DIR}/cmake/scripts/macdeployfix.sh ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents
)
# This tool and next will inspect linked libraries in order to determine which dependencies are required

71
cmake/scripts/macdeployfix.sh

@ -0,0 +1,71 @@
#!/bin/bash
# solves problem with macdeployqt on Qt 5.4 RC and Qt 5.5
# http://qt-project.org/forums/viewthread/50118
BUILD_FOLDER_PATH=$1
BUILD_QML_FOLDER_PATH="$BUILD_FOLDER_PATH/Resources/qml"
BUILD_PLUGINS_FOLDER_PATH="$BUILD_FOLDER_PATH/PlugIns"
if [ -d ${BUILD_QML_FOLDER_PATH} ]; then
declare -a BROKEN_FILES;
k=0;
for j in $(find ${BUILD_QML_FOLDER_PATH} -name *.dylib); do
BROKEN_FILES[${k}]=$j
((k=k+1))
done
for i in "${BROKEN_FILES[@]}"; do
REPLACE_STRING="$BUILD_FOLDER_PATH/"
APP_CONTENT_FILE=${i//$REPLACE_STRING/""}
IFS='/' read -a array <<< "$APP_CONTENT_FILE"
LENGTH=${#array[@]}
LAST_ITEM_INDEX=$((LENGTH-1))
FILE=${array[${LENGTH} - 1]}
ORIGINE_PATH=$(find ${BUILD_PLUGINS_FOLDER_PATH} -name ${FILE})
ORIGINE_PATH=${ORIGINE_PATH//$REPLACE_STRING/""}
s=""
for((l=0;l<${LAST_ITEM_INDEX};l++)) do
s=$s"../"
done
s=$s$ORIGINE_PATH
echo "s: $s"
REMOVE_BROKEN_ALIAS=$(rm -rf $i)
RESULT=$(ln -s $s $i)
done
fi
# replace framework links
declare -a BROKEN_FRAMEWORKS;
k=0;
BUILD_FRAMEWORKS_FOLDER_PATH="$BUILD_FOLDER_PATH/Frameworks"
for j in $(find ${BUILD_FRAMEWORKS_FOLDER_PATH} -name Qt*.framework); do
BROKEN_FRAMEWORKS[${k}]=$j
((k=k+1))
done
for i in "${BROKEN_FRAMEWORKS[@]}"; do
FRAMEWORK_FILE=$i/$(basename -s ".framework" $i)
otool -L $FRAMEWORK_FILE | grep -o /usr/.*Qt.*framework/\\w* | while read -a libs ; do
install_name_tool -change ${libs[0]} @loader_path/../../../`basename ${libs[0]}`.framework/`basename ${libs[0]}` $FRAMEWORK_FILE
done
done
declare -a BROKEN_PLUGINS;
k=0;
BUILD_PLUGINS_FOLDER_PATH="$BUILD_FOLDER_PATH/PlugIns"
for j in $(find ${BUILD_PLUGINS_FOLDER_PATH} -name *.dylib); do
BROKEN_PLUGINS[${k}]=$j
((k=k+1))
done
for i in "${BROKEN_PLUGINS[@]}"; do
FRAMEWORK_FILE=$i
otool -L $FRAMEWORK_FILE | grep -o /usr/.*Qt.*framework/\\w* | while read -a libs ; do
install_name_tool -change ${libs[0]} @loader_path/../../Frameworks/`basename ${libs[0]}`.framework/`basename ${libs[0]}` $FRAMEWORK_FILE
done
done

1017
eth/main.cpp

File diff suppressed because it is too large

107
ethkey/KeyAux.h

@ -104,6 +104,7 @@ public:
New,
Import,
ImportWithAddress,
ImportPresale,
Export,
Recode,
Kill,
@ -155,7 +156,7 @@ public:
m_mode = OperationMode::KillBare;
else if (arg == "--create-wallet")
m_mode = OperationMode::CreateWallet;
else if (arg == "--list")
else if (arg == "-l" || arg == "--list")
m_mode = OperationMode::List;
else if ((arg == "-n" || arg == "--new") && i + 1 < argc)
{
@ -168,7 +169,13 @@ public:
m_inputs = strings(1, argv[++i]);
m_name = argv[++i];
}
else if ((arg == "-i" || arg == "--import-with-address") && i + 3 < argc)
else if (arg == "--import-presale" && i + 2 < argc)
{
m_mode = OperationMode::ImportPresale;
m_inputs = strings(1, argv[++i]);
m_name = argv[++i];
}
else if (arg == "--import-with-address" && i + 3 < argc)
{
m_mode = OperationMode::ImportWithAddress;
m_inputs = strings(1, argv[++i]);
@ -192,7 +199,7 @@ public:
{
KeyPair k(Secret::random());
while (m_icap && k.address()[0])
k = KeyPair(sha3(k.secret()));
k = KeyPair(Secret(sha3(k.secret().ref())));
return k;
}
@ -219,21 +226,13 @@ public:
}
else if (m_mode == OperationMode::DecodeTx)
{
string const& i = m_inputs[0];
bytes b = fromHex(i);
bytes b = inputData(m_inputs[0]);
if (b.empty())
{
std::string s = contentsString(i);
b = fromHex(s);
if (b.empty())
b = asBytes(s);
}
if (b.empty())
cerr << "Unknown file or bad hex: " << i << endl;
cerr << "Unknown file or bad hex: '" << m_inputs[0] << "'" << endl;
else
try
{
TransactionBase t(b, CheckTransaction::Everything);
TransactionBase t(b, CheckTransaction::None);
cout << "Transaction " << t.sha3().hex() << endl;
if (t.isCreation())
{
@ -246,7 +245,17 @@ public:
cout << " to: " << t.to().hex() << endl;
cout << " data: " << (t.data().empty() ? "none" : toHex(t.data())) << endl;
}
cout << " from: " << t.from().hex() << endl;
try
{
auto s = t.sender();
if (t.isCreation())
cout << " creates: " << toAddress(s, t.nonce()).hex() << endl;
cout << " from: " << s.hex() << endl;
}
catch (...)
{
cout << " from: <unsigned>" << endl;
}
cout << " value: " << formatBalance(t.value()) << " (" << t.value() << " wei)" << endl;
cout << " nonce: " << t.nonce() << endl;
cout << " gas: " << t.gas() << endl;
@ -306,18 +315,10 @@ public:
for (string const& i: m_inputs)
{
bytes b = fromHex(i);
bool isFile = false;
bool isFile;
bytes b = inputData(i, &isFile);
if (b.empty())
{
isFile = true;
std::string s = contentsString(i);
b = fromHex(s);
if (b.empty())
b = asBytes(s);
}
if (b.empty())
cerr << "Unknown file or bad hex: " << i << endl;
cerr << "Unknown file or bad hex: '" << i << "'" << endl;
else
try
{
@ -326,11 +327,11 @@ public:
cout << t.sha3() << ": ";
if (isFile)
{
writeFile(i + ".signed", t.data());
writeFile(i + ".signed", toHex(t.rlp()));
cout << i + ".signed" << endl;
}
else
cout << toHex(t.data()) << endl;
cout << toHex(t.rlp()) << endl;
}
catch (Exception& ex)
{
@ -352,7 +353,7 @@ public:
if (m_lock.empty())
m_lock = createPassword("Enter a password with which to secure this account: ");
auto k = makeKey();
h128 u = store.importSecret(k.secret().asBytes(), m_lock);
h128 u = store.importSecret(k.secret().ref(), m_lock);
cout << "Created key " << toUUID(u) << endl;
cout << " Address: " << k.address().hex() << endl;
cout << " ICAP: " << ICAP(k.address()).encoded() << endl;
@ -362,12 +363,12 @@ public:
for (string const& input: m_inputs)
{
h128 u;
bytes b;
b = fromHex(input);
bytesSec b;
b.writable() = fromHex(input);
if (b.size() != 32)
{
std::string s = contentsString(input);
b = fromHex(s);
b.writable() = fromHex(s);
if (b.size() != 32)
u = store.importKey(input);
}
@ -386,18 +387,18 @@ public:
if (!contents(i).empty())
{
h128 u = store.readKey(i, false);
bytes s = store.secret(u, [&](){ return getPassword("Enter password for key " + i + ": "); });
bytesSec s = store.secret(u, [&](){ return getPassword("Enter password for key " + i + ": "); });
cout << "Key " << i << ":" << endl;
cout << " UUID: " << toUUID(u) << ":" << endl;
cout << " Address: " << toAddress(Secret(s)).hex() << endl;
cout << " Secret: " << Secret(s).abridged() << endl;
cout << " Secret: " << toHex(s.ref().cropped(0, 8)) << "..." << endl;
}
else if (h128 u = fromUUID(i))
{
bytes s = store.secret(u, [&](){ return getPassword("Enter password for key " + toUUID(u) + ": "); });
bytesSec s = store.secret(u, [&](){ return getPassword("Enter password for key " + toUUID(u) + ": "); });
cout << "Key " << i << ":" << endl;
cout << " Address: " << toAddress(Secret(s)).hex() << endl;
cout << " Secret: " << Secret(s).abridged() << endl;
cout << " Secret: " << toHex(s.ref().cropped(0, 8)) << "..." << endl;
}
else
cerr << "Couldn't inspect " << i << "; not found." << endl;
@ -454,12 +455,12 @@ public:
{
string const& i = m_inputs[0];
h128 u;
bytes b;
b = fromHex(i);
bytesSec b;
b.writable() = fromHex(i);
if (b.size() != 32)
{
std::string s = contentsString(i);
b = fromHex(s);
b.writable() = fromHex(s);
if (b.size() != 32)
u = wallet.store().importKey(i);
}
@ -477,6 +478,13 @@ public:
cout << " UUID: " << toUUID(u) << endl;
break;
}
case OperationMode::ImportPresale:
{
std::string pw;
KeyPair k = wallet.presaleSecret(contentsString(m_inputs[0]), [&](bool){ return (pw = getPassword("Enter the password for the presale key: ")); });
wallet.import(k.secret(), m_name, pw, "Same password as used for presale key");
break;
}
case OperationMode::List:
{
vector<u128> bare;
@ -497,7 +505,7 @@ public:
if (Address a = wallet.address(u))
{
cout << toUUID(u) << " " << a.abridged();
cout << " (Not ICAP) ";
cout << " " << ICAP(a).encoded();
cout << " " << wallet.accountName(a) << endl;
}
for (auto const& u: bare)
@ -521,6 +529,7 @@ public:
<< " --new-bare Generate and output a key without interacting with wallet and dump the JSON." << endl
<< " --import-bare [ <file>|<secret-hex> , ... ] Import keys from given sources." << endl
<< " --recode-bare [ <uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl
<< " --inspect-bare [ <uuid>|<file> , ... ] Output information on given keys." << endl
// << " --export-bare [ <uuid> , ... ] Export given keys." << endl
<< " --kill-bare [ <uuid> , ... ] Delete given keys." << endl
<< "Secret-store configuration:" << endl
@ -530,6 +539,7 @@ public:
<< " -l,--list List all keys available in wallet." << endl
<< " -n,--new <name> Create a new key with given name and add it in the wallet." << endl
<< " -i,--import [<uuid>|<file>|<secret-hex>] <name> Import keys from given source and place in wallet." << endl
<< " --import-presale <file> <name> Import a presale wallet into a key with the given name." << endl
<< " --import-with-address [<uuid>|<file>|<secret-hex>] <address> <name> Import keys from given source with given address and place in wallet." << endl
<< " -e,--export [ <address>|<uuid> , ... ] Export given keys." << endl
<< " -r,--recode [ <address>|<uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl
@ -557,6 +567,23 @@ public:
;
}
static bytes inputData(std::string const& _input, bool* _isFile = nullptr)
{
bytes b = fromHex(_input);
if (_isFile)
*_isFile = false;
if (b.empty())
{
if (_isFile)
*_isFile = true;
std::string s = boost::trim_copy_if(contentsString(_input), is_any_of(" \t\n"));
b = fromHex(s);
if (b.empty())
b = asBytes(s);
}
return b;
}
static bool isTrue(std::string const& _m)
{
return _m == "on" || _m == "yes" || _m == "true" || _m == "1";

1
ethminer/CMakeLists.txt

@ -30,6 +30,7 @@ endif()
target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} ethash)
target_link_libraries(${EXECUTABLE} devcrypto)
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
eth_copy_dlls("${EXECUTABLE}" MHD_DLLS)

3
ethrpctest/CommandLineInterface.cpp

@ -114,7 +114,8 @@ void sighandler(int)
void CommandLineInterface::actOnInput()
{
BlockChainLoader bcl(m_json);
FixedClient client(bcl.bc(), bcl.state());
cerr << "void CommandLineInterface::actOnInput() FixedClient now accepts eth::Block!!!" << endl;
FixedClient client(bcl.bc(), eth::Block{}/*bcl.state()*/);
unique_ptr<FixedWebThreeServer> jsonrpcServer;
auto server = new jsonrpc::HttpServer(8080, "", "", 2);
jsonrpcServer.reset(new FixedWebThreeServer(*server, {}, &client));

20
ethvm/main.cpp

@ -21,11 +21,12 @@
*/
#include <fstream>
#include <iostream>
#include <ctime>
#include <boost/algorithm/string.hpp>
#include <libdevcore/CommonIO.h>
#include <libdevcore/RLP.h>
#include <libdevcore/SHA3.h>
#include <libethereum/State.h>
#include <libethereum/Block.h>
#include <libethereum/Executive.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
@ -83,10 +84,11 @@ int main(int argc, char** argv)
Address sender = Address(69);
Address origin = Address(69);
u256 value = 0;
u256 gas = state.gasLimitRemaining();
u256 gas = Block().gasLimitRemaining();
u256 gasPrice = 0;
bool styledJson = true;
StandardTrace st;
EnvInfo envInfo;
for (int i = 1; i < argc; ++i)
{
@ -130,6 +132,18 @@ int main(int argc, char** argv)
value = u256(argv[++i]);
else if (arg == "--value" && i + 1 < argc)
value = u256(argv[++i]);
else if (arg == "--beneficiary" && i + 1 < argc)
envInfo.setBeneficiary(Address(argv[++i]));
else if (arg == "--number" && i + 1 < argc)
envInfo.setNumber(u256(argv[++i]));
else if (arg == "--difficulty" && i + 1 < argc)
envInfo.setDifficulty(u256(argv[++i]));
else if (arg == "--timestamp" && i + 1 < argc)
envInfo.setTimestamp(u256(argv[++i]));
else if (arg == "--gas-limit" && i + 1 < argc)
envInfo.setGasLimit(u256(argv[++i]));
else if (arg == "--value" && i + 1 < argc)
value = u256(argv[++i]);
else if (arg == "stats")
mode = Mode::Statistics;
else if (arg == "output")
@ -151,7 +165,7 @@ int main(int argc, char** argv)
data = code;
state.addBalance(sender, value);
Executive executive(state, eth::LastHashes(), 0);
Executive executive(state, envInfo);
ExecutionResult res;
executive.setResultRecipient(res);
Transaction t = eth::Transaction(value, gasPrice, gas, data, 0);

20
evmjit/CMakeLists.txt

@ -1,6 +1,7 @@
cmake_minimum_required(VERSION 2.8.12)
if (${CMAKE_VERSION} VERSION_GREATER 3.0)
cmake_policy(SET CMP0042 OLD) # fix MACOSX_RPATH
cmake_policy(SET CMP0048 NEW) # allow VERSION argument in project()
project(EVMJIT VERSION 0.9.0 LANGUAGES CXX)
else()
@ -27,12 +28,25 @@ endif()
# LLVM
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND NOT LLVM_DIR)
# Workaround for Ubuntu broken LLVM package
message(STATUS "Using llvm-3.7-dev package from Ubuntu. If does not work, build LLVM and set -DLLVM_DIR=llvm-build/share/llvm/cmake")
execute_process(COMMAND llvm-config-3.7 --includedir OUTPUT_VARIABLE LLVM_INCLUDE_DIRS OUTPUT_STRIP_TRAILING_WHITESPACE)
find_program(LLVM3_7_CONFIG llvm-config-3.7)
find_program(LLVM3_8_CONFIG llvm-config-3.8)
if (LLVM3_7_CONFIG)
message(STATUS "Using llvm-3.7-dev package from Ubuntu. If does not work, build LLVM and set -DLLVM_DIR=llvm-build/share/llvm/cmake")
set(LLVM_CONFIG_EXEC llvm-config-3.7)
set(LLVM_LIB_DIR /usr/lib/llvm-3.7/lib)
elseif(LLVM3_8_CONFIG)
message(STATUS "Using llvm-3.8-dev package from Ubuntu. If does not work, build LLVM and set -DLLVM_DIR=llvm-build/share/llvm/cmake")
set(LLVM_CONFIG_EXEC llvm-config-3.8)
set(LLVM_LIB_DIR /usr/lib/llvm-3.8/lib)
else()
message(FATAL_ERROR "No LLVM package found!")
endif()
execute_process(COMMAND ${LLVM_CONFIG_EXEC} --includedir OUTPUT_VARIABLE LLVM_INCLUDE_DIRS OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "LLVM include dirs: ${LLVM_INCLUDE_DIRS}")
set(LLVM_LIBS "-lLLVMipo -lLLVMVectorize -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMX86Desc -lLLVMX86Info -lLLVMMCDisassembler -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMCodeGen -lLLVMScalarOpts -lLLVMProfileData -lLLVMInstCombine -lLLVMInstrumentation -lLLVMTransformUtils -lLLVMipa -lLLVMMCJIT -lLLVMExecutionEngine -lLLVMTarget -lLLVMAnalysis -lLLVMRuntimeDyld -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMMC -lLLVMCore -lLLVMSupport -lz -lpthread -lffi -ltinfo -ldl -lm")
set(LLVM_DEFINITIONS "-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
link_directories(/usr/lib/llvm-3.7/lib)
link_directories(${LLVM_LIB_DIR})
else()
find_package(LLVM REQUIRED CONFIG)
if (${LLVM_VERSION} VERSION_LESS 3.7)

14
evmjit/include/evmjit/JIT-c.h

@ -1,6 +1,14 @@
#include "stdint.h"
#ifdef _MSC_VER
#define EXPORT __declspec(dllexport)
#define _ALLOW_KEYWORD_MACROS
#define noexcept throw()
#else
#define EXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -47,11 +55,11 @@ typedef enum evmjit_return_code
typedef struct evmjit_context evmjit_context;
evmjit_context* evmjit_create(evmjit_runtime_data* _data, void* _env);
EXPORT evmjit_context* evmjit_create(evmjit_runtime_data* _data, void* _env);
evmjit_return_code evmjit_exec(evmjit_context* _context);
EXPORT evmjit_return_code evmjit_exec(evmjit_context* _context);
void evmjit_destroy(evmjit_context* _context);
EXPORT void evmjit_destroy(evmjit_context* _context);
inline char const* evmjit_get_output(evmjit_runtime_data* _data) { return _data->callData; }

2
evmjit/libevmjit-cpp/Env.cpp

@ -44,7 +44,7 @@ extern "C"
EXPORT void env_blockhash(ExtVMFace* _env, i256* _number, h256* o_hash)
{
*o_hash = _env->blockhash(jit2eth(*_number));
*o_hash = _env->blockHash(jit2eth(*_number));
}
EXPORT void env_create(ExtVMFace* _env, int64_t* io_gas, i256* _endowment, byte* _initBeg, uint64_t _initSize, h256* o_address)

14
evmjit/libevmjit-cpp/JitVM.cpp

@ -23,8 +23,8 @@ bytesConstRef JitVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _on
// TODO: Rejecting transactions with gas limit > 2^63 can be used by attacker to take JIT out of scope
rejected |= io_gas > std::numeric_limits<decltype(m_data.gas)>::max(); // Do not accept requests with gas > 2^63 (int64 max)
rejected |= _ext.gasPrice > std::numeric_limits<decltype(m_data.gasPrice)>::max();
rejected |= _ext.currentBlock.number() > std::numeric_limits<decltype(m_data.number)>::max();
rejected |= _ext.currentBlock.timestamp() > std::numeric_limits<decltype(m_data.timestamp)>::max();
rejected |= _ext.envInfo().number() > std::numeric_limits<decltype(m_data.number)>::max();
rejected |= _ext.envInfo().timestamp() > std::numeric_limits<decltype(m_data.timestamp)>::max();
if (rejected)
{
@ -41,11 +41,11 @@ bytesConstRef JitVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _on
m_data.caller = eth2jit(fromAddress(_ext.caller));
m_data.origin = eth2jit(fromAddress(_ext.origin));
m_data.callValue = eth2jit(_ext.value);
m_data.coinBase = eth2jit(fromAddress(_ext.currentBlock.coinbaseAddress()));
m_data.difficulty = eth2jit(_ext.currentBlock.difficulty());
m_data.gasLimit = eth2jit(_ext.currentBlock.gasLimit());
m_data.number = static_cast<decltype(m_data.number)>(_ext.currentBlock.number());
m_data.timestamp = static_cast<decltype(m_data.timestamp)>(_ext.currentBlock.timestamp());
m_data.coinBase = eth2jit(fromAddress(_ext.envInfo().beneficiary()));
m_data.difficulty = eth2jit(_ext.envInfo().difficulty());
m_data.gasLimit = eth2jit(_ext.envInfo().gasLimit());
m_data.number = static_cast<decltype(m_data.number)>(_ext.envInfo().number());
m_data.timestamp = static_cast<decltype(m_data.timestamp)>(_ext.envInfo().timestamp());
m_data.code = _ext.code.data();
m_data.codeSize = _ext.code.size();
m_data.codeHash = eth2jit(_ext.codeHash);

2
evmjit/libevmjit/BasicBlock.h

@ -59,7 +59,7 @@ private:
size_t m_globalPops = 0; ///< Number of items poped from global stack. In other words: global - local stack overlap.
ssize_t m_minSize = 0; ///< Minimum reached local stack size. Can be negative.
ssize_t m_maxSize = 0; ///< Maximum reached local stack size.
ssize_t m_maxSize = 0; ///< Maximum reached local stack size.
};
class BasicBlock

2
evmjit/libevmjit/Compiler.cpp

@ -626,7 +626,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti
case Instruction::BLOCKHASH:
{
auto number = stack.pop();
auto hash = _ext.blockhash(number);
auto hash = _ext.blockHash(number);
stack.push(hash);
break;
}

10
evmjit/libevmjit/CompilerHelper.h

@ -49,7 +49,15 @@ private:
RuntimeManager& m_runtimeManager;
};
using InsertPointGuard = llvm::IRBuilderBase::InsertPointGuard;
struct InsertPointGuard
{
explicit InsertPointGuard(llvm::IRBuilderBase& _builder): m_builder(_builder), m_insertPoint(_builder.saveIP()) {}
~InsertPointGuard() { m_builder.restoreIP(m_insertPoint); }
private:
llvm::IRBuilderBase& m_builder;
llvm::IRBuilderBase::InsertPoint m_insertPoint;
};
}
}

2
evmjit/libevmjit/Ext.cpp

@ -131,7 +131,7 @@ llvm::Value* Ext::balance(llvm::Value* _address)
return m_builder.CreateLoad(ret);
}
llvm::Value* Ext::blockhash(llvm::Value* _number)
llvm::Value* Ext::blockHash(llvm::Value* _number)
{
auto hash = getArgAlloca();
createCall(EnvFunc::blockhash, {getRuntimeManager().getEnvPtr(), byPtr(_number), hash});

2
evmjit/libevmjit/Ext.h

@ -51,7 +51,7 @@ public:
llvm::Value* calldataload(llvm::Value* _index);
llvm::Value* create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize);
llvm::Value* call(llvm::Value* _callGas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress);
llvm::Value* blockhash(llvm::Value* _number);
llvm::Value* blockHash(llvm::Value* _number);
llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize);
MemoryRef extcode(llvm::Value* _addr);

6
evmjit/libevmjit/JIT-c.cpp

@ -6,7 +6,7 @@ extern "C"
{
using namespace dev::evmjit;
EXPORT evmjit_context* evmjit_create(evmjit_runtime_data* _data, void* _env)
evmjit_context* evmjit_create(evmjit_runtime_data* _data, void* _env)
{
auto data = reinterpret_cast<RuntimeData*>(_data);
auto env = reinterpret_cast<Env*>(_env);
@ -20,13 +20,13 @@ EXPORT evmjit_context* evmjit_create(evmjit_runtime_data* _data, void* _env)
return reinterpret_cast<evmjit_context*>(context);
}
EXPORT void evmjit_destroy(evmjit_context* _context)
void evmjit_destroy(evmjit_context* _context)
{
auto context = reinterpret_cast<ExecutionContext*>(_context);
delete context;
}
EXPORT evmjit_return_code evmjit_exec(evmjit_context* _context)
evmjit_return_code evmjit_exec(evmjit_context* _context)
{
auto context = reinterpret_cast<ExecutionContext*>(_context);

2
evmjit/libevmjit/preprocessor/llvm_includes_start.h

@ -1,6 +1,6 @@
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4267 4244 4800)
#pragma warning(disable: 4267 4244 4800 4624)
#elif defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"

12
exp/main.cpp

@ -299,7 +299,7 @@ int main()
#elif 0
void mine(State& s, BlockChain const& _bc, SealEngineFace* _se)
{
s.commitToMine(_bc);
s.commitToSeal(_bc);
Notified<bytes> sealed;
_se->onSealGenerated([&](bytes const& sealedHeader){ sealed = sealedHeader; });
_se->generateSeal(s.info());
@ -329,8 +329,8 @@ int main()
OverlayDB stateDB = State::openDB(bc.genesisHash());
cnote << bc;
State s = bc.genesisState(stateDB);
s.setAddress(myMiner.address());
Block s = bc.genesisBlock(stateDB);
s.setBeneficiary(myMiner.address());
cnote << s;
// Sync up - this won't do much until we use the last state.
@ -362,8 +362,8 @@ int main()
cnote << s;
// Mine to get some ether and set in stone.
s.commitToMine(bc);
s.commitToMine(bc);
s.commitToSeal(bc);
s.commitToSeal(bc);
mine(s, bc, se);
bc.attemptImport(s.blockData(), stateDB);
@ -386,7 +386,7 @@ int main()
cdebug << "Path:" << tempDir;
Client c(&net, tempDir);
c.setAddress(myMiner.address());
c.setBeneficiary(myMiner.address());
this_thread::sleep_for(chrono::milliseconds(1000));

8
extdep/getstuff.bat

@ -27,13 +27,13 @@ set eth_version=%2
cd download
if not exist %eth_name%-%eth_version%.tar.gz (
for /f "tokens=2 delims={}" %%g in ('bitsadmin /create %eth_name%-%eth_version%.tar.gz') do (
bitsadmin /transfer {%%g} /download /priority normal %eth_server%/%eth_name%-%eth_version%.tar.gz %cd%\%eth_name%-%eth_version%.tar.gz
if not exist %eth_name%-%eth_version%-x64.tar.gz (
for /f "tokens=2 delims={}" %%g in ('bitsadmin /create %eth_name%-%eth_version%-x64.tar.gz') do (
bitsadmin /transfer {%%g} /download /priority normal %eth_server%/%eth_name%-%eth_version%-x64.tar.gz %cd%\%eth_name%-%eth_version%-x64.tar.gz
bitsadmin /cancel {%%g}
)
)
if not exist %eth_name%-%eth_version% cmake -E tar -zxvf %eth_name%-%eth_version%.tar.gz
if not exist %eth_name%-%eth_version% cmake -E tar -zxvf %eth_name%-%eth_version%-x64.tar.gz
cmake -E copy_directory %eth_name%-%eth_version% ..\install\windows
cd ..

5
libdevcore/Base64.h

@ -44,7 +44,10 @@ template <size_t N> inline std::string toBase36(FixedHash<N> const& _h)
typename FixedHash<N>::Arith a = _h;
std::string ret;
for (; a > 0; a /= 36)
ret = c_alphabet[(unsigned)a % 36] + ret;
{
unsigned r = (unsigned)(a - a / 36 * 36); // boost's % is broken
ret = c_alphabet[r] + ret;
}
return ret;
}

10
libdevcore/CMakeLists.txt

@ -1,11 +1,4 @@
cmake_policy(SET CMP0015 NEW)
# this policy was introduced in cmake 3.0
# remove if, once 3.0 will be used on unix
if (${CMAKE_MAJOR_VERSION} GREATER 2)
# old policy do not use MACOSX_RPATH
cmake_policy(SET CMP0042 OLD)
endif()
set(CMAKE_AUTOMOC OFF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB")
@ -24,8 +17,9 @@ file(GLOB HEADERS "*.h")
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_RANDOM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${DB_LIBRARIES})

4
libdevcore/Common.cpp

@ -22,13 +22,14 @@
#include "Common.h"
#include "Exceptions.h"
#include "Log.h"
#include "BuildInfo.h"
using namespace std;
using namespace dev;
namespace dev
{
char const* Version = "0.9.34";
char const* Version = ETH_PROJECT_VERSION;
const u256 UndefinedU256 = ~(u256)0;
@ -57,4 +58,3 @@ TimerHelper::~TimerHelper()
}
}

41
libdevcore/Common.h

@ -79,6 +79,47 @@ using bytes = std::vector<byte>;
using bytesRef = vector_ref<byte>;
using bytesConstRef = vector_ref<byte const>;
template <class T>
class secure_vector
{
public:
secure_vector() {}
secure_vector(secure_vector<T> const& _c) = default;
explicit secure_vector(unsigned _size): m_data(_size) {}
explicit secure_vector(unsigned _size, T _item): m_data(_size, _item) {}
explicit secure_vector(std::vector<T> const& _c): m_data(_c) {}
explicit secure_vector(vector_ref<T> _c): m_data(_c.data(), _c.data() + _c.size()) {}
explicit secure_vector(vector_ref<const T> _c): m_data(_c.data(), _c.data() + _c.size()) {}
~secure_vector() { ref().cleanse(); }
secure_vector<T>& operator=(secure_vector<T> const& _c)
{
if (&_c == this)
return *this;
ref().cleanse();
m_data = _c.m_data;
return *this;
}
std::vector<T>& writable() { clear(); return m_data; }
std::vector<T> const& makeInsecure() const { return m_data; }
void clear() { ref().cleanse(); }
vector_ref<T> ref() { return vector_ref<T>(&m_data); }
vector_ref<T const> ref() const { return vector_ref<T const>(&m_data); }
size_t size() const { return m_data.size(); }
bool empty() const { return m_data.empty(); }
void swap(secure_vector<T>& io_other) { m_data.swap(io_other.m_data); }
private:
std::vector<T> m_data;
};
using bytesSec = secure_vector<byte>;
// Numeric types.
using bigint = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<>>;
using u64 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<64, 64, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;

7
libdevcore/CommonData.cpp

@ -20,8 +20,7 @@
*/
#include "CommonData.h"
#include <random>
#include <boost/random/uniform_int_distribution.hpp>
#include "Exceptions.h"
#include "Log.h"
@ -59,9 +58,9 @@ std::string dev::escaped(std::string const& _s, bool _all)
std::string dev::randomWord()
{
static std::mt19937_64 s_eng(0);
std::string ret(std::uniform_int_distribution<int>(1, 5)(s_eng), ' ');
std::string ret(boost::random::uniform_int_distribution<int>(1, 5)(s_eng), ' ');
char const n[] = "qwertyuiop";//asdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890";
std::uniform_int_distribution<int> d(0, sizeof(n) - 2);
boost::random::uniform_int_distribution<int> d(0, sizeof(n) - 2);
for (char& c: ret)
c = n[d(s_eng)];
return ret;

20
libdevcore/CommonData.h

@ -349,6 +349,26 @@ std::vector<T> keysOf(std::unordered_map<T, U> const& _m)
return ret;
}
template<class T, class U>
std::vector<U> valuesOf(std::map<T, U> const& _m)
{
std::vector<U> ret;
ret.reserve(_m.size());
for (auto const& i: _m)
ret.push_back(i.second);
return ret;
}
template<class T, class U>
std::vector<U> valuesOf(std::unordered_map<T, U> const& _m)
{
std::vector<U> ret;
ret.reserve(_m.size());
for (auto const& i: _m)
ret.push_back(i.second);
return ret;
}
template <class T, class V>
bool contains(T const& _t, V const& _v)
{

17
libdevcore/CommonIO.cpp

@ -91,6 +91,14 @@ bytes dev::contents(string const& _file)
return contentsGeneric<bytes>(_file);
}
bytesSec dev::contentsSec(string const& _file)
{
bytes b = contentsGeneric<bytes>(_file);
bytesSec ret(b);
bytesRef(&b).cleanse();
return ret;
}
string dev::contentsString(string const& _file)
{
return contentsGeneric<string>(_file);
@ -110,14 +118,17 @@ void dev::writeFile(std::string const& _file, bytesConstRef _data, bool _writeDe
{
// create directory if not existent
fs::path p(_file);
fs::create_directories(p.parent_path());
fs::permissions(p.parent_path(), fs::owner_all);
if (!fs::exists(p.parent_path()))
{
fs::create_directories(p.parent_path());
DEV_IGNORE_EXCEPTIONS(fs::permissions(p.parent_path(), fs::owner_all));
}
ofstream s(_file, ios::trunc | ios::binary);
s.write(reinterpret_cast<char const*>(_data.data()), _data.size());
if (!s)
BOOST_THROW_EXCEPTION(FileError() << errinfo_comment("Could not write to file: " + _file));
fs::permissions(_file, fs::owner_read|fs::owner_write);
DEV_IGNORE_EXCEPTIONS(fs::permissions(_file, fs::owner_read|fs::owner_write));
}
}

2
libdevcore/CommonIO.h

@ -48,6 +48,8 @@ std::string getPassword(std::string const& _prompt);
/// Retrieve and returns the contents of the given file.
/// If the file doesn't exist or isn't readable, returns an empty container / bytes.
bytes contents(std::string const& _file);
/// Secure variation.
bytesSec contentsSec(std::string const& _file);
/// Retrieve and returns the contents of the given file as a std::string.
/// If the file doesn't exist or isn't readable, returns an empty container / bytes.
std::string contentsString(std::string const& _file);

11
libdevcore/CommonJS.h

@ -51,10 +51,17 @@ inline std::string toJS(bytes const& _n, std::size_t _padding = 0)
return "0x" + toHex(n);
}
template< typename T >std::string toJS( T const& i )
template<unsigned T> std::string toJS(SecureFixedHash<T> const& _i)
{
std::stringstream stream;
stream << "0x" << std::hex << i;
stream << "0x" << _i.makeInsecure().hex();
return stream.str();
}
template<typename T> std::string toJS(T const& _i)
{
std::stringstream stream;
stream << "0x" << std::hex << _i;
return stream.str();
}

2
libdevcore/Exceptions.h

@ -60,6 +60,8 @@ struct BadRoot: virtual Exception { public: BadRoot(h256 const& _root): Exceptio
DEV_SIMPLE_EXCEPTION(FileError);
DEV_SIMPLE_EXCEPTION(Overflow);
DEV_SIMPLE_EXCEPTION(FailedInvariant);
DEV_SIMPLE_EXCEPTION(ValueTooLarge);
struct InterfaceNotSupported: virtual Exception { public: InterfaceNotSupported(std::string _f): Exception("Interface " + _f + " not supported.") {} };
struct ExternalFunctionFailure: virtual Exception { public: ExternalFunctionFailure(std::string _f): Exception("Function " + _f + "() failed.") {} };

4
libdevcore/FileSystem.cpp

@ -27,7 +27,7 @@
#if defined(_WIN32)
#include <shlobj.h>
#elif defined(__APPLE__)
#else
#include <stdlib.h>
#include <stdio.h>
#include <pwd.h>
@ -56,14 +56,12 @@ std::string dev::getDataDir(std::string _prefix)
#else
boost::filesystem::path dataDirPath;
char const* homeDir = getenv("HOME");
#if defined(__APPLE__)
if (!homeDir || strlen(homeDir) == 0)
{
struct passwd* pwd = getpwuid(getuid());
if (pwd)
homeDir = pwd->pw_dir;
}
#endif
if (!homeDir || strlen(homeDir) == 0)
dataDirPath = boost::filesystem::path("/");

2
libdevcore/FixedHash.cpp

@ -26,7 +26,7 @@
using namespace std;
using namespace dev;
std::random_device dev::s_fixedHashEngine;
boost::random_device dev::s_fixedHashEngine;
h128 dev::fromUUID(std::string const& _uuid)
{

95
libdevcore/FixedHash.h

@ -25,8 +25,9 @@
#include <array>
#include <cstdint>
#include <random>
#include <algorithm>
#include <boost/random/random_device.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include "CommonData.h"
namespace dev
@ -36,7 +37,7 @@ namespace dev
template <unsigned N> struct StaticLog2 { enum { result = 1 + StaticLog2<N/2>::result }; };
template <> struct StaticLog2<1> { enum { result = 0 }; };
extern std::random_device s_fixedHashEngine;
extern boost::random_device s_fixedHashEngine;
/// Fixed-size raw-byte array container type, with an API optimised for storing hashes.
/// Transparently converts to/from the corresponding arithmetic type; this will
@ -154,7 +155,7 @@ public:
{
FixedHash ret;
for (auto& i: ret.m_data)
i = (uint8_t)std::uniform_int_distribution<uint16_t>(0, 255)(_eng);
i = (uint8_t)boost::random::uniform_int_distribution<uint16_t>(0, 255)(_eng);
return ret;
}
@ -214,10 +215,90 @@ public:
return ret;
}
void clear() { m_data.fill(0); }
private:
std::array<byte, N> m_data; ///< The binary data.
};
template <unsigned T>
class SecureFixedHash: private FixedHash<T>
{
public:
using ConstructFromHashType = typename FixedHash<T>::ConstructFromHashType;
using ConstructFromStringType = typename FixedHash<T>::ConstructFromStringType;
using ConstructFromPointerType = typename FixedHash<T>::ConstructFromPointerType;
SecureFixedHash() = default;
explicit SecureFixedHash(bytes const& _b, ConstructFromHashType _t = FixedHash<T>::FailIfDifferent): FixedHash<T>(_b, _t) {}
explicit SecureFixedHash(bytesConstRef _b, ConstructFromHashType _t = FixedHash<T>::FailIfDifferent): FixedHash<T>(_b, _t) {}
explicit SecureFixedHash(bytesSec const& _b, ConstructFromHashType _t = FixedHash<T>::FailIfDifferent): FixedHash<T>(_b.ref(), _t) {}
template <unsigned M> explicit SecureFixedHash(FixedHash<M> const& _h, ConstructFromHashType _t = FixedHash<T>::AlignLeft): FixedHash<T>(_h, _t) {}
template <unsigned M> explicit SecureFixedHash(SecureFixedHash<M> const& _h, ConstructFromHashType _t = FixedHash<T>::AlignLeft): FixedHash<T>(_h.makeInsecure(), _t) {}
explicit SecureFixedHash(std::string const& _s, ConstructFromStringType _t = FixedHash<T>::FromHex, ConstructFromHashType _ht = FixedHash<T>::FailIfDifferent): FixedHash<T>(_s, _t, _ht) {}
explicit SecureFixedHash(bytes const* _d, ConstructFromPointerType _t): FixedHash<T>(_d, _t) {}
~SecureFixedHash() { ref().cleanse(); }
SecureFixedHash<T>& operator=(SecureFixedHash<T> const& _c)
{
if (&_c == this)
return *this;
ref().cleanse();
FixedHash<T>::operator=(static_cast<FixedHash<T> const&>(_c));
return *this;
}
using FixedHash<T>::size;
bytesSec asBytesSec() const { return bytesSec(ref()); }
FixedHash<T> const& makeInsecure() const { return static_cast<FixedHash<T> const&>(*this); }
FixedHash<T>& writable() { clear(); return static_cast<FixedHash<T>&>(*this); }
using FixedHash<T>::operator bool;
// The obvious comparison operators.
bool operator==(SecureFixedHash const& _c) const { return static_cast<FixedHash<T> const&>(*this).operator==(static_cast<FixedHash<T> const&>(_c)); }
bool operator!=(SecureFixedHash const& _c) const { return static_cast<FixedHash<T> const&>(*this).operator!=(static_cast<FixedHash<T> const&>(_c)); }
bool operator<(SecureFixedHash const& _c) const { return static_cast<FixedHash<T> const&>(*this).operator<(static_cast<FixedHash<T> const&>(_c)); }
bool operator>=(SecureFixedHash const& _c) const { return static_cast<FixedHash<T> const&>(*this).operator>=(static_cast<FixedHash<T> const&>(_c)); }
bool operator<=(SecureFixedHash const& _c) const { return static_cast<FixedHash<T> const&>(*this).operator<=(static_cast<FixedHash<T> const&>(_c)); }
bool operator>(SecureFixedHash const& _c) const { return static_cast<FixedHash<T> const&>(*this).operator>(static_cast<FixedHash<T> const&>(_c)); }
using FixedHash<T>::operator==;
using FixedHash<T>::operator!=;
using FixedHash<T>::operator<;
using FixedHash<T>::operator>=;
using FixedHash<T>::operator<=;
using FixedHash<T>::operator>;
// The obvious binary operators.
SecureFixedHash& operator^=(FixedHash<T> const& _c) { static_cast<FixedHash<T>&>(*this).operator^=(_c); return *this; }
SecureFixedHash operator^(FixedHash<T> const& _c) const { return SecureFixedHash(*this) ^= _c; }
SecureFixedHash& operator|=(FixedHash<T> const& _c) { static_cast<FixedHash<T>&>(*this).operator^=(_c); return *this; }
SecureFixedHash operator|(FixedHash<T> const& _c) const { return SecureFixedHash(*this) |= _c; }
SecureFixedHash& operator&=(FixedHash<T> const& _c) { static_cast<FixedHash<T>&>(*this).operator^=(_c); return *this; }
SecureFixedHash operator&(FixedHash<T> const& _c) const { return SecureFixedHash(*this) &= _c; }
SecureFixedHash& operator^=(SecureFixedHash const& _c) { static_cast<FixedHash<T>&>(*this).operator^=(static_cast<FixedHash<T> const&>(_c)); return *this; }
SecureFixedHash operator^(SecureFixedHash const& _c) const { return SecureFixedHash(*this) ^= _c; }
SecureFixedHash& operator|=(SecureFixedHash const& _c) { static_cast<FixedHash<T>&>(*this).operator^=(static_cast<FixedHash<T> const&>(_c)); return *this; }
SecureFixedHash operator|(SecureFixedHash const& _c) const { return SecureFixedHash(*this) |= _c; }
SecureFixedHash& operator&=(SecureFixedHash const& _c) { static_cast<FixedHash<T>&>(*this).operator^=(static_cast<FixedHash<T> const&>(_c)); return *this; }
SecureFixedHash operator&(SecureFixedHash const& _c) const { return SecureFixedHash(*this) &= _c; }
SecureFixedHash operator~() const { auto r = ~static_cast<FixedHash<T> const&>(*this); return static_cast<SecureFixedHash const&>(r); }
using FixedHash<T>::abridged;
using FixedHash<T>::abridgedMiddle;
bytesConstRef ref() const { return FixedHash<T>::ref(); }
byte const* data() const { return FixedHash<T>::data(); }
static SecureFixedHash<T> random() { SecureFixedHash<T> ret; ret.FixedHash<T>::ref().randomize(); return ret; }
using FixedHash<T>::firstBitSet;
void clear() { ref().cleanse(); }
};
/// Fast equality operator for h256.
template<> inline bool FixedHash<32>::operator==(FixedHash<32> const& _other) const
{
@ -244,6 +325,14 @@ inline std::ostream& operator<<(std::ostream& _out, FixedHash<N> const& _h)
return _out;
}
/// Stream I/O for the SecureFixedHash class.
template <unsigned N>
inline std::ostream& operator<<(std::ostream& _out, SecureFixedHash<N> const& _h)
{
_out << "SecureFixedHash#" << std::hex << typename FixedHash<N>::hash()(_h.makeInsecure()) << std::dec;
return _out;
}
// Common types of FixedHash.
using h2048 = FixedHash<256>;
using h1024 = FixedHash<128>;

5
libdevcore/Guards.h

@ -24,7 +24,12 @@
#include <mutex>
#include <condition_variable>
#include <atomic>
#pragma warning(push)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <boost/thread.hpp>
#pragma warning(pop)
#pragma GCC diagnostic pop
namespace dev
{

5
libdevcore/Log.h

@ -25,7 +25,12 @@
#include <ctime>
#include <chrono>
#pragma warning(push)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <boost/thread.hpp>
#pragma warning(pop)
#pragma GCC diagnostic pop
#include "vector_ref.h"
#include "Common.h"
#include "CommonIO.h"

9
libdevcore/SHA3.cpp

@ -211,13 +211,14 @@ defsha3(512)
}
h256 sha3(bytesConstRef _input)
bool sha3(bytesConstRef _input, bytesRef o_output)
{
// FIXME: What with unaligned memory?
h256 ret;
keccak::sha3_256(ret.data(), 32, _input.data(), _input.size());
if (o_output.size() != 32)
return false;
keccak::sha3_256(o_output.data(), 32, _input.data(), _input.size());
// keccak::keccak(ret.data(), 32, (uint64_t const*)_input.data(), _input.size());
return ret;
return true;
}
}

19
libdevcore/SHA3.h

@ -32,20 +32,31 @@ namespace dev
// SHA-3 convenience routines.
/// Calculate SHA3-256 hash of the given input, returning as a 256-bit hash.
h256 sha3(bytesConstRef _input);
/// Calculate SHA3-256 hash of the given input and load it into the given output.
inline void sha3(bytesConstRef _input, bytesRef _output) { sha3(_input).ref().populate(_output); }
/// @returns false if o_output.size() != 32.
bool sha3(bytesConstRef _input, bytesRef o_output);
/// Calculate SHA3-256 hash of the given input, returning as a 256-bit hash.
inline h256 sha3(bytesConstRef _input) { h256 ret; sha3(_input, ret.ref()); return ret; }
inline SecureFixedHash<32> sha3Secure(bytesConstRef _input) { SecureFixedHash<32> ret; sha3(_input, ret.writable().ref()); return ret; }
/// Calculate SHA3-256 hash of the given input, returning as a 256-bit hash.
inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef(&_input)); }
inline SecureFixedHash<32> sha3Secure(bytes const& _input) { return sha3Secure(bytesConstRef(&_input)); }
/// Calculate SHA3-256 hash of the given input (presented as a binary-filled string), returning as a 256-bit hash.
inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); }
inline SecureFixedHash<32> sha3Secure(std::string const& _input) { return sha3Secure(bytesConstRef(_input)); }
/// Calculate SHA3-256 hash of the given input (presented as a FixedHash), returns a 256-bit hash.
template<unsigned N> inline h256 sha3(FixedHash<N> const& _input) { return sha3(_input.ref()); }
template<unsigned N> inline SecureFixedHash<32> sha3Secure(FixedHash<N> const& _input) { return sha3Secure(_input.ref()); }
/// Fully secure variants are equivalent for sha3 and sha3Secure.
inline SecureFixedHash<32> sha3(bytesSec const& _input) { return sha3Secure(_input.ref()); }
inline SecureFixedHash<32> sha3Secure(bytesSec const& _input) { return sha3Secure(_input.ref()); }
template<unsigned N> inline SecureFixedHash<32> sha3(SecureFixedHash<N> const& _input) { return sha3Secure(_input.ref()); }
template<unsigned N> inline SecureFixedHash<32> sha3Secure(SecureFixedHash<N> const& _input) { return sha3Secure(_input.ref()); }
/// Calculate SHA3-256 hash of the given input, possibly interpreting it as nibbles, and return the hash as a string filled with binary data.
inline std::string sha3(std::string const& _input, bool _isNibbles) { return asString((_isNibbles ? sha3(fromHex(_input)) : sha3(bytesConstRef(&_input))).asBytes()); }

2
libdevcore/TransientDirectory.cpp

@ -41,7 +41,7 @@ TransientDirectory::TransientDirectory(std::string const& _path):
BOOST_THROW_EXCEPTION(FileError());
fs::create_directories(m_path);
fs::permissions(m_path, fs::owner_all);
DEV_IGNORE_EXCEPTIONS(fs::permissions(m_path, fs::owner_all));
}
TransientDirectory::~TransientDirectory()

7
libdevcore/Worker.h

@ -54,7 +54,12 @@ protected:
Worker(Worker&& _m) { std::swap(m_name, _m.m_name); }
/// Move-assignment.
Worker& operator=(Worker&& _m) { std::swap(m_name, _m.m_name); return *this; }
Worker& operator=(Worker&& _m)
{
assert(&_m != this);
std::swap(m_name, _m.m_name);
return *this;
}
virtual ~Worker() { terminate(); }

34
libdevcore/vector_ref.h

@ -5,10 +5,16 @@
#include <type_traits>
#include <vector>
#include <string>
#include <random>
#include <boost/random/random_device.hpp>
#include <boost/random/uniform_int_distribution.hpp>
namespace dev
{
static unsigned char s_cleanseCounter = 0;
static boost::random_device s_vectorRefEngine;
/**
* A modifiable reference to an existing object or vector in memory.
*/
@ -65,6 +71,34 @@ public:
void copyTo(vector_ref<typename std::remove_const<_T>::type> _t) const { if (overlapsWith(_t)) memmove(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); else memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); }
/// Copies the contents of this vector_ref to the contents of @a _t, and zeros further trailing elements in @a _t.
void populate(vector_ref<typename std::remove_const<_T>::type> _t) const { copyTo(_t); memset(_t.data() + m_count, 0, std::max(_t.size(), m_count) - m_count); }
/// Populate with random data.
template <class Engine>
void randomize(Engine& _eng)
{
uint8_t* e = (uint8_t*)end();
for (uint8_t* i = (uint8_t*)begin(); i != e; ++i)
*i = (uint8_t)boost::random::uniform_int_distribution<uint16_t>(0, 255)(_eng);
}
/// @returns a random valued object.
void randomize() { randomize(s_vectorRefEngine); }
/// Securely overwrite the memory.
/// @note adapted from OpenSSL's implementation.
void cleanse()
{
uint8_t* p = (uint8_t*)begin();
size_t len = (uint8_t*)end() - p;
size_t loop = len;
size_t count = s_cleanseCounter;
while (loop--)
{
*(p++) = (uint8_t)count;
count += (17 + ((size_t)p & 0xf));
}
p = (uint8_t*)memchr((uint8_t*)begin(), (uint8_t)count, len);
if (p)
count += (63 + (size_t)p);
s_cleanseCounter = (uint8_t)count;
}
_T* begin() { return m_data; }
_T* end() { return m_data + m_count; }

2
libdevcrypto/AES.h

@ -31,4 +31,4 @@ namespace dev
bytes aesDecrypt(bytesConstRef _cipher, std::string const& _password, unsigned _rounds = 2000, bytesConstRef _salt = bytesConstRef());
}
}

6
libdevcrypto/CMakeLists.txt

@ -1,10 +1,4 @@
cmake_policy(SET CMP0015 NEW)
# this policy was introduced in cmake 3.0
# remove if, once 3.0 will be used on unix
if (${CMAKE_MAJOR_VERSION} GREATER 2)
# old policy do not use MACOSX_RPATH
cmake_policy(SET CMP0042 OLD)
endif()
set(CMAKE_AUTOMOC OFF)
aux_source_directory(. SRC_LIST)

137
libdevcrypto/Common.cpp

@ -21,7 +21,6 @@
*/
#include "Common.h"
#include <random>
#include <cstdint>
#include <chrono>
#include <thread>
@ -29,7 +28,6 @@
#include <libscrypt/libscrypt.h>
#include <libdevcore/Guards.h>
#include <libdevcore/SHA3.h>
#include <libdevcore/FileSystem.h>
#include <libdevcore/RLP.h>
#if ETH_HAVE_SECP256K1
#include <secp256k1/include/secp256k1.h>
@ -149,9 +147,9 @@ bool dev::decryptSym(Secret const& _k, bytesConstRef _cipher, bytes& o_plain)
return decrypt(_k, _cipher, o_plain);
}
std::pair<bytes, h128> dev::encryptSymNoAuth(h128 const& _k, bytesConstRef _plain)
std::pair<bytes, h128> dev::encryptSymNoAuth(SecureFixedHash<16> const& _k, bytesConstRef _plain)
{
h128 iv(Nonce::get());
h128 iv(Nonce::get().makeInsecure());
return make_pair(encryptSymNoAuth(_k, iv, _plain), iv);
}
@ -175,23 +173,23 @@ bytes dev::encryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _pl
}
}
bytes dev::decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _cipher)
bytesSec dev::decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _cipher)
{
if (_k.size() != 16 && _k.size() != 24 && _k.size() != 32)
return bytes();
return bytesSec();
SecByteBlock key(_k.data(), _k.size());
try
{
CTR_Mode<AES>::Decryption d;
d.SetKeyWithIV(key, key.size(), _iv.data());
bytes ret(_cipher.size());
d.ProcessData(ret.data(), _cipher.data(), _cipher.size());
bytesSec ret(_cipher.size());
d.ProcessData(ret.writable().data(), _cipher.data(), _cipher.size());
return ret;
}
catch (CryptoPP::Exception& _e)
{
cerr << _e.what() << endl;
return bytes();
return bytesSec();
}
}
@ -239,12 +237,12 @@ bool dev::verify(Public const& _p, Signature const& _s, h256 const& _hash)
#endif
}
bytes dev::pbkdf2(string const& _pass, bytes const& _salt, unsigned _iterations, unsigned _dkLen)
bytesSec dev::pbkdf2(string const& _pass, bytes const& _salt, unsigned _iterations, unsigned _dkLen)
{
bytes ret(_dkLen);
bytesSec ret(_dkLen);
if (PKCS5_PBKDF2_HMAC<SHA256>().DeriveKey(
ret.data(),
ret.size(),
ret.writable().data(),
_dkLen,
0,
reinterpret_cast<byte const*>(_pass.data()),
_pass.size(),
@ -256,9 +254,9 @@ bytes dev::pbkdf2(string const& _pass, bytes const& _salt, unsigned _iterations,
return ret;
}
bytes dev::scrypt(std::string const& _pass, bytes const& _salt, uint64_t _n, uint32_t _r, uint32_t _p, unsigned _dkLen)
bytesSec dev::scrypt(std::string const& _pass, bytes const& _salt, uint64_t _n, uint32_t _r, uint32_t _p, unsigned _dkLen)
{
bytes ret(_dkLen);
bytesSec ret(_dkLen);
if (libscrypt_scrypt(
reinterpret_cast<uint8_t const*>(_pass.data()),
_pass.size(),
@ -267,41 +265,41 @@ bytes dev::scrypt(std::string const& _pass, bytes const& _salt, uint64_t _n, uin
_n,
_r,
_p,
ret.data(),
ret.size()
ret.writable().data(),
_dkLen
) != 0)
BOOST_THROW_EXCEPTION(CryptoException() << errinfo_comment("Key derivation failed."));
return ret;
}
void KeyPair::populateFromSecret(Secret const& _sec)
{
m_secret = _sec;
if (s_secp256k1pp.verifySecret(m_secret, m_public))
m_address = toAddress(m_public);
}
KeyPair KeyPair::create()
{
for (int i = 0; i < 100; ++i)
{
KeyPair ret(FixedHash<32>::random());
KeyPair ret(Secret::random());
if (ret.address())
return ret;
}
return KeyPair();
}
KeyPair::KeyPair(h256 _sec):
m_secret(_sec)
{
if (s_secp256k1pp.verifySecret(m_secret, m_public))
m_address = toAddress(m_public);
}
KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _password)
{
return KeyPair(sha3(aesDecrypt(_seed, _password)));
return KeyPair(Secret(sha3(aesDecrypt(_seed, _password))));
}
h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
{
// H(H(r||k)^h)
h256 s;
sha3mac(Nonce::get().ref(), _priv.ref(), s.ref());
sha3mac(Secret::random().ref(), _priv.ref(), s.ref());
s ^= _hash;
sha3(s.ref(), s.ref());
@ -310,84 +308,15 @@ h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
return s;
}
mutex Nonce::s_x;
static string s_seedFile;
h256 Nonce::get()
{
// todo: atomic efface bit, periodic save, kdf, rr, rng
// todo: encrypt
Guard l(Nonce::s_x);
return Nonce::singleton().next();
}
void Nonce::reset()
{
Guard l(Nonce::s_x);
Nonce::singleton().resetInternal();
}
void Nonce::setSeedFilePath(string const& _filePath)
{
s_seedFile = _filePath;
}
Nonce::~Nonce()
Secret Nonce::next()
{
Guard l(Nonce::s_x);
if (m_value)
// this might throw
resetInternal();
}
Nonce& Nonce::singleton()
{
static Nonce s;
return s;
}
void Nonce::initialiseIfNeeded()
{
if (m_value)
return;
bytes b = contents(seedFile());
if (b.size() == 32)
memcpy(m_value.data(), b.data(), 32);
else
Guard l(x_value);
if (!m_value)
{
// todo: replace w/entropy from user and system
std::mt19937_64 s_eng(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count());
std::uniform_int_distribution<uint16_t> d(0, 255);
for (unsigned i = 0; i < 32; ++i)
m_value[i] = (uint8_t)d(s_eng);
m_value = Secret::random();
if (!m_value)
BOOST_THROW_EXCEPTION(InvalidState());
}
if (!m_value)
BOOST_THROW_EXCEPTION(InvalidState());
// prevent seed reuse if process terminates abnormally
// this might throw
writeFile(seedFile(), bytes());
}
h256 Nonce::next()
{
initialiseIfNeeded();
m_value = sha3(m_value);
return m_value;
}
void Nonce::resetInternal()
{
// this might throw
next();
writeFile(seedFile(), m_value.asBytes());
m_value = h256();
}
string const& Nonce::seedFile()
{
if (s_seedFile.empty())
s_seedFile = getDataDir() + "/seed";
return s_seedFile;
m_value = sha3Secure(m_value.ref());
return sha3(~m_value);
}

73
libdevcrypto/Common.h

@ -28,13 +28,12 @@
#include <libdevcore/Common.h>
#include <libdevcore/FixedHash.h>
#include <libdevcore/Exceptions.h>
#include <libdevcore/FileSystem.h>
namespace dev
{
/// A secret key: 32 bytes.
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
using Secret = h256;
using Secret = SecureFixedHash<32>;
/// A public key: 64 bytes.
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
@ -76,7 +75,7 @@ using Addresses = h160s;
using AddressHash = std::unordered_set<h160>;
/// A vector of secrets.
using Secrets = h256s;
using Secrets = std::vector<Secret>;
/// Convert a secret key into the public key equivalent.
Public toPublic(Secret const& _secret);
@ -110,21 +109,21 @@ void encryptECIES(Public const& _k, bytesConstRef _plain, bytes& o_cipher);
bool decryptECIES(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext);
/// Encrypts payload with random IV/ctr using AES128-CTR.
std::pair<bytes, h128> encryptSymNoAuth(h128 const& _k, bytesConstRef _plain);
std::pair<bytes, h128> encryptSymNoAuth(SecureFixedHash<16> const& _k, bytesConstRef _plain);
/// Encrypts payload with specified IV/ctr using AES128-CTR.
bytes encryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _plain);
/// Decrypts payload with specified IV/ctr using AES128-CTR.
bytes decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _cipher);
bytesSec decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _cipher);
/// Encrypts payload with specified IV/ctr using AES128-CTR.
inline bytes encryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _plain) { return encryptAES128CTR(_k.ref(), _iv, _plain); }
inline bytes encryptSymNoAuth(h256 const& _k, h128 const& _iv, bytesConstRef _plain) { return encryptAES128CTR(_k.ref(), _iv, _plain); }
inline bytes encryptSymNoAuth(SecureFixedHash<16> const& _k, h128 const& _iv, bytesConstRef _plain) { return encryptAES128CTR(_k.ref(), _iv, _plain); }
inline bytes encryptSymNoAuth(SecureFixedHash<32> const& _k, h128 const& _iv, bytesConstRef _plain) { return encryptAES128CTR(_k.ref(), _iv, _plain); }
/// Decrypts payload with specified IV/ctr using AES128-CTR.
inline bytes decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher) { return decryptAES128CTR(_k.ref(), _iv, _cipher); }
inline bytes decryptSymNoAuth(h256 const& _k, h128 const& _iv, bytesConstRef _cipher) { return decryptAES128CTR(_k.ref(), _iv, _cipher); }
inline bytesSec decryptSymNoAuth(SecureFixedHash<16> const& _k, h128 const& _iv, bytesConstRef _cipher) { return decryptAES128CTR(_k.ref(), _iv, _cipher); }
inline bytesSec decryptSymNoAuth(SecureFixedHash<32> const& _k, h128 const& _iv, bytesConstRef _cipher) { return decryptAES128CTR(_k.ref(), _iv, _cipher); }
/// Recovers Public key from signed message hash.
Public recover(Signature const& _sig, h256 const& _hash);
@ -136,10 +135,10 @@ Signature sign(Secret const& _k, h256 const& _hash);
bool verify(Public const& _k, Signature const& _s, h256 const& _hash);
/// Derive key via PBKDF2.
bytes pbkdf2(std::string const& _pass, bytes const& _salt, unsigned _iterations, unsigned _dkLen = 32);
bytesSec pbkdf2(std::string const& _pass, bytes const& _salt, unsigned _iterations, unsigned _dkLen = 32);
/// Derive key via Scrypt.
bytes scrypt(std::string const& _pass, bytes const& _salt, uint64_t _n, uint32_t _r, uint32_t _p, unsigned _dkLen);
bytesSec scrypt(std::string const& _pass, bytes const& _salt, uint64_t _n, uint32_t _r, uint32_t _p, unsigned _dkLen);
/// Simple class that represents a "key pair".
/// All of the data of the class can be regenerated from the secret key (m_secret) alone.
@ -151,7 +150,7 @@ public:
KeyPair() {}
/// Normal constructor - populates object from the given secret key.
KeyPair(Secret _k);
KeyPair(Secret const& _k) { populateFromSecret(_k); }
/// Create a new, randomly generated object.
static KeyPair create();
@ -170,10 +169,12 @@ public:
/// Retrieve the associated address of the public key.
Address const& address() const { return m_address; }
bool operator==(KeyPair const& _c) const { return m_secret == _c.m_secret; }
bool operator!=(KeyPair const& _c) const { return m_secret != _c.m_secret; }
bool operator==(KeyPair const& _c) const { return m_public == _c.m_public; }
bool operator!=(KeyPair const& _c) const { return m_public != _c.m_public; }
private:
void populateFromSecret(Secret const& _k);
Secret m_secret;
Public m_public;
Address m_address;
@ -181,43 +182,37 @@ private:
namespace crypto
{
struct InvalidState: public dev::Exception {};
DEV_SIMPLE_EXCEPTION(InvalidState);
/// Key derivation
h256 kdf(Secret const& _priv, h256 const& _hash);
/**
* @brief Generator for nonce material.
* @brief Generator for non-repeating nonce material.
* The Nonce class should only be used when a non-repeating nonce
* is required and, in its current form, not recommended for signatures.
* This is primarily because the key-material for signatures is
* encrypted on disk whereas the seed for Nonce is not.
* Thus, Nonce's primary intended use at this time is for networking
* where the key is also stored in plaintext.
*/
struct Nonce
class Nonce
{
public:
/// Returns the next nonce (might be read from a file).
static h256 get();
/// Stores the current nonce in a file and resets Nonce to the uninitialised state.
static void reset();
/// Sets the location of the seed file to a non-default place. Used for testing.
static void setSeedFilePath(std::string const& _filePath);
static Secret get() { static Nonce s; return s.next(); }
private:
Nonce() {}
~Nonce();
/// @returns the singleton instance.
static Nonce& singleton();
/// Reads the last seed from the seed file.
void initialiseIfNeeded();
/// @returns the next nonce.
h256 next();
/// Stores the current seed in the seed file.
void resetInternal();
/// @returns the path of the seed file.
static std::string const& seedFile();
Nonce() = default;
/// Mutex for the singleton object.
/// @note Every access to any private function has to be guarded by this mutex.
static std::mutex s_x;
/// @returns the next nonce.
Secret next();
h256 m_value;
std::mutex x_value;
Secret m_value;
};
}
}

18
libdevcrypto/CryptoPP.cpp

@ -33,7 +33,7 @@ static_assert(dev::Secret::size == 32, "Secret key must be 32 bytes.");
static_assert(dev::Public::size == 64, "Public key must be 64 bytes.");
static_assert(dev::Signature::size == 65, "Signature must be 65 bytes.");
bytes Secp256k1PP::eciesKDF(Secret _z, bytes _s1, unsigned kdByteLen)
bytes Secp256k1PP::eciesKDF(Secret const& _z, bytes _s1, unsigned kdByteLen)
{
auto reps = ((kdByteLen + 7) * 8) / (CryptoPP::SHA256::BLOCKSIZE * 8);
// SEC/ISO/Shoup specify counter size SHOULD be equivalent
@ -67,7 +67,7 @@ void Secp256k1PP::encryptECIES(Public const& _k, bytes& io_cipher)
{
// interop w/go ecies implementation
auto r = KeyPair::create();
h256 z;
Secret z;
ecdh::agree(r.sec(), _k, z);
auto key = eciesKDF(z, bytes(), 32);
bytesConstRef eKey = bytesConstRef(&key).cropped(0, 16);
@ -77,7 +77,7 @@ void Secp256k1PP::encryptECIES(Public const& _k, bytes& io_cipher)
bytes mKey(32);
ctx.Final(mKey.data());
bytes cipherText = encryptSymNoAuth(h128(eKey), h128(), bytesConstRef(&io_cipher));
bytes cipherText = encryptSymNoAuth(SecureFixedHash<16>(eKey), h128(), bytesConstRef(&io_cipher));
if (cipherText.empty())
return;
@ -110,8 +110,8 @@ bool Secp256k1PP::decryptECIES(Secret const& _k, bytes& io_text)
// invalid message: length
return false;
h256 z;
ecdh::agree(_k, *(Public*)(io_text.data()+1), z);
Secret z;
ecdh::agree(_k, *(Public*)(io_text.data() + 1), z);
auto key = eciesKDF(z, bytes(), 64);
bytesConstRef eKey = bytesConstRef(&key).cropped(0, 16);
bytesRef mKeyMaterial = bytesRef(&key).cropped(16, 16);
@ -137,7 +137,7 @@ bool Secp256k1PP::decryptECIES(Secret const& _k, bytes& io_text)
if (mac[i] != msgMac[i])
return false;
plain = decryptSymNoAuth(h128(eKey), iv, cipherNoIV);
plain = decryptSymNoAuth(SecureFixedHash<16>(eKey), iv, cipherNoIV).makeInsecure();
io_text.resize(plain.size());
io_text.swap(plain);
@ -222,7 +222,7 @@ Signature Secp256k1PP::sign(Secret const& _key, h256 const& _hash)
Integer kInv = k.InverseMod(m_q);
Integer z(_hash.asBytes().data(), 32);
Integer s = (kInv * (Integer(_key.asBytes().data(), 32) * r + z)) % m_q;
Integer s = (kInv * (Integer(_key.data(), 32) * r + z)) % m_q;
if (r == 0 || s == 0)
BOOST_THROW_EXCEPTION(InvalidState());
@ -310,7 +310,7 @@ bool Secp256k1PP::verifySecret(Secret const& _s, Public& _p)
return true;
}
void Secp256k1PP::agree(Secret const& _s, Public const& _r, h256& o_s)
void Secp256k1PP::agree(Secret const& _s, Public const& _r, Secret& o_s)
{
// TODO: mutex ASN1::secp256k1() singleton
// Creating Domain is non-const for m_oid and m_oid is not thread-safe
@ -318,7 +318,7 @@ void Secp256k1PP::agree(Secret const& _s, Public const& _r, h256& o_s)
assert(d.AgreedValueLength() == sizeof(o_s));
byte remote[65] = {0x04};
memcpy(&remote[1], _r.data(), 64);
d.Agree(o_s.data(), _s.data(), remote);
d.Agree(o_s.writable().data(), _s.data(), remote);
}
void Secp256k1PP::exportPublicKey(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const& _k, Public& o_p)

6
libdevcrypto/CryptoPP.h

@ -87,7 +87,7 @@ public:
bool decryptECIES(Secret const& _k, bytes& io_text);
/// Key derivation function used by encryptECIES and decryptECIES.
bytes eciesKDF(Secret _z, bytes _s1, unsigned kdBitLen = 256);
bytes eciesKDF(Secret const& _z, bytes _s1, unsigned kdBitLen = 256);
/// @returns siganture of message.
Signature sign(Secret const& _k, bytesConstRef _message);
@ -107,10 +107,10 @@ public:
/// Verifies _s is a valid secret key and returns corresponding public key in o_p.
bool verifySecret(Secret const& _s, Public& o_p);
void agree(Secret const& _s, Public const& _r, h256& o_s);
void agree(Secret const& _s, Public const& _r, Secret& o_s);
protected:
void exportPrivateKey(DL_PrivateKey_EC<ECP> const& _k, Secret& o_s) { _k.GetPrivateExponent().Encode(o_s.data(), Secret::size); }
void exportPrivateKey(DL_PrivateKey_EC<ECP> const& _k, Secret& o_s) { _k.GetPrivateExponent().Encode(o_s.writable().data(), Secret::size); }
void exportPublicKey(DL_PublicKey_EC<ECP> const& _k, Public& o_p);

2
libdevcrypto/ECDHE.cpp

@ -29,7 +29,7 @@ using namespace dev::crypto;
static Secp256k1PP s_secp256k1;
void dev::crypto::ecdh::agree(Secret const& _s, Public const& _r, h256& o_s)
void dev::crypto::ecdh::agree(Secret const& _s, Public const& _r, Secret& o_s)
{
s_secp256k1.agree(_s, _r, o_s);
}

4
libdevcrypto/ECDHE.h

@ -39,7 +39,7 @@ using AliasSession = std::pair<Public,h256>;
class Alias
{
public:
Alias(Secret _s): m_secret(_s) {};
Alias(Secret const& _s): m_secret(_s) {};
AliasSession session(Address _a) { return m_sessions.count(_a) ? m_sessions.find(_a)->second : AliasSession(); }
@ -50,7 +50,7 @@ private:
namespace ecdh
{
void agree(Secret const& _s, Public const& _r, h256& o_s);
void agree(Secret const& _s, Public const& _r, Secret& o_s);
}
/**

67
libdevcrypto/SecretStore.cpp

@ -91,26 +91,26 @@ SecretStore::SecretStore(string const& _path): m_path(_path)
load();
}
bytes SecretStore::secret(h128 const& _uuid, function<string()> const& _pass, bool _useCache) const
bytesSec SecretStore::secret(h128 const& _uuid, function<string()> const& _pass, bool _useCache) const
{
auto rit = m_cached.find(_uuid);
if (_useCache && rit != m_cached.end())
return rit->second;
auto it = m_keys.find(_uuid);
bytes key;
bytesSec key;
if (it != m_keys.end())
{
key = decrypt(it->second.encryptedKey, _pass());
key = bytesSec(decrypt(it->second.encryptedKey, _pass()));
if (!key.empty())
m_cached[_uuid] = key;
}
return key;
}
h128 SecretStore::importSecret(bytes const& _s, string const& _pass)
h128 SecretStore::importSecret(bytesSec const& _s, string const& _pass)
{
h128 r;
EncryptedKey key{encrypt(_s, _pass), string()};
EncryptedKey key{encrypt(_s.ref(), _pass), string()};
r = h128::random();
m_cached[r] = _s;
m_keys[r] = move(key);
@ -118,6 +118,17 @@ h128 SecretStore::importSecret(bytes const& _s, string const& _pass)
return r;
}
h128 SecretStore::importSecret(bytesConstRef _s, string const& _pass)
{
h128 r;
EncryptedKey key{encrypt(_s, _pass), string()};
r = h128::random();
m_cached[r] = bytesSec(_s);
m_keys[r] = move(key);
save();
return r;
}
void SecretStore::kill(h128 const& _uuid)
{
m_cached.erase(_uuid);
@ -137,7 +148,7 @@ void SecretStore::save(string const& _keysPath)
{
fs::path p(_keysPath);
fs::create_directories(p);
fs::permissions(p, fs::owner_all);
DEV_IGNORE_EXCEPTIONS(fs::permissions(p, fs::owner_all));
for (auto& k: m_keys)
{
string uuid = toUUID(k.first);
@ -159,7 +170,7 @@ void SecretStore::load(string const& _keysPath)
{
fs::path p(_keysPath);
fs::create_directories(p);
fs::permissions(p, fs::owner_all);
DEV_IGNORE_EXCEPTIONS(fs::permissions(p, fs::owner_all));
for (fs::directory_iterator it(p); it != fs::directory_iterator(); ++it)
if (fs::is_regular_file(it->path()))
readKey(it->path().string(), true);
@ -188,16 +199,16 @@ h128 SecretStore::readKeyContent(string const& _content, string const& _file)
bool SecretStore::recode(h128 const& _uuid, string const& _newPass, function<string()> const& _pass, KDF _kdf)
{
bytes s = secret(_uuid, _pass, true);
bytesSec s = secret(_uuid, _pass, true);
if (s.empty())
return false;
m_cached.erase(_uuid);
m_keys[_uuid].encryptedKey = encrypt(s, _newPass, _kdf);
m_keys[_uuid].encryptedKey = encrypt(s.ref(), _newPass, _kdf);
save();
return true;
}
static bytes deriveNewKey(string const& _pass, KDF _kdf, js::mObject& o_ret)
static bytesSec deriveNewKey(string const& _pass, KDF _kdf, js::mObject& o_ret)
{
unsigned dklen = 32;
unsigned iterations = 1 << 18;
@ -233,16 +244,16 @@ static bytes deriveNewKey(string const& _pass, KDF _kdf, js::mObject& o_ret)
}
}
string SecretStore::encrypt(bytes const& _v, string const& _pass, KDF _kdf)
string SecretStore::encrypt(bytesConstRef _v, string const& _pass, KDF _kdf)
{
js::mObject ret;
bytes derivedKey = deriveNewKey(_pass, _kdf, ret);
bytesSec derivedKey = deriveNewKey(_pass, _kdf, ret);
if (derivedKey.empty())
BOOST_THROW_EXCEPTION(crypto::CryptoException() << errinfo_comment("Key derivation failed."));
ret["cipher"] = "aes-128-ctr";
h128 key(derivedKey, h128::AlignLeft);
SecureFixedHash<16> key(derivedKey, h128::AlignLeft);
h128 iv = h128::random();
{
js::mObject params;
@ -251,19 +262,19 @@ string SecretStore::encrypt(bytes const& _v, string const& _pass, KDF _kdf)
}
// cipher text
bytes cipherText = encryptSymNoAuth(key, iv, &_v);
bytes cipherText = encryptSymNoAuth(key, iv, _v);
if (cipherText.empty())
BOOST_THROW_EXCEPTION(crypto::CryptoException() << errinfo_comment("Key encryption failed."));
ret["ciphertext"] = toHex(cipherText);
// and mac.
h256 mac = sha3(ref(derivedKey).cropped(16, 16).toBytes() + cipherText);
h256 mac = sha3(derivedKey.ref().cropped(16, 16).toBytes() + cipherText);
ret["mac"] = toHex(mac.ref());
return js::write_string(js::mValue(ret), true);
}
bytes SecretStore::decrypt(string const& _v, string const& _pass)
bytesSec SecretStore::decrypt(string const& _v, string const& _pass)
{
js::mObject o;
{
@ -273,14 +284,14 @@ bytes SecretStore::decrypt(string const& _v, string const& _pass)
}
// derive key
bytes derivedKey;
bytesSec derivedKey;
if (o["kdf"].get_str() == "pbkdf2")
{
auto params = o["kdfparams"].get_obj();
if (params["prf"].get_str() != "hmac-sha256")
{
cwarn << "Unknown PRF for PBKDF2" << params["prf"].get_str() << "not supported.";
return bytes();
return bytesSec();
}
unsigned iterations = params["c"].get_int();
bytes salt = fromHex(params["salt"].get_str());
@ -294,13 +305,13 @@ bytes SecretStore::decrypt(string const& _v, string const& _pass)
else
{
cwarn << "Unknown KDF" << o["kdf"].get_str() << "not supported.";
return bytes();
return bytesSec();
}
if (derivedKey.size() < 32 && !(o.count("compat") && o["compat"].get_str() == "2"))
{
cwarn << "Derived key's length too short (<32 bytes)";
return bytes();
return bytesSec();
}
bytes cipherText = fromHex(o["ciphertext"].get_str());
@ -311,23 +322,23 @@ bytes SecretStore::decrypt(string const& _v, string const& _pass)
h256 mac(o["mac"].get_str());
h256 macExp;
if (o.count("compat") && o["compat"].get_str() == "2")
macExp = sha3(bytesConstRef(&derivedKey).cropped(derivedKey.size() - 16).toBytes() + cipherText);
macExp = sha3(derivedKey.ref().cropped(derivedKey.size() - 16).toBytes() + cipherText);
else
macExp = sha3(bytesConstRef(&derivedKey).cropped(16, 16).toBytes() + cipherText);
macExp = sha3(derivedKey.ref().cropped(16, 16).toBytes() + cipherText);
if (mac != macExp)
{
cwarn << "Invalid key - MAC mismatch; expected" << toString(macExp) << ", got" << toString(mac);
return bytes();
return bytesSec();
}
}
else if (o.count("sillymac"))
{
h256 mac(o["sillymac"].get_str());
h256 macExp = sha3(asBytes(o["sillymacjson"].get_str()) + bytesConstRef(&derivedKey).cropped(derivedKey.size() - 16).toBytes() + cipherText);
h256 macExp = sha3(asBytes(o["sillymacjson"].get_str()) + derivedKey.ref().cropped(derivedKey.size() - 16).toBytes() + cipherText);
if (mac != macExp)
{
cwarn << "Invalid key - MAC mismatch; expected" << toString(macExp) << ", got" << toString(mac);
return bytes();
return bytesSec();
}
}
else
@ -340,15 +351,15 @@ bytes SecretStore::decrypt(string const& _v, string const& _pass)
h128 iv(params["iv"].get_str());
if (o.count("compat") && o["compat"].get_str() == "2")
{
h128 key(sha3(h128(derivedKey, h128::AlignRight)), h128::AlignRight);
SecureFixedHash<16> key(sha3Secure(derivedKey.ref().cropped(derivedKey.size() - 16)), h128::AlignRight);
return decryptSymNoAuth(key, iv, &cipherText);
}
else
return decryptSymNoAuth(h128(derivedKey, h128::AlignLeft), iv, &cipherText);
return decryptSymNoAuth(SecureFixedHash<16>(derivedKey, h128::AlignLeft), iv, &cipherText);
}
else
{
cwarn << "Unknown cipher" << o["cipher"].get_str() << "not supported.";
return bytes();
return bytesSec();
}
}

14
libdevcrypto/SecretStore.h

@ -52,7 +52,7 @@ public:
/// @returns the secret key stored by the given @a _uuid.
/// @param _pass function that returns the password for the key.
/// @param _useCache if true, allow previously decrypted keys to be returned directly.
bytes secret(h128 const& _uuid, std::function<std::string()> const& _pass, bool _useCache = true) const;
bytesSec secret(h128 const& _uuid, std::function<std::string()> const& _pass, bool _useCache = true) const;
/// Imports the (encrypted) key stored in the file @a _file and copies it to the managed directory.
h128 importKey(std::string const& _file) { auto ret = readKey(_file, false); if (ret) save(); return ret; }
/// Imports the (encrypted) key contained in the json formatted @a _content and stores it in
@ -60,7 +60,8 @@ public:
h128 importKeyContent(std::string const& _content) { auto ret = readKeyContent(_content, std::string()); if (ret) save(); return ret; }
/// Imports the decrypted key given by @a _s and stores it, encrypted with
/// (a key derived from) the password @a _pass.
h128 importSecret(bytes const& _s, std::string const& _pass);
h128 importSecret(bytesSec const& _s, std::string const& _pass);
h128 importSecret(bytesConstRef _s, std::string const& _pass);
/// Decrypts and re-encrypts the key identified by @a _uuid.
bool recode(h128 const& _uuid, std::string const& _newPass, std::function<std::string()> const& _pass, KDF _kdf = KDF::Scrypt);
/// Removes the key specified by @a _uuid from both memory and disk.
@ -69,6 +70,9 @@ public:
/// Returns the uuids of all stored keys.
std::vector<h128> keys() const { return keysOf(m_keys); }
/// @returns true iff we have the given key stored.
bool contains(h128 const& _k) const { return m_keys.count(_k); }
/// Clears all cached decrypted keys. The passwords have to be supplied in order to retrieve
/// secrets again after calling this function.
void clearCache() const;
@ -102,12 +106,12 @@ private:
void load(std::string const& _keysPath);
void load() { load(m_path); }
/// Encrypts @a _v with a key derived from @a _pass or the empty string on error.
static std::string encrypt(bytes const& _v, std::string const& _pass, KDF _kdf = KDF::Scrypt);
static std::string encrypt(bytesConstRef _v, std::string const& _pass, KDF _kdf = KDF::Scrypt);
/// Decrypts @a _v with a key derived from @a _pass or the empty byte array on error.
static bytes decrypt(std::string const& _v, std::string const& _pass);
static bytesSec decrypt(std::string const& _v, std::string const& _pass);
/// Stores decrypted keys by uuid.
mutable std::unordered_map<h128, bytes> m_cached;
mutable std::unordered_map<h128, bytesSec> m_cached;
/// Stores encrypted keys together with the file they were loaded from by uuid.
std::unordered_map<h128, EncryptedKey> m_keys;

5036
libdevcrypto/WordList.cpp

File diff suppressed because it is too large

31
libdevcrypto/WordList.h

@ -0,0 +1,31 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file WordList.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include "Common.h"
namespace dev
{
extern strings const WordList;
}

80
libethash-cl/ethash_cl_miner.cpp

@ -29,8 +29,11 @@
#include <iostream>
#include <assert.h>
#include <queue>
#include <random>
#include <vector>
#include <random>
#include <random>
#include <atomic>
#include <sstream>
#include <libethash/util.h>
#include <libethash/ethash.h>
#include <libethash/internal.h>
@ -55,7 +58,22 @@ unsigned const ethash_cl_miner::c_defaultGlobalWorkSizeMultiplier = 4096; // * C
unsigned const ethash_cl_miner::c_defaultMSPerBatch = 0;
// TODO: If at any point we can use libdevcore in here then we should switch to using a LogChannel
#if defined(_WIN32)
extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* lpOutputString);
static std::atomic_flag s_logSpin = ATOMIC_FLAG_INIT;
#define ETHCL_LOG(_contents) \
do \
{ \
std::stringstream ss; \
ss << _contents; \
while (s_logSpin.test_and_set(std::memory_order_acquire)) {} \
OutputDebugStringA(ss.str().c_str()); \
cerr << ss.str() << endl << flush; \
s_logSpin.clear(std::memory_order_release); \
} while (false)
#else
#define ETHCL_LOG(_contents) cout << "[OPENCL]:" << _contents << endl
#endif
// Types of OpenCL devices we are interested in
#define ETHCL_QUERIED_DEVICE_TYPES (CL_DEVICE_TYPE_GPU | CL_DEVICE_TYPE_ACCELERATOR)
@ -266,6 +284,25 @@ void ethash_cl_miner::listDevices()
doForAllDevices([&outString, &i](cl::Device const _device)
{
outString += "[" + to_string(i) + "] " + _device.getInfo<CL_DEVICE_NAME>() + "\n";
outString += "\tCL_DEVICE_TYPE: ";
switch (_device.getInfo<CL_DEVICE_TYPE>())
{
case CL_DEVICE_TYPE_CPU:
outString += "CPU\n";
break;
case CL_DEVICE_TYPE_GPU:
outString += "GPU\n";
break;
case CL_DEVICE_TYPE_ACCELERATOR:
outString += "ACCELERATOR\n";
break;
default:
outString += "DEFAULT\n";
break;
}
outString += "\tCL_DEVICE_GLOBAL_MEM_SIZE: " + to_string(_device.getInfo<CL_DEVICE_GLOBAL_MEM_SIZE>()) + "\n";
outString += "\tCL_DEVICE_MAX_MEM_ALLOC_SIZE: " + to_string(_device.getInfo<CL_DEVICE_MAX_MEM_ALLOC_SIZE>()) + "\n";
outString += "\tCL_DEVICE_MAX_WORK_GROUP_SIZE: " + to_string(_device.getInfo<CL_DEVICE_MAX_WORK_GROUP_SIZE>()) + "\n";
++i;
}
);
@ -361,15 +398,25 @@ bool ethash_cl_miner::init(
try
{
m_dagChunksCount = 1;
ETHCL_LOG("Creating one big buffer for the DAG");
m_dagChunks.push_back(cl::Buffer(m_context, CL_MEM_READ_ONLY, _dagSize));
ETHCL_LOG("Created one big buffer for the DAG");
ETHCL_LOG("Loading single big chunk kernels");
m_hashKernel = cl::Kernel(program, "ethash_hash");
m_searchKernel = cl::Kernel(program, "ethash_search");
ETHCL_LOG("Mapping one big chunk.");
m_queue.enqueueWriteBuffer(m_dagChunks[0], CL_TRUE, 0, _dagSize, _dag);
}
catch (cl::Error const& err)
{
ETHCL_LOG("Allocating/mapping single buffer failed with: " << err.what() << "(" << err.err() << "). GPU can't allocate the DAG in a single chunk. Bailing.");
return false;
#if 0 // Disabling chunking for release since it seems not to work. Never manages to mine a block. TODO: Fix when time is found.
int errCode = err.err();
if (errCode != CL_INVALID_BUFFER_SIZE || errCode != CL_MEM_OBJECT_ALLOCATION_FAILURE)
ETHCL_LOG("Allocating single buffer failed with: " << err.what() << "(" << errCode << ")");
ETHCL_LOG("Allocating/mapping single buffer failed with: " << err.what() << "(" << errCode << ")");
cl_ulong result;
// if we fail midway on the try above make sure we start clean
m_dagChunks.clear();
device.getInfo(CL_DEVICE_MAX_MEM_ALLOC_SIZE, &result);
ETHCL_LOG(
"Failed to allocate 1 big chunk. Max allocateable memory is "
@ -387,32 +434,9 @@ bool ethash_cl_miner::init(
(i == 3) ? (_dagSize - 3 * ((_dagSize >> 9) << 7)) : (_dagSize >> 9) << 7
));
}
}
if (m_dagChunksCount == 1)
{
ETHCL_LOG("Loading single big chunk kernels");
m_hashKernel = cl::Kernel(program, "ethash_hash");
m_searchKernel = cl::Kernel(program, "ethash_search");
}
else
{
ETHCL_LOG("Loading chunk kernels");
m_hashKernel = cl::Kernel(program, "ethash_hash_chunks");
m_searchKernel = cl::Kernel(program, "ethash_search_chunks");
}
// create buffer for header
ETHCL_LOG("Creating buffer for header.");
m_header = cl::Buffer(m_context, CL_MEM_READ_ONLY, 32);
if (m_dagChunksCount == 1)
{
ETHCL_LOG("Mapping one big chunk.");
m_queue.enqueueWriteBuffer(m_dagChunks[0], CL_TRUE, 0, _dagSize, _dag);
}
else
{
// TODO Note: If we ever change to _dagChunksNum other than 4, then the size would need recalculation
void* dag_ptr[4];
for (unsigned i = 0; i < m_dagChunksCount; i++)
@ -425,7 +449,11 @@ bool ethash_cl_miner::init(
memcpy(dag_ptr[i], (char *)_dag + i*((_dagSize >> 9) << 7), (i == 3) ? (_dagSize - 3 * ((_dagSize >> 9) << 7)) : (_dagSize >> 9) << 7);
m_queue.enqueueUnmapMemObject(m_dagChunks[i], dag_ptr[i]);
}
#endif
}
// create buffer for header
ETHCL_LOG("Creating buffer for header.");
m_header = cl::Buffer(m_context, CL_MEM_READ_ONLY, 32);
// create mining buffers
for (unsigned i = 0; i != c_bufferCount; ++i)

5
libethcore/ABI.h

@ -68,5 +68,10 @@ template <class T> T abiOut(bytes const& _data)
return ABIDeserialiser<T>::deserialise(o);
}
template <class T> T abiOut(bytesConstRef& _data)
{
return ABIDeserialiser<T>::deserialise(_data);
}
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save