Browse Source

Merge pull request #2864 from ethereum/rmalethzero

Remove AlethZero; network cleanups
cl-refactor
Arkadiy Paronyan 10 years ago
parent
commit
22728e7601
  1. 1
      BuildInfo.h.in
  2. 71
      CMakeLists.txt
  3. 98
      alethzero/CMakeLists.txt
  4. 65
      alethzero/Connect.cpp
  5. 65
      alethzero/Connect.h
  6. 126
      alethzero/Connect.ui
  7. 83
      alethzero/Context.cpp
  8. 84
      alethzero/Context.h
  9. 148
      alethzero/DappHost.cpp
  10. 70
      alethzero/DappHost.h
  11. 263
      alethzero/DappLoader.cpp
  12. 111
      alethzero/DappLoader.h
  13. 384
      alethzero/Debugger.cpp
  14. 112
      alethzero/Debugger.h
  15. 300
      alethzero/Debugger.ui
  16. 201
      alethzero/DownloadView.cpp
  17. 63
      alethzero/DownloadView.h
  18. 181
      alethzero/GasPricing.ui
  19. 123
      alethzero/GetPassword.ui
  20. 106
      alethzero/GraphParameters.h
  21. 195
      alethzero/Grapher.cpp
  22. 116
      alethzero/Grapher.h
  23. 1439
      alethzero/Main.ui
  24. 104
      alethzero/MainFace.cpp
  25. 167
      alethzero/MainFace.h
  26. 2160
      alethzero/MainWin.cpp
  27. 303
      alethzero/MainWin.h
  28. 116
      alethzero/MiningView.cpp
  29. 72
      alethzero/MiningView.h
  30. 103
      alethzero/NatspecHandler.cpp
  31. 62
      alethzero/NatspecHandler.h
  32. 185
      alethzero/OurWebThreeStubServer.cpp
  33. 86
      alethzero/OurWebThreeStubServer.h
  34. 631
      alethzero/Transact.cpp
  35. 124
      alethzero/Transact.h
  36. 336
      alethzero/Transact.ui
  37. 30
      alethzero/WebPage.cpp
  38. 51
      alethzero/WebPage.h
  39. BIN
      alethzero/alethzero.icns
  40. BIN
      alethzero/alethzero.ico
  41. 1
      alethzero/alethzero.rc
  42. 12
      alethzero/main.cpp
  43. 144
      alethzero/plugins/blockchain/AllAccounts.cpp
  44. 64
      alethzero/plugins/blockchain/AllAccounts.h
  45. 137
      alethzero/plugins/blockchain/AllAccounts.ui
  46. 208
      alethzero/plugins/blockchain/ExportState.cpp
  47. 70
      alethzero/plugins/blockchain/ExportState.h
  48. 183
      alethzero/plugins/blockchain/ExportState.ui
  49. 69
      alethzero/plugins/brainwallet/BrainWallet.cpp
  50. 44
      alethzero/plugins/brainwallet/BrainWallet.h
  51. 136
      alethzero/plugins/brainwallet/BrainWallet.ui
  52. 222
      alethzero/plugins/keys/ImportKey.cpp
  53. 44
      alethzero/plugins/keys/ImportKey.h
  54. 336
      alethzero/plugins/keys/ImportKey.ui
  55. 98
      alethzero/plugins/log/LogPanel.cpp
  56. 64
      alethzero/plugins/log/LogPanel.h
  57. 99
      alethzero/plugins/log/LogPanel.ui
  58. 108
      alethzero/plugins/namers/NameRegNamer.cpp
  59. 59
      alethzero/plugins/namers/NameRegNamer.h
  60. 171
      alethzero/plugins/namers/NewAccount.cpp
  61. 56
      alethzero/plugins/namers/NewAccount.h
  62. 260
      alethzero/plugins/namers/NewAccount.ui
  63. 99
      alethzero/plugins/namers/OtherAccounts.cpp
  64. 55
      alethzero/plugins/namers/OtherAccounts.h
  65. 95
      alethzero/plugins/namers/OtherAccounts.ui
  66. 67
      alethzero/plugins/namers/OurAccounts.cpp
  67. 52
      alethzero/plugins/namers/OurAccounts.h
  68. 87
      alethzero/plugins/special/InjectTransactions.cpp
  69. 48
      alethzero/plugins/special/InjectTransactions.h
  70. 95
      alethzero/plugins/special/InjectTransactions.ui
  71. 178
      alethzero/plugins/whisper/Whisper.cpp
  72. 60
      alethzero/plugins/whisper/Whisper.h
  73. 176
      alethzero/plugins/whisper/Whisper.ui
  74. 78
      alethzero/plugins/whisper/WhisperPeers.cpp
  75. 55
      alethzero/plugins/whisper/WhisperPeers.h
  76. 32
      alethzero/plugins/whisper/WhisperPeers.ui
  77. 7
      cmake/scripts/buildinfo.cmake
  78. 4
      eth/main.cpp
  79. 7
      libdevcore/Common.h
  80. 39
      libdevcore/Log.h
  81. 1
      libethcore/BlockInfo.cpp
  82. 4
      libethereum/EthereumHost.h
  83. 58
      libp2p/Common.cpp
  84. 73
      libp2p/Common.h
  85. 52
      libp2p/Host.cpp
  86. 39
      libp2p/Host.h
  87. 18
      libp2p/NodeTable.cpp
  88. 40
      libp2p/NodeTable.h
  89. 2
      libp2p/Peer.cpp
  90. 2
      libp2p/Peer.h
  91. 4
      libp2p/RLPxHandshake.h
  92. 4
      libp2p/Session.cpp
  93. 2
      libp2p/Session.h
  94. 14
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  95. 8
      libwebthree/WebThree.cpp
  96. 26
      libwebthree/WebThree.h
  97. 14
      mix/Web3Server.cpp
  98. 4
      test/libp2p/capability.cpp
  99. 8
      test/libp2p/net.cpp
  100. 6
      test/libp2p/peer.cpp

1
BuildInfo.h.in

@ -5,3 +5,4 @@
#define ETH_CLEAN_REPO @ETH_CLEAN_REPO@ #define ETH_CLEAN_REPO @ETH_CLEAN_REPO@
#define ETH_BUILD_TYPE @ETH_BUILD_TYPE@ #define ETH_BUILD_TYPE @ETH_BUILD_TYPE@
#define ETH_BUILD_PLATFORM @ETH_BUILD_PLATFORM@ #define ETH_BUILD_PLATFORM @ETH_BUILD_PLATFORM@
#define ETH_FATDB @ETH_FATDB@

71
CMakeLists.txt

@ -242,12 +242,14 @@ function(createBuildInfo)
set(_cmake_build_type "${CMAKE_CFG_INTDIR}") set(_cmake_build_type "${CMAKE_CFG_INTDIR}")
endif() endif()
message("createBuildInfo()")
# Generate header file containing useful build information # Generate header file containing useful build information
add_custom_target(BuildInfo.h ALL add_custom_target(BuildInfo.h ALL
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND ${CMAKE_COMMAND} -DETH_SOURCE_DIR="${CMAKE_SOURCE_DIR}" -DETH_DST_DIR="${CMAKE_BINARY_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}" -DETH_BUILD_TYPE="${_cmake_build_type}" -DETH_BUILD_PLATFORM="${ETH_BUILD_PLATFORM}"
-DPROJECT_VERSION="${PROJECT_VERSION}" -DPROJECT_VERSION="${PROJECT_VERSION}" -DETH_FATDB="${FATDB}"
-P "${ETH_SCRIPTS_DIR}/buildinfo.cmake" -P "${ETH_SCRIPTS_DIR}/buildinfo.cmake"
) )
include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR})
@ -375,6 +377,7 @@ message("-- CXXFLAGS: ${CMAKE_CXX_FLAGS}")
# this must be an include, as a function it would mess up with variable scope! # this must be an include, as a function it would mess up with variable scope!
include(EthExecutableHelper) include(EthExecutableHelper)
message("creating build info...")
createBuildInfo() createBuildInfo()
if (ROCKSDB AND ROCKSDB_FOUND) if (ROCKSDB AND ROCKSDB_FOUND)
@ -504,74 +507,8 @@ if (GUI)
add_subdirectory(libnatspec) add_subdirectory(libnatspec)
add_subdirectory(libjsqrc) add_subdirectory(libjsqrc)
if (ETH_HAVE_WEBENGINE)
add_subdirectory(alethzero)
# add_subdirectory(third) // reenable once not qtwebkit.
endif()
if (SOLIDITY) if (SOLIDITY)
add_subdirectory(mix) add_subdirectory(mix)
endif () endif ()
endif() endif()
if (APPLE AND GUI)
add_custom_target(appdmg
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND ${CMAKE_COMMAND}
-DAPP_DMG_EXE=${ETH_APP_DMG}
-DAPP_DMG_FILE=appdmg.json.in
-DAPP_DMG_ICON="alethzero/alethzero.icns"
-DAPP_DMG_BACKGROUND="install-folder-bg.png"
-DETH_BUILD_DIR="${CMAKE_BINARY_DIR}"
-DETH_MIX_APP="$<TARGET_FILE_DIR:mix>"
-DETH_ALETHZERO_APP="$<TARGET_FILE_DIR:AlethZero>"
-P "${ETH_SCRIPTS_DIR}/appdmg.cmake"
)
endif ()
if (WIN32)
# packaging stuff
include(InstallRequiredSystemLibraries)
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 ${PROJECT_VERSION})
set(CPACK_GENERATOR "NSIS")
# seems to be not working
# set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/alethzero/alethzero.bmp")
# our stuff
#set(CPACK_COMPONENT_ALETHZERO_GROUP "Applications")
#set(CPACK_COMPONENT_MIX_GROUP "Applications")
#set(CPACK_COMPONENT_SOLC_GROUP "CLI")
#set(CPACK_COMPONENT_ETH_GROUP "CLI")
#set(CPACK_COMPONENT_ETHMINER_GROUP "CLI")
#set(CPACK_COMPONENT_RLP_GROUP "CLI")
#set(CPACK_COMPONENT_ABI_GROUP "CLI")
#set(CPACK_COMPONENTS_ALL alethzero mix solc eth ethminer rlp abi)
# nsis specific stuff
if (CMAKE_CL_64)
set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64")
set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION} (Win64)")
else ()
set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION}")
endif()
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")
set(CPACK_NSIS_MODIFY_PATH ON)
set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/alethzero/alethzero.ico")
set(CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}/alethzero/alethzero.ico")
include(CPack)
endif (WIN32)

98
alethzero/CMakeLists.txt

@ -1,98 +0,0 @@
cmake_policy(SET CMP0015 NEW)
# let cmake autolink dependencies on windows
cmake_policy(SET CMP0020 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)
cmake_policy(SET CMP0043 OLD)
endif()
if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.6") AND NOT APPLE)
# Supress warnings for qt headers for clang+ccache
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override")
endif ()
set(CMAKE_INCLUDE_CURRENT_DIR ON)
aux_source_directory(. SRC_LIST)
file(GLOB_RECURSE SRC_LIST "./plugins/*.cpp")
file(GLOB_RECURSE HEADERS "./plugins/*.h")
aux_source_directory(. SRC_LIST)
file(GLOB_RECURSE PLUGIN_UI RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/plugins/*.ui")
foreach(ITEM ${PLUGIN_UI})
get_filename_component(UI_NAME ${ITEM} NAME_WE)
qt5_wrap_ui(ui_${UI_NAME}.h ./${ITEM})
endforeach()
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(BEFORE ..)
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
find_package (Qt5WebEngine)
find_package (Qt5WebEngineWidgets)
if (APPLE AND (NOT "${Qt5Core_VERSION_STRING}" VERSION_LESS "5.5"))
# 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)
qt5_wrap_ui(ui_Debugger.h Debugger.ui)
qt5_wrap_ui(ui_Transact.h Transact.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)
file(GLOB HEADERS "*.h")
if (APPLE)
set(EXECUTABLE AlethZero)
else ()
set(EXECUTABLE alethzero)
endif ()
# eth_add_executable is defined in cmake/EthExecutableHelper.cmake
eth_add_executable(${EXECUTABLE}
ICON alethzero
UI_RESOURCES ${PLUGIN_UI} alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui GetPassword.ui GasPricing.ui
WIN_RESOURCES alethzero.rc
)
add_dependencies(${EXECUTABLE} BuildInfo.h)
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 AND (NOT "${Qt5Core_VERSION_STRING}" VERSION_LESS "5.5"))
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)
target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} lll)
if (SOLIDITY)
target_link_libraries(${EXECUTABLE} solidity)
endif ()
target_link_libraries(${EXECUTABLE} evmasm)
target_link_libraries(${EXECUTABLE} web3jsonrpc)
target_link_libraries(${EXECUTABLE} jsqrc)
target_link_libraries(${EXECUTABLE} natspec)
target_link_libraries(${EXECUTABLE} ${MHD_LIBRARIES})
if (SERPENT)
target_link_libraries(${EXECUTABLE} serpent)
endif()
# eth_install_executable is defined in cmake/EthExecutableHelper.cmake
eth_install_executable(${EXECUTABLE} DLLS MHD_DLLS EVMJIT_DLLS OpenCL_DLLS)

65
alethzero/Connect.cpp

@ -1,65 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Connect.cpp
* @author Alex Leverington <nessence@gmail.com>
* @date 2015
*/
#include "Connect.h"
#include <libp2p/Host.h>
#include "ui_Connect.h"
using namespace dev;
using namespace az;
Connect::Connect(QWidget *parent) :
QDialog(parent),
ui(new Ui::Connect)
{
ui->setupUi(this);
}
Connect::~Connect()
{
delete ui;
}
void Connect::setEnvironment(QStringList const& _nodes)
{
if (ui->host->count() == 0)
ui->host->addItems(_nodes);
}
void Connect::reset()
{
ui->nodeId->clear();
ui->required->setChecked(true);
}
QString Connect::host()
{
return ui->host->currentText();
}
QString Connect::nodeId()
{
return ui->nodeId->text();
}
bool Connect::required()
{
return ui->required->isChecked();
}

65
alethzero/Connect.h

@ -1,65 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Connect.h
* @author Alex Leverington <nessence@gmail.com>
* @date 2015
*/
#pragma once
#include <QDialog>
#include <QList>
namespace Ui { class Connect; }
namespace dev
{
namespace p2p { class Host; }
namespace az
{
class Connect: public QDialog
{
Q_OBJECT
public:
explicit Connect(QWidget* _parent = 0);
~Connect();
/// Populate host chooser with default host entries.
void setEnvironment(QStringList const& _nodes);
/// Clear dialogue inputs.
void reset();
/// @returns the host string, as chosen or entered by the user. Assumed to be "hostOrIP:port" (:port is optional).
QString host();
/// @returns the identity of the node, as entered by the user. Assumed to be a 64-character hex string.
QString nodeId();
/// @returns true if Required is checked by the user, indicating that the host is a required Peer.
bool required();
private:
Ui::Connect* ui;
};
}
}

126
alethzero/Connect.ui

@ -1,126 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Connect</class>
<widget class="QDialog" name="Connect">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>343</width>
<height>178</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>343</width>
<height>178</height>
</size>
</property>
<property name="windowTitle">
<string>Connect to Peer</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="1" column="0">
<layout class="QFormLayout" name="formLayout">
<item row="1" column="0" colspan="2">
<widget class="QComboBox" name="host">
<property name="minimumSize">
<size>
<width>311</width>
<height>0</height>
</size>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLineEdit" name="nodeId">
<property name="placeholderText">
<string>Node Id</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="required">
<property name="text">
<string>Required (Always Connect to this Peer)</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="formLabel">
<property name="text">
<string>Enter a peer to which a connection may be made:</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Connect</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Connect</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

83
alethzero/Context.cpp

@ -1,83 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Debugger.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "Context.h"
#include <QComboBox>
#include <QSpinBox>
#include <libethcore/Common.h>
using namespace std;
using namespace dev;
using namespace eth;
using namespace az;
NatSpecFace::~NatSpecFace()
{
}
Context::~Context()
{
}
void dev::az::setValueUnits(QComboBox* _units, QSpinBox* _value, u256 _v)
{
initUnits(_units);
if (_v > 0)
{
_units->setCurrentIndex(0);
while (_v > 50000 && _units->currentIndex() < (int)(units().size() - 2))
{
_v /= 1000;
_units->setCurrentIndex(_units->currentIndex() + 1);
}
}
else
_units->setCurrentIndex(6);
_value->setValue((unsigned)_v);
}
u256 dev::az::fromValueUnits(QComboBox* _units, QSpinBox* _value)
{
return _value->value() * units()[units().size() - 1 - _units->currentIndex()].first;
}
void dev::az::initUnits(QComboBox* _b)
{
for (auto n = (unsigned)units().size(); n-- != 0; )
_b->addItem(QString::fromStdString(units()[n].second), n);
}
vector<KeyPair> dev::az::keysAsVector(QList<KeyPair> const& keys)
{
auto list = keys.toStdList();
return {begin(list), end(list)};
}
bool dev::az::sourceIsSolidity(string const& _source)
{
// TODO: Improve this heuristic
return (_source.substr(0, 8) == "contract" || _source.substr(0, 5) == "//sol");
}
bool dev::az::sourceIsSerpent(string const& _source)
{
// TODO: Improve this heuristic
return (_source.substr(0, 5) == "//ser");
}

84
alethzero/Context.h

@ -1,84 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Debugger.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <string>
#include <vector>
#include <QString>
#include <QList>
#include <libethcore/Common.h>
class QComboBox;
class QSpinBox;
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; "
#define ETH_HTML_DIV(S) "<div style=\"" S "\">"
#define ETH_HTML_SPAN(S) "<span style=\"" S "\">"
void initUnits(QComboBox* _b);
void setValueUnits(QComboBox* _units, QSpinBox* _value, dev::u256 _v);
dev::u256 fromValueUnits(QComboBox* _units, QSpinBox* _value);
std::vector<dev::KeyPair> keysAsVector(QList<dev::KeyPair> const& _keys);
bool sourceIsSolidity(std::string const& _source);
bool sourceIsSerpent(std::string const& _source);
class NatSpecFace
{
public:
virtual ~NatSpecFace();
virtual void add(dev::h256 const& _contractHash, std::string const& _doc) = 0;
virtual std::string retrieve(dev::h256 const& _contractHash) const = 0;
virtual std::string getUserNotice(std::string const& json, const dev::bytes& _transactionData) = 0;
virtual std::string getUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionDacta) = 0;
};
class Context
{
public:
virtual ~Context();
virtual std::string pretty(dev::Address const& _a) const = 0;
virtual std::string prettyU256(dev::u256 const& _n) const = 0;
virtual std::pair<dev::Address, dev::bytes> fromString(std::string const& _a) const = 0;
virtual std::string renderDiff(dev::eth::StateDiff const& _d) const = 0;
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;
};
}
}

148
alethzero/DappHost.cpp

@ -1,148 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file DappHost.cpp
* @author Arkadiy Paronyan <arkadiy@ethdev.org>
* @date 2015
*/
#include "DappHost.h"
#include <QUrl>
#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),
m_url(QString("http://localhost:%1/").arg(m_port)),
m_threads(_threads),
m_running(false),
m_daemon(nullptr)
{
startListening();
}
DappHost::~DappHost()
{
stopListening();
}
void DappHost::startListening()
{
if(!this->m_running)
{
this->m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, this->m_port, nullptr, nullptr, &DappHost::callback, this, MHD_OPTION_THREAD_POOL_SIZE, this->m_threads, MHD_OPTION_END);
if (this->m_daemon != nullptr)
this->m_running = true;
}
}
void DappHost::stopListening()
{
if(this->m_running)
{
MHD_stop_daemon(this->m_daemon);
this->m_running = false;
}
}
void DappHost::sendOptionsResponse(MHD_Connection* _connection)
{
MHD_Response *result = MHD_create_response_from_data(0, NULL, 0, 1);
MHD_add_response_header(result, "Allow", "GET, OPTIONS");
MHD_add_response_header(result, "Access-Control-Allow-Headers", "origin, content-type, accept");
MHD_add_response_header(result, "DAV", "1");
MHD_queue_response(_connection, MHD_HTTP_OK, result);
MHD_destroy_response(result);
}
void DappHost::sendNotAllowedResponse(MHD_Connection* _connection)
{
MHD_Response *result = MHD_create_response_from_data(0, NULL, 0, 1);
MHD_add_response_header(result, "Allow", "GET, OPTIONS");
MHD_queue_response(_connection, MHD_HTTP_METHOD_NOT_ALLOWED, result);
MHD_destroy_response(result);
}
void DappHost::sendResponse(std::string const& _url, MHD_Connection* _connection)
{
QUrl requestUrl(QString::fromStdString(_url));
QString path = requestUrl.path().toLower();
if (path.isEmpty())
path = "/";
bytesConstRef response;
unsigned code = MHD_HTTP_NOT_FOUND;
std::string contentType;
while (!path.isEmpty())
{
auto iter = m_entriesByPath.find(path);
if (iter != m_entriesByPath.end())
{
ManifestEntry const* entry = iter->second;
auto contentIter = m_dapp.content.find(entry->hash);
if (contentIter == m_dapp.content.end())
break;
response = bytesConstRef(contentIter->second.data(), contentIter->second.size());
code = entry->httpStatus != 0 ? entry->httpStatus : MHD_HTTP_OK;
contentType = entry->contentType;
break;
}
path.truncate(path.length() - 1);
path = path.mid(0, path.lastIndexOf('/'));
}
MHD_Response *result = MHD_create_response_from_data(response.size(), const_cast<byte*>(response.data()), 0, 1);
if (!contentType.empty())
MHD_add_response_header(result, "Content-Type", contentType.c_str());
MHD_queue_response(_connection, code, result);
MHD_destroy_response(result);
}
int DappHost::callback(void* _cls, MHD_Connection* _connection, char const* _url, char const* _method, char const* _version, char const* _uploadData, size_t* _uploadDataSize, void** _conCls)
{
(void)_version;
(void)_uploadData;
(void)_uploadDataSize;
(void)_conCls;
DappHost* host = static_cast<DappHost*>(_cls);
if (std::string("GET") == _method)
host->sendResponse(std::string(_url), _connection);
else if (std::string("OPTIONS") == _method)
host->sendOptionsResponse(_connection);
else
host->sendNotAllowedResponse(_connection);
return MHD_YES;
}
QUrl DappHost::hostDapp(Dapp&& _dapp)
{
m_dapp = std::move(_dapp);
m_entriesByPath.clear();
for (ManifestEntry const& entry: m_dapp.manifest.entries)
m_entriesByPath[QString::fromStdString(entry.path)] = &entry;
return m_url;
}
bool DappHost::servesUrl(QUrl const& _url) const
{
return m_url == _url || m_url.isParentOf(_url);
}

70
alethzero/DappHost.h

@ -1,70 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file DappHost.h
* @author Arkadiy Paronyan <arkadiy@ethdev.org>
* @date 2015
*/
#pragma once
#include <map>
#include <QUrl>
#include <QString>
#include "DappLoader.h"
struct MHD_Daemon;
struct MHD_Connection;
namespace dev
{
namespace az
{
/// DApp web server. Servers web content, resolves paths by hashes
class DappHost
{
public:
/// @param _port Network pork to listen for incoming connections
/// @param _threads Max number of threads to process requests
DappHost(int _port, int _threads = 10);
virtual ~DappHost();
/// Load and host a dapp. Previsous dapp in discarded. Synchronous
QUrl hostDapp(Dapp&& _dapp);
/// @returns true if the given url is served from this DappHost.
bool servesUrl(QUrl const& _url) const;
private:
void startListening();
void stopListening();
void sendOptionsResponse(MHD_Connection* _connection);
void sendNotAllowedResponse(MHD_Connection* _connection);
void sendResponse(std::string const& _url, MHD_Connection* _connection);
static int callback(void* _cls, MHD_Connection* _connection, char const* _url, char const* _method, char const* _version, char const* _uploadData, size_t* _uploadDataSize, void** _conCls);
int const m_port;
QUrl const m_url;
int m_threads;
bool m_running;
MHD_Daemon* m_daemon;
Dapp m_dapp;
std::map<QString, ManifestEntry const*> m_entriesByPath;
};
}
}

263
alethzero/DappLoader.cpp

@ -1,263 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file DappLoader.cpp
* @author Arkadiy Paronyan <arkadiy@ethdev.org>
* @date 2015
*/
#include <algorithm>
#include <json/json.h>
#include <QUrl>
#include <QStringList>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QMimeDatabase>
#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/CryptoPP.h>
#include <libdevcore/SHA3.h>
#include <libethcore/CommonJS.h>
#include <libethereum/Client.h>
#include <libwebthree/WebThree.h>
#include "DappLoader.h"
using namespace dev;
using namespace az;
using namespace eth;
using namespace crypto;
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)
{
connect(&m_net, &QNetworkAccessManager::finished, this, &DappLoader::downloadComplete);
}
DappLocation DappLoader::resolveAppUri(QString const& _uri)
{
QUrl url(_uri);
if (!url.scheme().isEmpty() && url.scheme() != "eth")
throw dev::Exception(); //TODO:
QStringList parts = url.host().split('.', QString::SkipEmptyParts);
QStringList domainParts;
std::reverse(parts.begin(), parts.end());
parts.append(url.path().split('/', QString::SkipEmptyParts));
Address address = m_nameReg;
Address lastAddress;
int partIndex = 0;
h256 contentHash;
while (address && partIndex < parts.length())
{
lastAddress = address;
string32 name = ZeroString32;
QByteArray utf8 = parts[partIndex].toUtf8();
std::copy(utf8.data(), utf8.data() + utf8.size(), name.data());
if (address != m_nameReg)
address = abiOut<Address>(web3()->ethereum()->call(address, abiIn("subRegistrar(bytes32)", name)).output);
else
address = abiOut<Address>(web3()->ethereum()->call(address, abiIn("register(bytes32)", name)).output);
domainParts.append(parts[partIndex]);
if (!address)
{
//we have the address of the last part, try to get content hash
contentHash = abiOut<h256>(web3()->ethereum()->call(lastAddress, abiIn("content(bytes32)", name)).output);
if (!contentHash)
throw dev::Exception() << errinfo_comment("Can't resolve address");
}
++partIndex;
}
string32 urlHintName = ZeroString32;
QByteArray utf8 = QString("urlhint").toUtf8();
std::copy(utf8.data(), utf8.data() + utf8.size(), urlHintName.data());
Address urlHint = abiOut<Address>(web3()->ethereum()->call(m_nameReg, abiIn("addr(bytes32)", urlHintName)).output);
string32 contentUrl = abiOut<string32>(web3()->ethereum()->call(urlHint, abiIn("url(bytes32)", contentHash)).output);
QString domain = domainParts.join('/');
parts.erase(parts.begin(), parts.begin() + partIndex);
QString path = parts.join('/');
QString contentUrlString = QString::fromUtf8(std::string(contentUrl.data(), contentUrl.size()).c_str());
if (!contentUrlString.startsWith("http://") || !contentUrlString.startsWith("https://"))
contentUrlString = "http://" + contentUrlString;
return DappLocation { domain, path, contentUrlString, contentHash };
}
void DappLoader::downloadComplete(QNetworkReply* _reply)
{
QUrl requestUrl = _reply->request().url();
if (m_pageUrls.count(requestUrl) != 0)
{
//inject web3 js
QByteArray content = "<script>\n";
content.append(web3Content());
content.append(("web3.admin.setSessionKey('" + m_sessionKey + "');").c_str());
content.append("</script>\n");
content.append(_reply->readAll());
QString contentType = _reply->header(QNetworkRequest::ContentTypeHeader).toString();
if (contentType.isEmpty())
{
QMimeDatabase db;
contentType = db.mimeTypeForUrl(requestUrl).name();
}
pageReady(content, contentType, requestUrl);
return;
}
try
{
//try to interpret as rlp
QByteArray data = _reply->readAll();
_reply->deleteLater();
h256 expected = m_uriHashes[requestUrl];
bytes package(reinterpret_cast<unsigned char const*>(data.constData()), reinterpret_cast<unsigned char const*>(data.constData() + data.size()));
Secp256k1PP dec;
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(Secret(expected), package);
got = sha3(package);
if (got != expected)
throw dev::Exception() << errinfo_comment("Dapp content hash does not match");
}
RLP rlp(package);
loadDapp(rlp);
bytesRef(&package).cleanse(); // TODO: replace with bytesSec once the crypto API is up to it.
}
catch (...)
{
qWarning() << tr("Error downloading DApp: ") << boost::current_exception_diagnostic_information().c_str();
emit dappError();
}
}
void DappLoader::loadDapp(RLP const& _rlp)
{
Dapp dapp;
unsigned len = _rlp.itemCountStrict();
dapp.manifest = loadManifest(_rlp[0].toString());
for (unsigned c = 1; c < len; ++c)
{
bytesConstRef content = _rlp[c].toBytesConstRef();
h256 hash = sha3(content);
auto entry = std::find_if(dapp.manifest.entries.cbegin(), dapp.manifest.entries.cend(), [=](ManifestEntry const& _e) { return _e.hash == hash; });
if (entry != dapp.manifest.entries.cend())
{
if (entry->path == "/deployment.js")
{
//inject web3 code
bytes b(web3Content().data(), web3Content().data() + web3Content().size());
b.insert(b.end(), content.begin(), content.end());
dapp.content[hash] = b;
}
else
dapp.content[hash] = content.toBytes();
}
else
throw dev::Exception() << errinfo_comment("Dapp content hash does not match");
}
emit dappReady(dapp);
}
QByteArray const& DappLoader::web3Content()
{
if (m_web3Js.isEmpty())
{
QString code;
code += contentsOfQResource(":/js/bignumber.min.js");
code += "\n";
code += contentsOfQResource(":/js/webthree.js");
code += "\n";
code += contentsOfQResource(":/js/setup.js");
code += "\n";
code += contentsOfQResource(":/js/admin.js");
code += "\n";
m_web3Js = code.toLatin1();
}
return m_web3Js;
}
Manifest DappLoader::loadManifest(std::string const& _manifest)
{
/// https://github.com/ethereum/go-ethereum/wiki/URL-Scheme
Manifest manifest;
Json::Reader jsonReader;
Json::Value root;
jsonReader.parse(_manifest, root, false);
Json::Value entries = root["entries"];
for (Json::ValueIterator it = entries.begin(); it != entries.end(); ++it)
{
Json::Value const& entryValue = *it;
std::string path = entryValue["path"].asString();
if (path.size() == 0 || path[0] != '/')
path = "/" + path;
std::string contentType = entryValue["contentType"].asString();
std::string strHash = entryValue["hash"].asString();
if (strHash.length() == 64)
strHash = "0x" + strHash;
h256 hash = jsToFixed<32>(strHash);
unsigned httpStatus = entryValue["status"].asInt();
manifest.entries.push_back(ManifestEntry{ path, hash, contentType, httpStatus });
}
return manifest;
}
void DappLoader::loadDapp(QString const& _uri)
{
QUrl uri(_uri);
QUrl contentUri;
h256 hash;
if (uri.path().endsWith(".dapp") && uri.query().startsWith("hash="))
{
contentUri = uri;
QString query = uri.query();
query.remove("hash=");
if (!query.startsWith("0x"))
query.insert(0, "0x");
hash = jsToFixed<32>(query.toStdString());
}
else
{
DappLocation location = resolveAppUri(_uri);
contentUri = location.contentUri;
hash = location.contentHash;
uri = contentUri;
}
QNetworkRequest request(contentUri);
m_uriHashes[uri] = hash;
m_net.get(request);
}
void DappLoader::loadPage(QString const& _uri)
{
QUrl uri(_uri);
QNetworkRequest request(uri);
m_pageUrls.insert(uri);
m_net.get(request);
}

111
alethzero/DappLoader.h

@ -1,111 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file DappLoader.h
* @author Arkadiy Paronyan <arkadiy@ethdev.org>
* @date 2015
*/
#pragma once
#include <map>
#include <string>
#include <vector>
#include <QObject>
#include <QString>
#include <QUrl>
#include <QNetworkAccessManager>
#include <libdevcore/FixedHash.h>
#include <libdevcrypto/Common.h>
namespace dev
{
class WebThreeDirect;
class RLP;
namespace az
{
struct ManifestEntry
{
std::string path;
dev::h256 hash;
std::string contentType;
unsigned httpStatus;
};
struct Manifest
{
std::vector<ManifestEntry> entries;
};
struct Dapp
{
Manifest manifest;
std::map<dev::h256, dev::bytes> content;
};
struct DappLocation
{
QString canonDomain;
QString path;
QString contentUri;
dev::h256 contentHash;
};
///Downloads, unpacks and prepares DApps for hosting
class DappLoader: public QObject
{
Q_OBJECT
public:
DappLoader(QObject* _parent, dev::WebThreeDirect* _web3, dev::Address _nameReg);
///Load a new DApp. Resolves a name with a name reg contract. Asynchronous. dappReady is emitted once everything is read, dappError othervise
///@param _uri Eth name path
void loadDapp(QString const& _uri);
///Load a regular html page
///@param _uri Page Uri
void loadPage(QString const& _uri);
void setSessionKey(std::string const& _s) { m_sessionKey = _s; }
signals:
void dappReady(Dapp& _dapp);
void pageReady(QByteArray const& _content, QString const& _mimeType, QUrl const& _uri);
void dappError();
private slots:
void downloadComplete(QNetworkReply* _reply);
private:
dev::WebThreeDirect* web3() const { return m_web3; }
DappLocation resolveAppUri(QString const& _uri);
void loadDapp(dev::RLP const& _rlp);
Manifest loadManifest(std::string const& _manifest);
QByteArray const& web3Content();
dev::WebThreeDirect* m_web3;
QNetworkAccessManager m_net;
std::map<QUrl, dev::h256> m_uriHashes;
std::set<QUrl> m_pageUrls;
QByteArray m_web3Js;
dev::Address m_nameReg;
std::string m_sessionKey;
};
}
}

384
alethzero/Debugger.cpp

@ -1,384 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Debugger.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "Debugger.h"
#include <fstream>
#include <QFileDialog>
#include <libevm/VM.h>
#include <libethereum/ExtVM.h>
#include <libethereum/Executive.h>
#include "ui_Debugger.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
Debugger::Debugger(Context* _c, QWidget* _parent):
QDialog(_parent),
ui(new Ui::Debugger),
m_context(_c)
{
ui->setupUi(this);
}
Debugger::~Debugger()
{
delete ui;
}
void Debugger::init()
{
if (m_session.history.size())
{
alterDebugStateGroup(true);
ui->debugCode->setEnabled(false);
ui->debugTimeline->setMinimum(0);
ui->debugTimeline->setMaximum(m_session.history.size());
ui->debugTimeline->setValue(0);
}
}
void Debugger::populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction)
{
finished();
if (m_session.populate(_executive, _transaction))
init();
update();
}
bool DebugSession::populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction)
{
try {
_executive.initialize(_transaction);
if (_executive.execute())
return false;
}
catch (...)
{
// Invalid transaction
return false;
}
vector<WorldState const*> levels;
bytes lastExtCode;
bytesConstRef lastData;
h256 lastHash;
h256 lastDataHash;
auto onOp = [&](uint64_t steps, Instruction inst, bigint newMemSize, bigint gasCost, bigint gas, VM* voidVM, ExtVMFace const* voidExt)
{
VM& vm = *voidVM;
ExtVM const& ext = *static_cast<ExtVM const*>(voidExt);
if (ext.code != lastExtCode)
{
lastExtCode = ext.code;
lastHash = sha3(lastExtCode);
if (!codes.count(lastHash))
codes[lastHash] = ext.code;
}
if (ext.data != lastData)
{
lastData = ext.data;
lastDataHash = sha3(lastData);
if (!codes.count(lastDataHash))
codes[lastDataHash] = ext.data.toBytes();
}
if (levels.size() < ext.depth)
levels.push_back(&history.back());
else
levels.resize(ext.depth);
history.append(WorldState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, static_cast<u256>(gas), lastHash, lastDataHash, vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels}));
};
_executive.go(onOp);
_executive.finalize();
return true;
}
void Debugger::finished()
{
m_session = DebugSession();
ui->callStack->clear();
ui->debugCode->clear();
ui->debugStack->clear();
ui->debugMemory->setHtml("");
ui->debugStorage->setHtml("");
ui->debugStateInfo->setText("");
alterDebugStateGroup(false);
}
void Debugger::update()
{
if (m_session.history.size())
{
WorldState const& nws = m_session.history[min((int)m_session.history.size() - 1, ui->debugTimeline->value())];
WorldState const& ws = ui->callStack->currentRow() > 0 ? *nws.levels[nws.levels.size() - ui->callStack->currentRow()] : nws;
if (ui->debugTimeline->value() >= m_session.history.size())
{
if (ws.gasCost > ws.gas)
ui->debugMemory->setHtml("<h3>OUT-OF-GAS</h3>");
else if (ws.inst == Instruction::RETURN && ws.stack.size() >= 2)
{
unsigned from = (unsigned)ws.stack.back();
unsigned size = (unsigned)ws.stack[ws.stack.size() - 2];
unsigned o = 0;
bytes out(size, 0);
for (; o < size && from + o < ws.memory.size(); ++o)
out[o] = ws.memory[from + o];
ui->debugMemory->setHtml("<h3>RETURN</h3>" + QString::fromStdString(dev::memDump(out, 16, true)));
}
else if (ws.inst == Instruction::STOP)
ui->debugMemory->setHtml("<h3>STOP</h3>");
else if (ws.inst == Instruction::SUICIDE && ws.stack.size() >= 1)
ui->debugMemory->setHtml("<h3>SUICIDE</h3>0x" + QString::fromStdString(toString(right160(ws.stack.back()))));
else
ui->debugMemory->setHtml("<h3>EXCEPTION</h3>");
ostringstream ss;
ss << dec << "EXIT | GAS: " << dec << max<dev::bigint>(0, (dev::bigint)ws.gas - ws.gasCost);
ui->debugStateInfo->setText(QString::fromStdString(ss.str()));
ui->debugStorage->setHtml("");
ui->debugCallData->setHtml("");
m_session.currentData = h256();
ui->callStack->clear();
m_session.currentLevels.clear();
ui->debugCode->clear();
m_session.currentCode = h256();
ui->debugStack->setHtml("");
}
else
{
if (m_session.currentLevels != nws.levels || !ui->callStack->count())
{
m_session.currentLevels = nws.levels;
ui->callStack->clear();
for (unsigned i = 0; i <= nws.levels.size(); ++i)
{
WorldState const& s = i ? *nws.levels[nws.levels.size() - i] : nws;
ostringstream out;
out << s.cur.abridged();
if (i)
out << " " << instructionInfo(s.inst).name << " @0x" << hex << s.curPC;
ui->callStack->addItem(QString::fromStdString(out.str()));
}
}
if (ws.code != m_session.currentCode)
{
m_session.currentCode = ws.code;
bytes const& code = m_session.codes[ws.code];
QListWidget* dc = ui->debugCode;
dc->clear();
m_session.pcWarp.clear();
for (unsigned i = 0; i <= code.size(); ++i)
{
byte b = i < code.size() ? code[i] : 0;
try
{
QString s = QString::fromStdString(instructionInfo((Instruction)b).name);
ostringstream out;
out << hex << setw(4) << setfill('0') << i;
m_session.pcWarp[i] = dc->count();
if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32)
{
unsigned bc = b - (byte)Instruction::PUSH1 + 1;
s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&code[i + 1], bc)));
i += bc;
}
dc->addItem(QString::fromStdString(out.str()) + " " + s);
}
catch (...)
{
cerr << "Unhandled exception!" << endl << boost::current_exception_diagnostic_information();
break; // probably hit data segment
}
}
}
if (ws.callData != m_session.currentData)
{
m_session.currentData = ws.callData;
if (ws.callData)
{
assert(m_session.codes.count(ws.callData));
ui->debugCallData->setHtml(QString::fromStdString(dev::memDump(m_session.codes[ws.callData], 16, true)));
}
else
ui->debugCallData->setHtml("");
}
QString stack;
for (auto i: ws.stack)
stack.prepend("<div>" + QString::fromStdString(m_context->prettyU256(i)) + "</div>");
ui->debugStack->setHtml(stack);
ui->debugMemory->setHtml(QString::fromStdString(dev::memDump(ws.memory, 16, true)));
assert(m_session.codes.count(ws.code));
if (m_session.codes[ws.code].size() >= (unsigned)ws.curPC)
{
int l = m_session.pcWarp[(unsigned)ws.curPC];
ui->debugCode->setCurrentRow(max(0, l - 5));
ui->debugCode->setCurrentRow(min(ui->debugCode->count() - 1, l + 5));
ui->debugCode->setCurrentRow(l);
}
else
cwarn << "PC (" << (unsigned)ws.curPC << ") is after code range (" << m_session.codes[ws.code].size() << ")";
ostringstream ss;
ss << dec << "STEP: " << ws.steps << " | PC: 0x" << hex << ws.curPC << " : " << instructionInfo(ws.inst).name << " | ADDMEM: " << dec << ws.newMemSize << " words | COST: " << dec << ws.gasCost << " | GAS: " << dec << ws.gas;
ui->debugStateInfo->setText(QString::fromStdString(ss.str()));
stringstream s;
auto keys = dev::keysOf(ws.storage);
sort(keys.begin(), keys.end());
for (auto const& key: keys)
s << "@" << m_context->prettyU256(key) << "&nbsp;&nbsp;&nbsp;&nbsp;" << m_context->prettyU256(ws.storage.at(key)) << "<br/>";
ui->debugStorage->setHtml(QString::fromStdString(s.str()));
}
}
}
void Debugger::on_callStack_currentItemChanged()
{
update();
}
void Debugger::alterDebugStateGroup(bool _enable) const
{
ui->stepOver->setEnabled(_enable);
ui->stepInto->setEnabled(_enable);
ui->stepOut->setEnabled(_enable);
ui->backOver->setEnabled(_enable);
ui->backInto->setEnabled(_enable);
ui->backOut->setEnabled(_enable);
ui->dump->setEnabled(_enable);
ui->dumpStorage->setEnabled(_enable);
ui->dumpPretty->setEnabled(_enable);
}
void Debugger::on_debugTimeline_valueChanged()
{
update();
}
void Debugger::on_stepOver_clicked()
{
if (ui->debugTimeline->value() < m_session.history.size()) {
auto l = m_session.history[ui->debugTimeline->value()].levels.size();
if ((ui->debugTimeline->value() + 1) < m_session.history.size() && m_session.history[ui->debugTimeline->value() + 1].levels.size() > l)
{
on_stepInto_clicked();
if (m_session.history[ui->debugTimeline->value()].levels.size() > l)
on_stepOut_clicked();
}
else
on_stepInto_clicked();
}
}
void Debugger::on_stepInto_clicked()
{
ui->debugTimeline->setValue(ui->debugTimeline->value() + 1);
ui->callStack->setCurrentRow(0);
}
void Debugger::on_stepOut_clicked()
{
if (ui->debugTimeline->value() < m_session.history.size())
{
auto ls = m_session.history[ui->debugTimeline->value()].levels.size();
auto l = ui->debugTimeline->value();
for (; l < m_session.history.size() && m_session.history[l].levels.size() >= ls; ++l) {}
ui->debugTimeline->setValue(l);
ui->callStack->setCurrentRow(0);
}
}
void Debugger::on_backInto_clicked()
{
ui->debugTimeline->setValue(ui->debugTimeline->value() - 1);
ui->callStack->setCurrentRow(0);
}
void Debugger::on_backOver_clicked()
{
auto l = m_session.history[ui->debugTimeline->value()].levels.size();
if (ui->debugTimeline->value() > 0 && m_session.history[ui->debugTimeline->value() - 1].levels.size() > l)
{
on_backInto_clicked();
if (m_session.history[ui->debugTimeline->value()].levels.size() > l)
on_backOut_clicked();
}
else
on_backInto_clicked();
}
void Debugger::on_backOut_clicked()
{
if (ui->debugTimeline->value() > 0 && m_session.history.size() > 0)
{
auto ls = m_session.history[min(ui->debugTimeline->value(), m_session.history.size() - 1)].levels.size();
int l = ui->debugTimeline->value();
for (; l > 0 && m_session.history[l].levels.size() >= ls; --l) {}
ui->debugTimeline->setValue(l);
ui->callStack->setCurrentRow(0);
}
}
void Debugger::on_dump_clicked()
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace");
ofstream f(fn.toStdString());
if (f.is_open())
for (WorldState const& ws: m_session.history)
f << ws.cur << " " << hex << toHex(dev::toCompactBigEndian(ws.curPC, 1)) << " " << hex << toHex(dev::toCompactBigEndian((unsigned)(byte)ws.inst, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)ws.gas, 1)) << endl;
}
void Debugger::on_dumpPretty_clicked()
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace");
ofstream f(fn.toStdString());
if (f.is_open())
for (WorldState const& ws: m_session.history)
{
f << endl << " STACK" << endl;
for (auto i: ws.stack)
f << (h256)i << endl;
f << " MEMORY" << endl << dev::memDump(ws.memory);
f << " STORAGE" << endl;
for (auto const& i: ws.storage)
f << showbase << hex << i.first << ": " << i.second << endl;
f << dec << ws.levels.size() << " | " << ws.cur << " | #" << ws.steps << " | " << hex << setw(4) << setfill('0') << ws.curPC << " : " << instructionInfo(ws.inst).name << " | " << dec << ws.gas << " | -" << dec << ws.gasCost << " | " << ws.newMemSize << "x32";
}
}
void Debugger::on_dumpStorage_clicked()
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace");
ofstream f(fn.toStdString());
if (f.is_open())
for (WorldState const& ws: m_session.history)
{
if (ws.inst == Instruction::STOP || ws.inst == Instruction::RETURN || ws.inst == Instruction::SUICIDE)
for (auto i: ws.storage)
f << toHex(dev::toCompactBigEndian(i.first, 1)) << " " << toHex(dev::toCompactBigEndian(i.second, 1)) << endl;
f << ws.cur << " " << hex << toHex(dev::toCompactBigEndian(ws.curPC, 1)) << " " << hex << toHex(dev::toCompactBigEndian((unsigned)(byte)ws.inst, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)ws.gas, 1)) << endl;
}
}

112
alethzero/Debugger.h

@ -1,112 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Debugger.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <libdevcore/RLP.h>
#include <libethcore/Common.h>
#include <libethereum/State.h>
#include <libethereum/Executive.h>
#include <QDialog>
#include <QMap>
#include <QList>
#include "Context.h"
namespace Ui { class Debugger; }
namespace dev
{
namespace az
{
struct WorldState
{
uint64_t steps;
dev::Address cur;
dev::u256 curPC;
dev::eth::Instruction inst;
dev::bigint newMemSize;
dev::u256 gas;
dev::h256 code;
dev::h256 callData;
dev::u256s stack;
dev::bytes memory;
dev::bigint gasCost;
std::unordered_map<dev::u256, dev::u256> storage;
std::vector<WorldState const*> levels;
};
struct DebugSession
{
DebugSession() {}
bool populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction);
dev::h256 currentCode;
dev::h256 currentData;
std::vector<WorldState const*> currentLevels;
QMap<unsigned, unsigned> pcWarp;
QList<WorldState> history;
std::map<dev::u256, dev::bytes> codes;
};
class Debugger: public QDialog
{
Q_OBJECT
public:
explicit Debugger(Context* _context, QWidget* _parent = 0);
~Debugger();
void populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction);
protected slots:
void on_callStack_currentItemChanged();
void on_debugTimeline_valueChanged();
void on_stepOver_clicked();
void on_stepInto_clicked();
void on_stepOut_clicked();
void on_backOver_clicked();
void on_backInto_clicked();
void on_backOut_clicked();
void on_dump_clicked();
void on_dumpPretty_clicked();
void on_dumpStorage_clicked();
void on_close_clicked() { close(); }
private:
void init();
void update();
void finished();
void alterDebugStateGroup(bool _enable) const;
Ui::Debugger* ui;
DebugSession m_session;
Context* m_context;
};
}
}

300
alethzero/Debugger.ui

@ -1,300 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Debugger</class>
<widget class="QDialog" name="Debugger">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>989</width>
<height>690</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<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="QToolButton" name="stepOver">
<property name="text">
<string>Step Over</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="stepInto">
<property name="text">
<string>Step Into</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="stepOut">
<property name="text">
<string>Step Out</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="backOver">
<property name="text">
<string>Back Over</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="backInto">
<property name="text">
<string>Back Into</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="backOut">
<property name="text">
<string>Back Out</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>
</layout>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QSplitter" name="splitter_42">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QListWidget" name="debugCode">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
<widget class="QListWidget" name="callStack">
<property name="font">
<font>
<family>Ubuntu Mono</family>
</font>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</widget>
<widget class="QSplitter" name="splitter_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QTextEdit" name="debugStack">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
<widget class="QTextEdit" name="debugMemory">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
<widget class="QTextEdit" name="debugStorage">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
<widget class="QTextEdit" name="debugCallData">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</widget>
</item>
<item>
<widget class="QLabel" name="debugStateInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="debugTimeline">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<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="QToolButton" name="dump">
<property name="text">
<string>Dump</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="dumpStorage">
<property name="text">
<string>Dump Storage</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="dumpPretty">
<property name="text">
<string>Dump Pretty</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>577</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="close">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

201
alethzero/DownloadView.cpp

@ -1,201 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file DownloadView.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "DownloadView.h"
#include <QtWidgets>
#include <QtCore>
#include <libethereum/DownloadMan.h>
#include "Grapher.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
SyncView::SyncView(QWidget* _p): QWidget(_p)
{
}
void SyncView::paintEvent(QPaintEvent*)
{
QPainter painter(this);
painter.fillRect(rect(), Qt::white);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setRenderHint(QPainter::HighQualityAntialiasing, true);
if (!m_client || !isVisible() || !rect().width() || !rect().height())
return;
DownloadMan const* man = m_client->downloadMan();
BlockQueueStatus bqs = m_client->blockQueueStatus();
SyncStatus sync = m_client->syncStatus();
unsigned syncFrom = m_client->numberFromHash(PendingBlockHash);
unsigned syncImported = syncFrom;
unsigned syncImporting = syncImported + bqs.importing;
unsigned syncVerified = syncImporting + bqs.verified;
unsigned syncVerifying = syncVerified + bqs.verifying;
unsigned syncUnverified = syncVerifying + bqs.unverified;
unsigned syncCount = syncUnverified + bqs.unknown - syncFrom;
// best effort guess. assumes there's no forks.
unsigned downloadFrom = sync.state == SyncState::Idle ? m_lastSyncFrom : m_client->numberFromHash(m_client->isKnown(man->firstBlock()) ? man->firstBlock() : PendingBlockHash);
unsigned downloadCount = sync.state == SyncState::Idle ? m_lastSyncCount : sync.blocksTotal;
unsigned downloadDone = downloadFrom + (sync.state == SyncState::Idle ? m_lastSyncCount : sync.blocksReceived);
unsigned downloadPoint = downloadFrom + (sync.state == SyncState::Idle ? m_lastSyncCount : man->overview().lastComplete);
unsigned hashFrom = sync.state == SyncState::Hashes ? m_client->numberFromHash(PendingBlockHash) : downloadFrom;
unsigned hashCount = sync.state == SyncState::Hashes ? sync.hashesTotal : downloadCount;
unsigned hashDone = hashFrom + (sync.state == SyncState::Hashes ? sync.hashesReceived : hashCount);
QString labelText = QString("PV%1").arg(sync.protocolVersion);
QColor labelBack = QColor::fromHsv(sync.protocolVersion == 60 ? 30 : sync.protocolVersion == 61 ? 120 : 240, 25, 200);
QColor labelFore = labelBack.darker();
switch (sync.state)
{
case SyncState::Hashes:
if (!syncCount || !sync.hashesEstimated)
{
m_lastSyncFrom = min(hashFrom, m_lastSyncFrom);
m_lastSyncCount = max(hashFrom + hashCount, m_lastSyncFrom + m_lastSyncCount) - m_lastSyncFrom;
m_wasEstimate = sync.hashesEstimated;
}
break;
case SyncState::Blocks:
if (m_wasEstimate)
{
m_lastSyncFrom = downloadFrom;
m_lastSyncCount = downloadCount;
m_wasEstimate = false;
}
break;
case SyncState::Idle:
if (!syncCount)
{
m_lastSyncFrom = (unsigned)-1;
m_lastSyncCount = 0;
labelBack = QColor::fromHsv(0, 0, 200);
labelFore = Qt::white;
labelText = "Idle";
}
default: break;
}
unsigned from = min(min(hashFrom, downloadFrom), min(syncFrom, m_lastSyncFrom));
unsigned count = max(max(hashFrom + hashCount, downloadFrom + downloadCount), max(syncFrom + syncCount, m_lastSyncFrom + m_lastSyncCount)) - from;
/* cnote << "Range " << from << "-" << (from + count) << "(" << hashFrom << "+" << hashCount << "," << downloadFrom << "+" << downloadCount << "," << syncFrom << "+" << syncCount << ")";
auto r = [&](unsigned u) {
return toString((u - from) * 100 / count) + "%";
};
if (count)
{
cnote << "Hashes:" << r(hashDone) << " Blocks:" << r(downloadFlank) << r(downloadDone) << r(downloadPoint);
cnote << "Importing:" << r(syncFrom) << r(syncImported) << r(syncImporting) << r(syncVerified) << r(syncVerifying) << r(syncUnverified);
}
*/
float const squareSize = min(rect().width(), rect().height());
auto middleRect = [&](float w, float h) {
return QRectF(rect().width() / 2 - w / 2, rect().height() / 2 - h / 2, w, h);
};
auto middle = [&](float x) {
return middleRect(squareSize * x, squareSize * x);
};
auto pieProgress = [&](unsigned h, unsigned s, unsigned v, float row, float thickness, unsigned nfrom, unsigned ncount) {
auto arcLen = [&](unsigned x) {
return x * -5760.f / count;
};
auto arcPos = [&](unsigned x) {
return int(90 * 16.f + arcLen(x - from)) % 5760;
};
painter.setPen(QPen(QColor::fromHsv(h, s, v), squareSize * thickness, Qt::SolidLine, Qt::FlatCap));
painter.setBrush(Qt::NoBrush);
painter.drawArc(middle(0.5 + row / 2), arcPos(nfrom), arcLen(ncount));
};
auto pieProgress2 = [&](unsigned h, unsigned s, unsigned v, float row, float orbit, float thickness, unsigned nfrom, unsigned ncount) {
pieProgress(h, s, v, row - orbit, thickness, nfrom, ncount);
pieProgress(h, s, v, row + orbit, thickness, nfrom, ncount);
};
auto pieLabel = [&](QString text, float points, QColor fore, QColor back) {
painter.setBrush(QBrush(back));
painter.setFont(QFont("Helvetica", points, QFont::Bold));
QRectF r = painter.boundingRect(middle(1.f), Qt::AlignCenter, text);
r.adjust(-r.width() / 4, -r.height() / 8, r.width() / 4, r.height() / 8);
painter.setPen(QPen(fore, r.height() / 20));
painter.drawRoundedRect(r, r.height() / 4, r.height() / 4);
painter.drawText(r, Qt::AlignCenter, text);
};
float lineHeight = painter.boundingRect(rect(), Qt::AlignTop | Qt::AlignHCenter, "Ay").height();
auto hProgress = [&](unsigned h, unsigned s, unsigned v, float row, float thickness, unsigned nfrom, unsigned ncount) {
QRectF r = rect();
painter.setPen(QPen(QColor::fromHsv(h, s, v), r.height() * thickness * 3, Qt::SolidLine, Qt::FlatCap));
painter.setBrush(Qt::NoBrush);
auto y = row * (r.height() - lineHeight) + lineHeight;
painter.drawLine(QPointF((nfrom - from) * r.width() / count, y), QPointF((nfrom + ncount - from) * r.width() / count, y));
};
auto hProgress2 = [&](unsigned h, unsigned s, unsigned v, float row, float orbit, float thickness, unsigned nfrom, unsigned ncount) {
hProgress(h, s, v, row - orbit * 3, thickness, nfrom, ncount);
hProgress(h, s, v, row + orbit * 3, thickness, nfrom, ncount);
};
auto hLabel = [&](QString text, float points, QColor fore, QColor back) {
painter.setBrush(QBrush(back));
painter.setFont(QFont("Helvetica", points, QFont::Bold));
QRectF r = painter.boundingRect(rect(), Qt::AlignTop | Qt::AlignHCenter, text);
r.adjust(-r.width() / 4, r.height() / 8, r.width() / 4, 3 * r.height() / 8);
painter.setPen(QPen(fore, r.height() / 20));
painter.drawRoundedRect(r, r.height() / 4, r.height() / 4);
painter.drawText(r, Qt::AlignCenter, text);
};
function<void(unsigned h, unsigned s, unsigned v, float row, float thickness, unsigned nfrom, unsigned ncount)> progress;
function<void(unsigned h, unsigned s, unsigned v, float row, float orbit, float thickness, unsigned nfrom, unsigned ncount)> progress2;
function<void(QString text, float points, QColor fore, QColor back)> label;
if (rect().width() / rect().height() > 5)
{
progress = hProgress;
progress2 = hProgress2;
label = hLabel;
}
else
{
progress = pieProgress;
progress2 = pieProgress2;
label = pieLabel;
}
if (sync.state != SyncState::Idle)
{
progress(0, 0, 220, 0.4f, 0.02f, from, hashDone - from); // Download rail
progress(240, 25, 170, 0.4f, 0.02f, downloadDone, downloadPoint - downloadDone); // Latest download point
progress(240, 50, 120, 0.4f, 0.04f, from, downloadDone - from); // Downloaded
}
progress(0, 0, 220, 0.8f, 0.01f, from, count); // Sync rail
progress(0, 0, 170, 0.8f, 0.02f, from, syncUnverified - from); // Verification rail
progress2(60, 25, 170, 0.8f, 0.06f, 0.005f, from, syncVerifying - from); // Verifying.
progress2(120, 25, 170, 0.8f, 0.06f, 0.005f, from, syncVerified - from); // Verified.
progress(120, 50, 120, 0.8f, 0.05f, from, syncFrom - from); // Imported.
progress(0, 0, 120, 0.8f, 0.02f, syncFrom, syncImporting - syncFrom); // Importing.
if (sync.state != SyncState::Idle || (sync.state == SyncState::Idle && !syncCount))
label(labelText, 11, labelFore, labelBack);
}

63
alethzero/DownloadView.h

@ -1,63 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file DownloadView.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#ifdef Q_MOC_RUN
#define BOOST_MPL_IF_HPP_INCLUDED
#endif
#include <list>
#include <QtWidgets/QWidget>
#ifndef Q_MOC_RUN
#include <libethereum/Client.h>
#endif
namespace dev
{
namespace eth { class Client; }
namespace az
{
class SyncView: public QWidget
{
Q_OBJECT
public:
SyncView(QWidget* _p = nullptr);
void setEthereum(dev::eth::Client const* _c) { m_client = _c; }
protected:
virtual void paintEvent(QPaintEvent*);
private:
dev::eth::Client const* m_client = nullptr;
unsigned m_lastSyncFrom = (unsigned)-1;
unsigned m_lastSyncCount = 0;
bool m_wasEstimate = false;
};
}
}

181
alethzero/GasPricing.ui

@ -1,181 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GasPricing</class>
<widget class="QDialog" name="GasPricing">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>416</width>
<height>286</height>
</rect>
</property>
<property name="windowTitle">
<string>Gas Pricing</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>398</width>
<height>45</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="label5_3">
<property name="text">
<string>&amp;Bid: The minimum grice of gas that is accepting into a block which we mine.</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="buddy">
<cstring>bidValue</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QSpinBox" name="askValue">
<property name="suffix">
<string/>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="10" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<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="close">
<property name="text">
<string>Close</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label5_2">
<property name="text">
<string>&amp;Ask: The minimum grice of gas that is accepting into a block which we mine.</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="buddy">
<cstring>askValue</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="askUnits"/>
</item>
<item row="5" column="0">
<widget class="QSpinBox" name="bidValue">
<property name="suffix">
<string/>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="bidUnits"/>
</item>
<item row="7" column="0" colspan="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="9" column="0" colspan="2">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="8" column="0" colspan="2">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>close</sender>
<signal>clicked()</signal>
<receiver>GasPricing</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>387</x>
<y>264</y>
</hint>
<hint type="destinationlabel">
<x>240</x>
<y>262</y>
</hint>
</hints>
</connection>
</connections>
</ui>

123
alethzero/GetPassword.ui

@ -1,123 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GetPassword</class>
<widget class="QDialog" name="GetPassword">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>187</height>
</rect>
</property>
<property name="windowTitle">
<string>Enter Password</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLineEdit" name="entry">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>GetPassword</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>GetPassword</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

106
alethzero/GraphParameters.h

@ -1,106 +0,0 @@
/* BEGIN COPYRIGHT
*
* This file is part of Noted.
*
* Copyright ©2011, 2012, Lancaster Logic Response Limited.
*
* Noted 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 2 of the License, or
* (at your option) any later version.
*
* Noted 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 Noted. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <algorithm>
#include <type_traits>
#include <cmath>
#undef foreach
#define foreach BOOST_FOREACH
namespace lb
{
template <class T>
static T graphParameters(T _min, T _max, unsigned _divisions, T* o_from = 0, T* o_delta = 0, bool _forceMinor = false, T _divisor = 1)
{
T uMin = _min / _divisor;
T uMax = _max / _divisor;
if (uMax == uMin || !_divisions)
{
if (o_delta && o_from)
{
*o_from = 0;
*o_delta = 1;
}
return 1;
}
long double l10 = std::log10((uMax - uMin) / T(_divisions) * 5.5f);
long double mt = std::pow(10.f, l10 - std::floor(l10));
long double ep = std::pow(10.f, std::floor(l10));
T inc = _forceMinor
? ((mt > 6.f) ? ep / 2.f : (mt > 3.f) ? ep / 5.f : (mt > 1.2f) ? ep / 10.f : ep / 20.f)
: ((mt > 6.f) ? ep * 2.f : (mt > 3.f) ? ep : (mt > 1.2f) ? ep / 2.f : ep / 5.f);
if (inc == 0)
inc = 1;
if (o_delta && o_from)
{
(*o_from) = std::floor(uMin / inc) * inc * _divisor;
(*o_delta) = (std::ceil(uMax / inc) - std::floor(uMin / inc)) * inc * _divisor;
}
else if (o_from)
{
(*o_from) = std::ceil(uMin / inc) * inc * _divisor;
}
return inc * _divisor;
}
struct GraphParametersForceMinor { GraphParametersForceMinor() {} };
static const GraphParametersForceMinor ForceMinor;
template <class T>
struct GraphParameters
{
inline GraphParameters(std::pair<T, T> _range, unsigned _divisions)
{
incr = graphParameters(_range.first, _range.second, _divisions, &from, &delta, false);
to = from + delta;
}
inline GraphParameters(std::pair<T, T> _range, unsigned _divisions, GraphParametersForceMinor)
{
incr = graphParameters(_range.first, _range.second, _divisions, &from, &delta, true);
to = from + delta;
}
inline GraphParameters(std::pair<T, T> _range, unsigned _divisions, T _divisor)
{
major = graphParameters(_range.first, _range.second, _divisions, &from, &delta, false, _divisor);
incr = graphParameters(_range.first, _range.second, _divisions, &from, &delta, true, _divisor);
to = from + delta;
}
template <class S, class Enable = void>
struct MajorDeterminor { static bool go(S _s, S _j) { S ip; S fp = std::modf(_s / _j + S(0.5), &ip); return fabs(fabs(fp) - 0.5) < 0.05; } };
template <class S>
struct MajorDeterminor<S, typename std::enable_if<std::is_integral<S>::value>::type> { static S go(S _s, S _j) { return _s % _j == 0; } };
bool isMajor(T _t) const { return MajorDeterminor<T>::go(_t, major); }
T from;
T delta;
T major;
T to;
T incr;
};
}

195
alethzero/Grapher.cpp

@ -1,195 +0,0 @@
/* BEGIN COPYRIGHT
*
* This file is part of Noted.
*
* Copyright ©2011, 2012, Lancaster Logic Response Limited.
*
* Noted 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 2 of the License, or
* (at your option) any later version.
*
* Noted 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 Noted. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QtGui/QPainter>
#include "GraphParameters.h"
#include "Grapher.h"
using namespace std;
using namespace lb;
void Grapher::init(QPainter* _p, std::pair<float, float> _xRange, std::pair<float, float> _yRange, std::function<std::string(float)> _xLabel, std::function<std::string(float)> _yLabel, std::function<std::string(float, float)> _pLabel, int _leftGutter, int _bottomGutter)
{
fontPixelSize = QFontInfo(QFont("Ubuntu", 10)).pixelSize();
if (_leftGutter)
_leftGutter = max<int>(_leftGutter, fontPixelSize * 2);
if (_bottomGutter)
_bottomGutter = max<int>(_bottomGutter, fontPixelSize * 1.25);
QRect a(_leftGutter, 0, _p->viewport().width() - _leftGutter, _p->viewport().height() - _bottomGutter);
init(_p, _xRange, _yRange, _xLabel, _yLabel, _pLabel, a);
}
bool Grapher::drawAxes(bool _x, bool _y) const
{
int w = active.width();
int h = active.height();
int l = active.left();
int r = active.right();
int t = active.top();
int b = active.bottom();
p->setFont(QFont("Ubuntu", 10));
p->fillRect(p->viewport(), qRgb(255, 255, 255));
static const int c_markLength = 2;
static const int c_markSpacing = 2;
static const int c_xSpacing = fontPixelSize * 3;
static const int c_ySpacing = fontPixelSize * 1.25;
if (w < c_xSpacing || h < c_ySpacing || !p->viewport().contains(active))
return false;
if (_y)
{
GraphParameters<float> yParams(yRange, h / c_ySpacing, 1.f);
float dy = fabs(yRange.second - yRange.first);
if (dy > .001)
for (float f = yParams.from; f < yParams.to; f += yParams.incr)
{
int y = b - h * (f - yParams.from) / dy;
if (yParams.isMajor(f))
{
p->setPen(QColor(208, 208, 208));
p->drawLine(l - c_markLength, y, r, y);
if (l > p->viewport().left())
{
p->setPen(QColor(144, 144, 144));
p->drawText(QRect(0, y - c_ySpacing / 2, l - c_markLength - c_markSpacing, c_ySpacing), Qt::AlignRight|Qt::AlignVCenter, QString::fromStdString(yLabel(round(f * 100000) / 100000)));
}
}
else
{
p->setPen(QColor(236, 236, 236));
p->drawLine(l, y, r, y);
}
}
p->setPen(QColor(192,192,192));
p->drawLine(l - c_markSpacing, b, r, b);
}
if (_x)
{
GraphParameters<float> xParams(xRange, w / c_xSpacing, 1.f);
float dx = fabs(xRange.second - xRange.first);
for (float f = xParams.from; f < xParams.to; f += xParams.incr)
{
int x = l + w * (f - xParams.from) / dx;
if (xParams.isMajor(f))
{
p->setPen(QColor(208, 208, 208));
p->drawLine(x, t, x, b + c_markLength);
if (b < p->viewport().bottom())
{
p->setPen(QColor(144, 144, 144));
p->drawText(QRect(x - c_xSpacing / 2, b + c_markLength + c_markSpacing, c_xSpacing, p->viewport().height() - (b + c_markLength + c_markSpacing)), Qt::AlignHCenter|Qt::AlignTop, QString::fromStdString(xLabel(f)));
}
}
else
{
p->setPen(QColor(236, 236, 236));
p->drawLine(x, t, x, b);
}
}
}
p->setClipRect(active);
return true;
}
void Grapher::drawLineGraph(vector<float> const& _data, QColor _color, QBrush const& _fillToZero, float _width) const
{
int s = _data.size();
QPoint l;
for (int i = 0; i < s; ++i)
{
int zy = yP(0.f);
QPoint h(xTP(i), yTP(_data[i]));
if (i)
{
if (_fillToZero != Qt::NoBrush)
{
p->setPen(Qt::NoPen);
p->setBrush(_fillToZero);
p->drawPolygon(QPolygon(QVector<QPoint>() << QPoint(h.x(), zy) << h << l << QPoint(l.x(), zy)));
}
p->setPen(QPen(_color, _width));
p->drawLine(QLine(l, h));
}
l = h;
}
}
void Grapher::ruleY(float _x, QColor _color, float _width) const
{
p->setPen(QPen(_color, _width));
p->drawLine(xTP(_x), active.top(), xTP(_x), active.bottom());
}
void Grapher::drawLineGraph(std::function<float(float)> const& _f, QColor _color, QBrush const& _fillToZero, float _width) const
{
QPoint l;
for (int x = active.left(); x < active.right(); x += 2)
{
int zy = yP(0.f);
QPoint h(x, yTP(_f(xRU(x))));
if (x != active.left())
{
if (_fillToZero != Qt::NoBrush)
{
p->setPen(Qt::NoPen);
p->setBrush(_fillToZero);
p->drawPolygon(QPolygon(QVector<QPoint>() << QPoint(h.x(), zy) << h << l << QPoint(l.x(), zy)));
}
p->setPen(QPen(_color, _width));
p->drawLine(QLine(l, h));
}
l = h;
}
}
void Grapher::labelYOrderedPoints(map<float, float> const& _data, int _maxCount, float _minFactor) const
{
int ly = active.top() + 6;
int pc = 0;
if (_data.empty())
return;
float smallestAllowed = prev(_data.end())->first * _minFactor;
for (auto peaki = _data.rbegin(); peaki != _data.rend(); ++peaki)
if ((peaki->first > smallestAllowed || _minFactor == 0) && pc < _maxCount)
{
auto peak = *peaki;
int x = xTP(peak.second);
int y = yTP(peak.first);
p->setPen(QColor::fromHsvF(float(pc) / _maxCount, 1.f, 0.5f, 0.5f));
p->drawEllipse(QPoint(x, y), 4, 4);
p->drawLine(x, y - 4, x, ly + 6);
QString f = QString::fromStdString(pLabel(xT(peak.second), yT(peak.first)));
int fw = p->fontMetrics().width(f);
p->drawLine(x + 16 + fw + 2, ly + 6, x, ly + 6);
p->setPen(QColor::fromHsvF(0, 0.f, .35f));
p->fillRect(QRect(x+12, ly-6, fw + 8, 12), QBrush(QColor(255, 255, 255, 160)));
p->drawText(QRect(x+16, ly-6, 160, 12), Qt::AlignVCenter, f);
ly += 14;
++pc;
}
}

116
alethzero/Grapher.h

@ -1,116 +0,0 @@
/* BEGIN COPYRIGHT
*
* This file is part of Noted.
*
* Copyright ©2011, 2012, Lancaster Logic Response Limited.
*
* Noted 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 2 of the License, or
* (at your option) any later version.
*
* Noted 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 Noted. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <map>
#include <vector>
#include <string>
#include <utility>
#include <functional>
#include <QtGui/QBrush>
#include <QtCore/QRect>
class QPainter;
namespace lb
{
class Grapher
{
public:
Grapher(): p(0) {}
void init(QPainter* _p, std::pair<float, float> _xRange, std::pair<float, float> _yRange, std::function<std::string(float _f)> _xLabel, std::function<std::string(float _f)> _yLabel, std::function<std::string(float, float)> _pLabel, int _leftGutter = 30, int _bottomGutter = 16);
void init(QPainter* _p, std::pair<float, float> _xRange, std::pair<float, float> _yRange, std::function<std::string(float _f)> _xLabel, std::function<std::string(float _f)> _yLabel, std::function<std::string(float, float)> _pLabel, QRect _active)
{
p = _p;
active = _active;
xRange = _xRange;
yRange = _yRange;
dx = xRange.second - xRange.first;
dy = yRange.second - yRange.first;
xLabel = _xLabel;
yLabel = _yLabel;
pLabel = _pLabel;
}
void setDataTransform(float _xM, float _xC, float _yM, float _yC)
{
xM = _xM;
xC = _xC;
yM = _yM;
yC = _yC;
}
void setDataTransform(float _xM, float _xC)
{
xM = _xM;
xC = _xC;
yM = 1.f;
yC = 0.f;
}
void resetDataTransform() { xM = yM = 1.f; xC = yC = 0.f; }
bool drawAxes(bool _x = true, bool _y = true) const;
void drawLineGraph(std::vector<float> const& _data, QColor _color = QColor(128, 128, 128), QBrush const& _fillToZero = Qt::NoBrush, float _width = 0.f) const;
void drawLineGraph(std::function<float(float)> const& _f, QColor _color = QColor(128, 128, 128), QBrush const& _fillToZero = Qt::NoBrush, float _width = 0.f) const;
void ruleX(float _y, QColor _color = QColor(128, 128, 128), float _width = 0.f) const;
void ruleY(float _x, QColor _color = QColor(128, 128, 128), float _width = 0.f) const;
void labelYOrderedPoints(std::map<float, float> const& _translatedData, int _maxCount = 20, float _minFactor = .01f) const;
protected:
QPainter* p = nullptr;
QRect active;
std::pair<float, float> xRange;
std::pair<float, float> yRange;
float xM = 0;
float xC = 0;
float yM = 0;
float yC = 0;
float dx = 0;
float dy = 0;
std::function<std::string(float _f)> xLabel;
std::function<std::string(float _f)> yLabel;
std::function<std::string(float _x, float _y)> pLabel;
float fontPixelSize = 0;
// Translate from raw indexed data into x/y graph units. Only relevant for indexed data.
float xT(float _dataIndex) const { return _dataIndex * xM + xC; }
float yT(float _dataValue) const { return _dataValue * yM + yC; }
// Translate from x/y graph units to widget pixels.
int xP(float _xUnits) const { return active.left() + (_xUnits - xRange.first) / dx * active.width(); }
int yP(float _yUnits) const { return active.bottom() - (_yUnits - yRange.first) / dy * active.height(); }
QPoint P(float _x, float _y) const { return QPoint(xP(_x), yP(_y)); }
// Translate direcly from raw indexed data to widget pixels.
int xTP(float _dataIndex) const { return active.left() + (xT(_dataIndex) - xRange.first) / dx * active.width(); }
int yTP(float _dataValue) const { return active.bottom() - (yT(_dataValue) - yRange.first) / dy * active.height(); }
// Translate back from pixels into graph units.
float xU(int _xPixels) const { return float(_xPixels - active.left()) / active.width() * dx + xRange.first; }
// Translate back from graph units into raw data index.
float xR(float _xUnits) const { return (_xUnits - xC) / xM; }
// Translate directly from pixels into raw data index. xRU(xTP(X)) == X
float xRU(int _xPixels) const { return xR(xU(_xPixels)); }
};
}

1439
alethzero/Main.ui

File diff suppressed because it is too large

104
alethzero/MainFace.cpp

@ -1,104 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MainFace.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include <QMenu>
#include "MainFace.h"
using namespace std;
using namespace dev;
using namespace az;
void AccountNamer::noteKnownChanged()
{
if (m_main)
m_main->noteKnownAddressesChanged(this);
}
void AccountNamer::noteNamesChanged()
{
if (m_main)
m_main->noteAddressNamesChanged(this);
}
void MainFace::notePlugin(std::function<Plugin*(MainFace*)> const& _new)
{
if (!s_linkedPlugins)
s_linkedPlugins = new std::vector<std::function<Plugin*(MainFace*)>>();
s_linkedPlugins->push_back(_new);
}
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_dock->setObjectName(_title);
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);
}
QAction* Plugin::addMenuItem(QString _n, QString _menuName, bool _sep)
{
QAction* a = new QAction(_n, main());
QMenu* m = main()->findChild<QMenu*>(_menuName);
if (_sep)
m->addSeparator();
m->addAction(a);
return a;
}
std::vector<std::function<Plugin*(MainFace*)>>* MainFace::s_linkedPlugins = nullptr;
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();
}

167
alethzero/MainFace.h

@ -1,167 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <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
{
#ifndef _MSC_VER // MSVC does not like gcc compiler attributes
#define DEV_AZ_NOTE_PLUGIN(ClassName) \
static bool s_notePlugin __attribute__((unused)) = [](){ MainFace::notePlugin([](MainFace* m){ return new ClassName(m); }); return true; }()
#else
#define DEV_AZ_NOTE_PLUGIN(ClassName) \
static bool s_notePlugin = [](){ MainFace::notePlugin([](MainFace* m){ return new ClassName(m); }); return true; }()
#endif
class Plugin;
class MainFace;
class Main;
class OurWebThreeStubServer;
using WatchHandler = std::function<void(dev::eth::LocalisedLogEntries const&)>;
class AccountNamer
{
friend class Main;
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(); }
protected:
void noteKnownChanged();
void noteNamesChanged();
private:
MainFace* m_main = nullptr;
};
class MainFace: public QMainWindow, public Context
{
Q_OBJECT
public:
explicit MainFace(QWidget* _parent = nullptr): QMainWindow(_parent) {}
static void notePlugin(std::function<Plugin*(MainFace*)> const& _new);
void adoptPlugin(Plugin* _p);
void killPlugins();
void allChange();
using Context::render;
// 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 OurWebThreeStubServer* web3Server() 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;
virtual void uninstallWatch(unsigned _id) = 0;
// Account naming API
virtual void install(AccountNamer* _adopt) = 0;
virtual void uninstall(AccountNamer* _kill) = 0;
virtual void noteKnownAddressesChanged(AccountNamer*) = 0;
virtual void noteAddressNamesChanged(AccountNamer*) = 0;
virtual Address toAddress(std::string const&) const = 0;
virtual std::string toName(Address const&) const = 0;
virtual Addresses allKnownAddresses() const = 0;
virtual void noteSettingsChanged() = 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; }
static std::vector<std::function<Plugin*(MainFace*)>>* s_linkedPlugins;
signals:
void knownAddressesChanged();
void addressNamesChanged();
void keyManagerChanged();
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() const { 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);
QAction* addMenuItem(QString _name, QString _menuName, bool _separate = false);
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;
};
class AccountNamerPlugin: public Plugin, public AccountNamer
{
protected:
AccountNamerPlugin(MainFace* _m, std::string const& _name): Plugin(_m, _name) { main()->install(this); }
~AccountNamerPlugin() { main()->uninstall(this); }
};
}
}

2160
alethzero/MainWin.cpp

File diff suppressed because it is too large

303
alethzero/MainWin.h

@ -1,303 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MainWin.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#ifdef Q_MOC_RUN
#define BOOST_MPL_IF_HPP_INCLUDED
#endif
#include <map>
#include <QtNetwork/QNetworkAccessManager>
#include <QtCore/QAbstractListModel>
#include <QtCore/QMutex>
#include <QtWidgets/QMainWindow>
#include <libdevcore/RLP.h>
#include <libethcore/Common.h>
#include <libethcore/KeyManager.h>
#include <libethereum/State.h>
#include <libethereum/Executive.h>
#include <libwebthree/WebThree.h>
#include <libsolidity/CompilerStack.h>
#include "Context.h"
#include "Transact.h"
#include "NatspecHandler.h"
#include "Connect.h"
#include "MainFace.h"
class QListWidgetItem;
class QActionGroup;
namespace Ui {
class Main;
}
namespace jsonrpc {
class HttpServer;
}
class QWebEnginePage;
namespace dev
{
namespace eth
{
class Client;
class State;
}
namespace az
{
class OurWebThreeStubServer;
class DappLoader;
class DappHost;
struct Dapp;
QString contentsOfQResource(std::string const& res);
class Main: public MainFace
{
Q_OBJECT
public:
explicit Main(QWidget *parent = 0);
~Main();
WebThreeDirect* web3() const override { return m_webThree.get(); }
OurWebThreeStubServer* web3Server() const override { return m_server.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(u256 const& _n) const override;
std::string render(dev::Address const& _a) const override;
std::pair<Address, bytes> fromString(std::string const& _a) const override;
std::string renderDiff(eth::StateDiff const& _d) const override;
u256 gasPrice() const override;
eth::KeyManager& keyManager() override { return m_keyManager; }
void noteKeysChanged() override { refreshBalances(); }
bool doConfirm();
Secret retrieveSecret(Address const& _address) const override;
// Account naming API.
void install(AccountNamer* _adopt) override;
void uninstall(AccountNamer* _kill) override;
void noteKnownAddressesChanged(AccountNamer*) override;
void noteAddressNamesChanged(AccountNamer*) override;
Address toAddress(std::string const&) const override;
std::string toName(Address const&) const override;
Addresses allKnownAddresses() const override;
void noteSettingsChanged() override { writeSettings(); }
public slots:
void load(QString _file);
void note(QString _entry);
void debug(QString _entry);
void warn(QString _entry);
QString contents(QString _file);
int authenticate(QString _title, QString _text);
void onKeysChanged();
private slots:
void eval(QString const& _js);
void addConsoleMessage(QString const& _js, QString const& _s);
// Application
void on_about_triggered();
void on_quit_triggered() { close(); }
// Network
void on_go_triggered();
void on_net_triggered();
void on_connect_triggered();
void on_idealPeers_valueChanged(int);
// Mining
void on_mine_triggered();
void on_prepNextDAG_triggered();
// View
void on_refresh_triggered();
void on_showAll_triggered() { refreshBlockChain(); }
void on_preview_triggered();
// Account management
void on_killAccount_triggered();
void on_importKey_triggered();
void on_reencryptKey_triggered();
void on_reencryptAll_triggered();
void on_importKeyFile_triggered();
void on_claimPresale_triggered();
void on_importPresale_triggered();
void on_exportKey_triggered();
// Tools
void on_newTransaction_triggered();
void on_loadJS_triggered();
// Stuff concerning the blocks/transactions/accounts panels
void on_ourAccounts_itemClicked(QListWidgetItem* _i);
void on_ourAccounts_doubleClicked();
void on_transactionQueue_currentItemChanged();
void on_blockChainFilter_textChanged();
void on_blocks_currentItemChanged();
// Misc
void on_urlEdit_returnPressed();
void on_jsInput_returnPressed();
void on_nameReg_textChanged();
// Special (debug) stuff
void on_paranoia_triggered();
void on_killBlockchain_triggered();
void on_clearPending_triggered();
void on_injectBlock_triggered();
void on_forceMining_triggered();
void on_usePrivate_triggered();
void on_turboMining_triggered();
void on_retryUnknown_triggered();
void on_vmInterpreter_triggered();
void on_vmJIT_triggered();
void on_vmSmart_triggered();
void on_rewindChain_triggered();
// Debugger
void on_debugCurrent_triggered();
void on_debugPending_triggered();
void on_debugDumpState_triggered() { debugDumpState(1); }
void on_debugDumpStatePre_triggered() { debugDumpState(0); }
void on_dumpBlockState_triggered();
// Config
void on_gasPrices_triggered();
void on_sentinel_triggered();
void refreshBlockChain();
// Dapps
void dappLoaded(Dapp& _dapp); //qt does not support rvalue refs for signals
void pageLoaded(QByteArray const& _content, QString const& _mimeType, QUrl const& _uri);
signals:
void poll();
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);
p2p::NetworkPreferences netPrefs() const;
QString lookup(QString const& _n) const;
Address getNameReg() const;
Address getCurrencies() const;
void updateFee();
void readSettings(bool _skipGeometry = false, bool _onlyGeometry = false);
void writeSettings();
void setPrivateChain(QString const& _private, bool _forceConfigure = false);
unsigned installWatch(eth::LogFilter const& _tf, WatchHandler const& _f) override;
unsigned installWatch(h256 const& _tf, WatchHandler const& _f) override;
void uninstallWatch(unsigned _w) override;
void keysChanged();
void onNewPending();
void onNewBlock();
void onNameRegChange();
void onCurrenciesChange();
void onBalancesChange();
void installWatches();
void installCurrenciesWatch();
void installNameRegWatch();
void installBalancesWatch();
virtual void timerEvent(QTimerEvent*) override;
void refreshNetwork();
void refreshMining();
void refreshCache();
void refreshAll();
void refreshPending();
void refreshBlockCount();
void refreshBalances();
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<WebThreeDirect> m_webThree;
std::map<unsigned, WatchHandler> m_handlers;
unsigned m_nameRegFilter = (unsigned)-1;
unsigned m_currenciesFilter = (unsigned)-1;
unsigned m_balancesFilter = (unsigned)-1;
QByteArray m_networkConfig;
QStringList m_servers;
eth::KeyManager m_keyManager;
QString m_privateChain;
dev::Address m_nameReg;
dev::Address m_beneficiary;
QActionGroup* m_vmSelectionGroup = nullptr;
QList<QPair<QString, QString>> m_consoleHistory;
std::unique_ptr<jsonrpc::HttpServer> m_httpConnector;
std::unique_ptr<OurWebThreeStubServer> m_server;
static std::string fromRaw(h256 const& _n, unsigned* _inc = nullptr);
NatspecHandler m_natSpecDB;
Transact* m_transact;
std::unique_ptr<DappHost> m_dappHost;
DappLoader* m_dappLoader;
QWebEnginePage* m_webPage;
Connect m_connect;
std::unordered_set<AccountNamer*> m_namers;
bool m_destructing = false;
};
}
}

116
alethzero/MiningView.cpp

@ -1,116 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MiningView.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "MiningView.h"
#include <QtWidgets>
#include <QtCore>
#include <libethereum/Client.h>
#include "Grapher.h"
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;
using dev::eth::MineInfo;
using dev::eth::WorkingProgress;
using dev::toString;
using dev::trimFront;
string id(float _y) { return toString(_y); }
string s(float _x){ return toString(round(_x * 1000) / 1000) + (!_x ? "s" : ""); }
string sL(float _x, float _y) { return toString(round(_x * 1000)) + "s (" + toString(_y) + ")"; }
MiningView::MiningView(QWidget* _p): QWidget(_p)
{
}
void MiningView::appendStats(list<MineInfo> const& _i, WorkingProgress const& _p)
{
(void)_p;
if (_i.empty())
return;
/* unsigned o = m_values.size();
for (MineInfo const& i: _i)
{
m_values.push_back(i.best);
m_lastBest = min(m_lastBest, i.best);
m_bests.push_back(m_lastBest);
m_reqs.push_back(i.requirement);
if (i.completed)
{
m_completes.push_back(o);
m_resets.push_back(o);
m_haveReset = false;
m_lastBest = 1e99;
}
++o;
}
if (m_haveReset)
{
m_resets.push_back(o - 1);
m_lastBest = 1e99;
m_haveReset = false;
}
o = max<int>(0, (int)m_values.size() - (int)m_duration);
trimFront(m_values, o);
trimFront(m_bests, o);
trimFront(m_reqs, o);
for (auto& i: m_resets)
i -= o;
m_resets.erase(remove_if(m_resets.begin(), m_resets.end(), [](int i){return i < 0;}), m_resets.end());
for (auto& i: m_completes)
i -= o;
m_completes.erase(remove_if(m_completes.begin(), m_completes.end(), [](int i){return i < 0;}), m_completes.end());
m_progress = _p;
update();*/
}
void MiningView::resetStats()
{
m_haveReset = true;
}
void MiningView::paintEvent(QPaintEvent*)
{
/*
Grapher g;
QPainter p(this);
g.init(&p, make_pair(0.f, max((float)m_duration * 0.1f, (float)m_values.size() * 0.1f)), make_pair(0.0f, 255.f - ((float)m_progress.requirement - 4.0f)), s, id, sL);
g.drawAxes();
g.setDataTransform(0.1f, 0, -1.0f, 255.f);
g.drawLineGraph(m_values, QColor(192, 192, 192));
g.drawLineGraph(m_bests, QColor(128, 128, 128));
g.drawLineGraph(m_reqs, QColor(128, 64, 64));
for (auto r: m_resets)
g.ruleY(r - 1, QColor(128, 128, 128));
for (auto r: m_completes)
g.ruleY(r, QColor(192, 64, 64));
*/
}

72
alethzero/MiningView.h

@ -1,72 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MiningView.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#ifdef Q_MOC_RUN
#define BOOST_MPL_IF_HPP_INCLUDED
#endif
#include <list>
#include <QtWidgets/QWidget>
#ifndef Q_MOC_RUN
#include <libethereum/Client.h>
#endif
namespace dev
{
namespace eth
{
struct MineInfo;
}
namespace az
{
class MiningView: public QWidget
{
Q_OBJECT
public:
MiningView(QWidget* _p = nullptr);
void appendStats(std::list<dev::eth::MineInfo> const& _l, dev::eth::WorkingProgress const& _p);
void resetStats();
protected:
virtual void paintEvent(QPaintEvent*);
private:
dev::eth::WorkingProgress m_progress;
unsigned m_duration = 300;
std::vector<float> m_values;
std::vector<float> m_bests;
std::vector<float> m_reqs;
std::vector<int> m_resets;
std::vector<int> m_completes;
double m_lastBest = 1e31;
bool m_haveReset = false;
};
}
}

103
alethzero/NatspecHandler.cpp

@ -1,103 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file NatspecHandler.cpp
* @author Lefteris Karapetsas <lefteris@ethdev.com>
* @date 2015
*/
#include "NatspecHandler.h"
#include <string>
#include <boost/filesystem.hpp>
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/Exceptions.h>
#include <libdevcore/Log.h>
#include <libdevcore/SHA3.h>
#include <libethereum/Defaults.h>
using namespace dev;
using namespace az;
using namespace eth;
using namespace std;
namespace fs = boost::filesystem;
NatspecHandler::NatspecHandler()
{
string path = Defaults::dbPath();
fs::create_directories(path);
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);
}
NatspecHandler::~NatspecHandler()
{
delete m_db;
}
void NatspecHandler::add(dev::h256 const& _contractHash, string const& _doc)
{
m_db->Put(m_writeOptions, _contractHash.ref(), _doc);
cdebug << "Registering NatSpec: " << _contractHash << _doc;
}
string NatspecHandler::retrieve(dev::h256 const& _contractHash) const
{
string ret;
m_db->Get(m_readOptions, _contractHash.ref(), &ret);
cdebug << "Looking up NatSpec: " << _contractHash << ret;
return ret;
}
string NatspecHandler::getUserNotice(string const& json, dev::bytes const& _transactionData)
{
Json::Value natspec;
Json::Value userNotice;
m_reader.parse(json, natspec);
FixedHash<4> transactionFunctionHash((bytesConstRef(&_transactionData).cropped(0, 4).toBytes()));
Json::Value methods = natspec["methods"];
for (Json::ValueIterator it = methods.begin(); it != methods.end(); ++it)
{
Json::Value keyValue = it.key();
if (!keyValue.isString())
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Illegal Natspec JSON detected"));
string functionSig = keyValue.asString();
FixedHash<4> functionHash(dev::sha3(functionSig));
if (functionHash == transactionFunctionHash)
{
Json::Value val = (*it)["notice"];
if (!val.isString())
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Illegal Natspec JSON detected"));
return val.asString();
}
}
// not found
return string();
}
string NatspecHandler::getUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionData)
{
return getUserNotice(retrieve(_contractHash), _transactionData);
}

62
alethzero/NatspecHandler.h

@ -1,62 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file NatspecHandler.h
* @author Lefteris Karapetsas <lefteris@ethdev.com>
* @date 2015
*/
#pragma once
#include <libdevcore/db.h>
#include <json/json.h>
#include <libdevcore/FixedHash.h>
#include "Context.h"
namespace dev
{
namespace az
{
class NatspecHandler: public NatSpecFace
{
public:
NatspecHandler();
~NatspecHandler();
/// Stores locally in a levelDB a key value pair of contract code hash to natspec documentation
virtual void add(dev::h256 const& _contractHash, std::string const& _doc) override;
/// Retrieves the natspec documentation as a string given a contract code hash
std::string retrieve(dev::h256 const& _contractHash) const override;
/// Given a json natspec string and the transaction data return the user notice
virtual std::string getUserNotice(std::string const& json, const dev::bytes& _transactionData) override;
/// Given a contract code hash and the transaction's data retrieve the natspec documention's
/// user notice for that transaction.
/// @returns The user notice or an empty string if no natspec for the contract exists
/// or if the existing natspec does not document the @c _methodName
virtual std::string getUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionDacta) override;
private:
ldb::ReadOptions m_readOptions;
ldb::WriteOptions m_writeOptions;
ldb::DB* m_db = nullptr;
Json::Reader m_reader;
};
}
}

185
alethzero/OurWebThreeStubServer.cpp

@ -1,185 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file OurWebThreeStubServer.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "OurWebThreeStubServer.h"
#include <QMessageBox>
#include <QAbstractButton>
#include <libwebthree/WebThree.h>
#include <libnatspec/NatspecExpressionEvaluator.h>
#include "MainWin.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
OurWebThreeStubServer::OurWebThreeStubServer(
jsonrpc::AbstractServerConnector& _conn,
Main* _main
):
WebThreeStubServer(_conn, *_main->web3(), make_shared<OurAccountHolder>(_main), vector<KeyPair>{}, _main->keyManager(), *static_cast<TrivialGasPricer*>(_main->ethereum()->gasPricer().get())),
m_main(_main)
{
}
string OurWebThreeStubServer::shh_newIdentity()
{
KeyPair kp = dev::KeyPair::create();
emit onNewId(QString::fromStdString(toJS(kp.sec())));
return toJS(kp.pub());
}
OurAccountHolder::OurAccountHolder(Main* _main):
AccountHolder([=](){ return _main->ethereum(); }),
m_main(_main)
{
connect(_main, SIGNAL(poll()), this, SLOT(doValidations()));
}
bool OurAccountHolder::showAuthenticationPopup(string const& _title, string const& _text)
{
if (!m_main->confirm())
{
cnote << "Skipping confirmation step for: " << _title << "\n" << _text;
return true;
}
QMessageBox userInput;
userInput.setText(QString::fromStdString(_title));
userInput.setInformativeText(QString::fromStdString(_text));
userInput.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
userInput.button(QMessageBox::Ok)->setText("Allow");
userInput.button(QMessageBox::Cancel)->setText("Reject");
userInput.setDefaultButton(QMessageBox::Cancel);
return userInput.exec() == QMessageBox::Ok;
//QMetaObject::invokeMethod(m_main, "authenticate", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, button), Q_ARG(QString, QString::fromStdString(_title)), Q_ARG(QString, QString::fromStdString(_text)));
//return button == QMessageBox::Ok;
}
bool OurAccountHolder::showCreationNotice(TransactionSkeleton const& _t, bool _toProxy)
{
return showAuthenticationPopup("Contract Creation Transaction", string("ÐApp is attemping to create a contract; ") + (_toProxy ? "(this transaction is not executed directly, but forwarded to another ÐApp) " : "") + "to be endowed with " + formatBalance(_t.value) + ", with additional network fees of up to " + formatBalance(_t.gas * _t.gasPrice) + ".\n\nMaximum total cost is " + formatBalance(_t.value + _t.gas * _t.gasPrice) + ".");
}
bool OurAccountHolder::showSendNotice(TransactionSkeleton const& _t, bool _toProxy)
{
return showAuthenticationPopup("Fund Transfer Transaction", "ÐApp is attempting to send " + formatBalance(_t.value) + " to a recipient " + m_main->pretty(_t.to) + (_toProxy ? " (this transaction is not executed directly, but forwarded to another ÐApp)" : "") +
", with additional network fees of up to " + formatBalance(_t.gas * _t.gasPrice) + ".\n\nMaximum total cost is " + formatBalance(_t.value + _t.gas * _t.gasPrice) + ".");
}
bool OurAccountHolder::showUnknownCallNotice(TransactionSkeleton const& _t, bool _toProxy)
{
return showAuthenticationPopup("DANGEROUS! Unknown Contract Transaction!",
"ÐApp is attempting to call into an unknown contract at address " +
m_main->pretty(_t.to) + ".\n\n" +
(_toProxy ? "This transaction is not executed directly, but forwarded to another ÐApp.\n\n" : "") +
"Call involves sending " +
formatBalance(_t.value) + " to the recipient, with additional network fees of up to " +
formatBalance(_t.gas * _t.gasPrice) +
"However, this also does other stuff which we don't understand, and does so in your name.\n\n" +
"WARNING: This is probably going to cost you at least " +
formatBalance(_t.value + _t.gas * _t.gasPrice) +
", however this doesn't include any side-effects, which could be of far greater importance.\n\n" +
"REJECT UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!");
}
h256 OurAccountHolder::authenticate(TransactionSkeleton const& _t)
{
Guard l(x_queued);
m_queued.push(_t);
return h256();
}
void OurAccountHolder::doValidations()
{
Guard l(x_queued);
while (!m_queued.empty())
{
auto t = m_queued.front();
m_queued.pop();
bool proxy = isProxyAccount(t.from);
if (!proxy && !isRealAccount(t.from))
{
cwarn << "Trying to send from non-existant account" << t.from;
return;
}
// TODO: determine gas price.
if (!validateTransaction(t, proxy))
return;
if (proxy)
queueTransaction(t);
else
// sign and submit.
if (Secret s = m_main->retrieveSecret(t.from))
m_main->ethereum()->submitTransaction(t, s);
}
}
AddressHash OurAccountHolder::realAccounts() const
{
return m_main->keyManager().accountsHash();
}
bool OurAccountHolder::validateTransaction(TransactionSkeleton const& _t, bool _toProxy)
{
if (!m_main->doConfirm())
return true;
if (_t.creation)
{
// show notice concerning the creation code. TODO: this needs entering into natspec.
return showCreationNotice(_t, _toProxy);
}
h256 contractCodeHash = m_main->ethereum()->postState().codeHash(_t.to);
if (contractCodeHash == EmptySHA3)
{
// recipient has no code - nothing special about this transaction, show basic value transfer info
return showSendNotice(_t, _toProxy);
}
string userNotice = m_main->natSpec()->getUserNotice(contractCodeHash, _t.data);
if (userNotice.empty())
return showUnknownCallNotice(_t, _toProxy);
NatspecExpressionEvaluator evaluator;
userNotice = evaluator.evalExpression(QString::fromStdString(userNotice)).toStdString();
// otherwise it's a transaction to a contract for which we have the natspec
return showAuthenticationPopup("Contract Transaction",
"ÐApp attempting to conduct contract interaction with " +
m_main->pretty(_t.to) +
": <b>" + userNotice + "</b>.\n\n" +
(_toProxy ? "This transaction is not executed directly, but forwarded to another ÐApp.\n\n" : "") +
(_t.value > 0 ?
"In addition, ÐApp is attempting to send " +
formatBalance(_t.value) + " to said recipient, with additional network fees of up to " +
formatBalance(_t.gas * _t.gasPrice) + " = " +
formatBalance(_t.value + _t.gas * _t.gasPrice) + "."
:
"Additional network fees are at most" +
formatBalance(_t.gas * _t.gasPrice) + ".")
);
}

86
alethzero/OurWebThreeStubServer.h

@ -1,86 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file OurWebThreeStubServer.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include <queue>
#include <QtCore/QObject>
#include <libdevcore/Guards.h>
#include <libethcore/CommonJS.h>
#include <libdevcrypto/Common.h>
#include <libweb3jsonrpc/WebThreeStubServer.h>
#include <libweb3jsonrpc/AccountHolder.h>
namespace dev
{
namespace az
{
class Main;
class OurAccountHolder: public QObject, public eth::AccountHolder
{
Q_OBJECT
public:
OurAccountHolder(Main* _main);
public slots:
void doValidations();
protected:
// easiest to return keyManager.addresses();
virtual dev::AddressHash realAccounts() const override;
// use web3 to submit a signed transaction to accept
virtual dev::h256 authenticate(dev::eth::TransactionSkeleton const& _t) override;
private:
bool showAuthenticationPopup(std::string const& _title, std::string const& _text);
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(eth::TransactionSkeleton const& _t, bool _toProxy);
std::queue<eth::TransactionSkeleton> m_queued;
Mutex x_queued;
Main* m_main;
};
class OurWebThreeStubServer: public QObject, public WebThreeStubServer
{
Q_OBJECT
public:
OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, Main* main);
virtual std::string shh_newIdentity() override;
signals:
void onNewId(QString _s);
private:
Main* m_main;
};
}
}

631
alethzero/Transact.cpp

@ -1,631 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Transact.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
// Make sure boost/asio.hpp is included before windows.h.
#include <boost/asio.hpp>
#include "Transact.h"
#include <fstream>
#include <boost/algorithm/string.hpp>
#include <QFileDialog>
#include <QMessageBox>
#include <QClipboard>
#include <liblll/Compiler.h>
#include <liblll/CodeFragment.h>
#if ETH_SOLIDITY || !ETH_TRUE
#include <libsolidity/CompilerStack.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/AST.h>
#include <libsolidity/SourceReferenceFormatter.h>
#endif
#include <libnatspec/NatspecExpressionEvaluator.h>
#include <libethereum/Client.h>
#include <libethereum/Utility.h>
#include <libethcore/ICAP.h>
#include <libethcore/KeyManager.h>
#if ETH_SERPENT
#include <libserpent/funcs.h>
#include <libserpent/util.h>
#endif
#include "Debugger.h"
#include "ui_Transact.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
Transact::Transact(MainFace* _c, QWidget* _parent):
QDialog(_parent),
ui(new Ui::Transact),
m_main(_c)
{
ui->setupUi(this);
resetGasPrice();
setValueUnits(ui->valueUnits, ui->value, 0);
on_destination_currentTextChanged(QString());
}
Transact::~Transact()
{
delete ui;
}
void Transact::setEnvironment(AddressHash const& _accounts, dev::eth::Client* _eth, NatSpecFace* _natSpecDB)
{
m_accounts = _accounts;
m_ethereum = _eth;
m_natSpecDB = _natSpecDB;
auto old = ui->from->currentIndex();
ui->from->clear();
for (auto const& address: m_accounts)
{
u256 b = ethereum()->balanceAt(address, PendingBlock);
QString s = QString("%2: %1").arg(formatBalance(b).c_str()).arg(QString::fromStdString(m_main->render(address)));
ui->from->addItem(s);
}
updateDestination();
if (old > -1 && old < ui->from->count())
ui->from->setCurrentIndex(old);
else if (ui->from->count())
ui->from->setCurrentIndex(0);
}
void Transact::resetGasPrice()
{
setValueUnits(ui->gasPriceUnits, ui->gasPrice, m_main->gasPrice());
}
bool Transact::isCreation() const
{
return ui->destination->currentText().isEmpty() || ui->destination->currentText() == "(Create Contract)";
}
u256 Transact::fee() const
{
return gas() * gasPrice();
}
u256 Transact::gas() const
{
return ui->gas->value() == -1 ? m_upperBound : ui->gas->value();
}
u256 Transact::value() const
{
if (ui->valueUnits->currentIndex() == -1)
return 0;
return ui->value->value() * units()[units().size() - 1 - ui->valueUnits->currentIndex()].first;
}
u256 Transact::gasPrice() const
{
if (ui->gasPriceUnits->currentIndex() == -1)
return 0;
return ui->gasPrice->value() * units()[units().size() - 1 - ui->gasPriceUnits->currentIndex()].first;
}
u256 Transact::total() const
{
return value() + fee();
}
void Transact::updateDestination()
{
// TODO: should be a Qt model.
ui->destination->clear();
ui->destination->addItem("(Create Contract)");
QMultiMap<QString, QString> in;
for (Address const& a: m_main->allKnownAddresses())
in.insert(QString::fromStdString(m_main->toName(a) + " (" + ICAP(a).encoded() + ")"), QString::fromStdString(a.hex()));
for (auto i = in.begin(); i != in.end(); ++i)
ui->destination->addItem(i.key(), i.value());
}
void Transact::updateFee()
{
// ui->fee->setText(QString("(gas sub-total: %1)").arg(formatBalance(fee()).c_str()));
auto totalReq = total();
ui->total->setText(QString("Total: %1").arg(formatBalance(totalReq).c_str()));
bool ok = false;
for (auto const& i: m_accounts)
if (ethereum()->balanceAt(i) >= totalReq)
{
ok = true;
break;
}
// ui->send->setEnabled(ok);
QPalette p = ui->total->palette();
p.setColor(QPalette::WindowText, QColor(ok ? 0x00 : 0x80, 0x00, 0x00));
ui->total->setPalette(p);
}
void Transact::on_destination_currentTextChanged(QString)
{
if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)")
{
auto p = toAccount();
if (p.first)
ui->calculatedName->setText(QString::fromStdString(m_main->render(p.first)));
else
ui->calculatedName->setText("Unknown Address");
// ui->calculatedName->setText(m_main->toName(a) + " (" + ICAP(a).encoded() + ")");
if (!p.second.empty())
{
m_data = p.second;
ui->data->setPlainText(QString::fromStdString("0x" + toHex(m_data)));
ui->data->setEnabled(false);
}
else if (!ui->data->isEnabled())
{
m_data.clear();
ui->data->setPlainText("");
ui->data->setEnabled(true);
}
}
else
ui->calculatedName->setText("Create Contract");
rejigData();
// 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(), gas(), m_data, nonce);
else
// TODO: cache like m_data.
t = Transaction(value(), gasPrice(), gas(), toAccount().first, m_data, nonce);
qApp->clipboard()->setText(QString::fromStdString(toHex(t.rlp())));
}
/*static std::string toString(TransactionException _te)
{
switch (_te)
{
case TransactionException::Unknown: return "Unknown error";
case TransactionException::InvalidSignature: return "Permanent Abort: Invalid transaction signature";
case TransactionException::InvalidNonce: return "Transient Abort: Invalid transaction nonce";
case TransactionException::NotEnoughCash: return "Transient Abort: Not enough cash to pay for transaction";
case TransactionException::OutOfGasBase: return "Permanent Abort: Not enough gas to consider transaction";
case TransactionException::BlockGasLimitReached: return "Transient Abort: Gas limit of block reached";
case TransactionException::BadInstruction: return "VM Error: Attempt to execute invalid instruction";
case TransactionException::BadJumpDestination: return "VM Error: Attempt to jump to invalid destination";
case TransactionException::OutOfGas: return "VM Error: Out of gas";
case TransactionException::OutOfStack: return "VM Error: VM stack limit reached during execution";
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)
{
string ret = "";
auto const& contract = _compiler.getContractDefinition(_contractName);
auto interfaceFunctions = contract.getInterfaceFunctions();
for (auto const& it: interfaceFunctions)
{
ret += it.first.abridged();
ret += " :";
ret += it.second->getDeclaration().getName() + "\n";
}
return ret;
}
#endif
static tuple<vector<string>, bytes, string> userInputToCode(string const& _user, bool _opt)
{
string lll;
string solidity;
bytes data;
vector<string> errors;
if (_user.find_first_not_of("1234567890abcdefABCDEF\n\t ") == string::npos && _user.size() % 2 == 0)
{
std::string u = _user;
boost::replace_all_copy(u, "\n", "");
boost::replace_all_copy(u, "\t", "");
boost::replace_all_copy(u, " ", "");
data = fromHex(u);
}
#if ETH_SOLIDITY || !ETH_TRUE
else if (sourceIsSolidity(_user))
{
dev::solidity::CompilerStack compiler(true);
try
{
// compiler.addSources(dev::solidity::StandardSources);
data = compiler.compile(_user, _opt);
solidity = "<h4>Solidity</h4>";
solidity += "<pre>var " + compiler.defaultContractName() + " = web3.eth.contract(" + QString::fromStdString(compiler.getInterface()).replace(QRegExp("\\s"), "").toHtmlEscaped().toStdString() + ");</pre>";
solidity += "<pre>" + QString::fromStdString(compiler.getSolidityInterface()).toHtmlEscaped().toStdString() + "</pre>";
solidity += "<pre>" + QString::fromStdString(getFunctionHashes(compiler, "")).toHtmlEscaped().toStdString() + "</pre>";
}
catch (dev::Exception const& exception)
{
ostringstream error;
solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler);
errors.push_back("Solidity: " + error.str());
}
catch (...)
{
errors.push_back("Solidity: Uncaught exception");
}
}
#endif
#if ETH_SERPENT
else if (sourceIsSerpent(_user))
{
try
{
data = dev::asBytes(::compile(_user));
}
catch (string const& err)
{
errors.push_back("Serpent " + err);
}
}
#endif
else
{
data = compileLLL(_user, _opt, &errors);
if (errors.empty())
{
auto asmcode = compileLLLToAsm(_user, _opt);
lll = "<h4>LLL</h4><pre>" + QString::fromStdString(asmcode).toHtmlEscaped().toStdString() + "</pre>";
}
}
return make_tuple(errors, data, lll + solidity);
}
string Transact::natspecNotice(Address _to, bytes const& _data)
{
if (ethereum()->codeAt(_to, PendingBlock).size())
{
string userNotice = m_natSpecDB->getUserNotice(ethereum()->postState().codeHash(_to), _data);
if (userNotice.empty())
return "Destination contract unknown.";
else
{
NatspecExpressionEvaluator evaluator;
return evaluator.evalExpression(QString::fromStdString(userNotice)).toStdString();
}
}
else
return "Destination not a contract.";
}
pair<Address, bytes> Transact::toAccount()
{
pair<Address, bytes> p;
if (!isCreation())
{
if (!ui->destination->currentData().isNull() && ui->destination->currentText() == ui->destination->itemText(ui->destination->currentIndex()))
p.first = Address(ui->destination->currentData().toString().trimmed().toStdString());
else
p = m_main->fromString(ui->destination->currentText().trimmed().toStdString());
}
return p;
}
void Transact::timerEvent(QTimerEvent*)
{
Address from = fromAccount();
Address to = toAccount().first;
if (m_upperBound != m_lowerBound)
{
qint64 mid = (m_lowerBound + m_upperBound) / 2;
ExecutionResult er;
if (isCreation())
er = ethereum()->create(from, value(), m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient);
else
er = ethereum()->call(from, value(), to, m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient);
if (er.excepted == TransactionException::OutOfGas || er.excepted == TransactionException::OutOfGasBase || er.excepted == TransactionException::OutOfGasIntrinsic || er.codeDeposit == CodeDeposit::Failed)
m_lowerBound = m_lowerBound == mid ? m_upperBound : mid;
else
{
m_lastGood = er;
m_upperBound = m_upperBound == mid ? m_lowerBound : mid;
}
updateBounds();
}
else
finaliseBounds();
}
void Transact::updateBounds()
{
ui->minGas->setValue(m_lowerBound);
ui->maxGas->setValue(m_upperBound);
double oran = m_startUpperBound - m_startLowerBound;
double nran = m_upperBound - m_lowerBound;
int x = int(log2(oran / nran) * 100.0 / log2(oran * 2));
ui->progressGas->setValue(x);
ui->progressGas->setVisible(true);
ui->gas->setSpecialValueText(QString("Auto (%1 gas)").arg(m_upperBound));
}
void Transact::finaliseBounds()
{
killTimer(m_gasCalcTimer);
quint64 baseGas = (quint64)Transaction::gasRequired(m_data, 0);
ui->progressGas->setVisible(false);
quint64 executionGas = m_upperBound - baseGas;
QString htmlInfo = QString("<div class=\"info\"><span class=\"icon\">INFO</span> Gas required: %1 total = %2 base, %3 exec [%4 refunded later]</div>").arg(m_upperBound).arg(baseGas).arg(executionGas).arg((qint64)m_lastGood.gasRefunded);
auto bail = [&](QString he) {
ui->send->setEnabled(false);
ui->code->setHtml(he + htmlInfo + m_dataInfo);
};
auto s = fromAccount();
auto b = ethereum()->balanceAt(s, PendingBlock);
if (b < value() + 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;
}
if (m_upperBound > m_ethereum->gasLimitRemaining())
{
// 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;
}
if (m_lastGood.excepted != TransactionException::None)
{
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> " + QString::fromStdString(toString(m_lastGood.excepted)) + "</div>");
return;
}
if (m_lastGood.codeDeposit == CodeDeposit::Failed)
{
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(m_lastGood.gasForDeposit)) + " GAS &lt; " + QString::fromStdString(toString(m_lastGood.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte</div>");
return;
}
updateFee();
ui->code->setHtml(htmlInfo + m_dataInfo);
ui->send->setEnabled(true);
}
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().first;
ExecutionResult lastGood;
m_startLowerBound = baseGas;
m_startUpperBound = (qint64)ethereum()->gasLimitRemaining();
for (unsigned i = 0; i < 30; ++i)
{
qint64 mid = m_startUpperBound;
ExecutionResult er;
if (isCreation())
er = ethereum()->create(from, value(), m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient);
else
er = ethereum()->call(from, value(), to, m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient);
if (er.excepted == TransactionException::OutOfGas || er.excepted == TransactionException::OutOfGasBase || er.excepted == TransactionException::OutOfGasIntrinsic || er.codeDeposit == CodeDeposit::Failed)
{
m_startLowerBound = mid;
m_startUpperBound *= 2;
}
else
{
// Begin async binary chop for gas calculation..
m_lastGood = lastGood;
m_lowerBound = m_startLowerBound;
m_upperBound = m_startUpperBound;
killTimer(m_gasCalcTimer);
m_gasCalcTimer = startTimer(0);
return GasRequirements{m_upperBound, baseGas, m_upperBound - baseGas, (qint64)lastGood.gasRefunded, lastGood};
}
}
return GasRequirements();
}
void Transact::rejigData()
{
if (!ethereum())
return;
// Determine how much balance we have to play with...
//findSecret(value() + ethereum()->gasLimitRemaining() * gasPrice());
auto s = fromAccount();
if (!s)
return;
QString htmlInfo;
auto bail = [&](QString he) {
ui->send->setEnabled(false);
m_dataInfo = he + htmlInfo;
ui->code->setHtml(m_dataInfo);
};
// Determine m_info.
if (isCreation())
{
string info;
vector<string> errors;
tie(errors, m_data, info) = userInputToCode(ui->data->toPlainText().toStdString(), ui->optimize->isChecked());
if (errors.size())
{
// Errors determining transaction data (i.e. init code). Bail.
QString htmlErrors;
for (auto const& i: errors)
htmlErrors.append("<div class=\"error\"><span class=\"icon\">ERROR</span> " + QString::fromStdString(i).toHtmlEscaped() + "</div>");
bail(htmlErrors);
return;
}
htmlInfo = QString::fromStdString(info) + "<h4>Code</h4>" + QString::fromStdString(disassemble(m_data)).toHtmlEscaped();
}
else
{
m_data = parseData(ui->data->toPlainText().toStdString());
htmlInfo = "<h4>Dump</h4>" + QString::fromStdString(dev::memDump(m_data, 8, true));
}
htmlInfo += "<h4>Hex</h4>" + QString(ETH_HTML_DIV(ETH_HTML_MONO)) + QString::fromStdString(toHex(m_data)) + "</div>";
// Add Natspec information
if (!isCreation())
htmlInfo = "<div class=\"info\"><span class=\"icon\">INFO</span> " + QString::fromStdString(natspecNotice(toAccount().first, m_data)).toHtmlEscaped() + "</div>" + htmlInfo;
determineGasRequirements();
m_dataInfo = htmlInfo;
ui->code->setHtml(m_dataInfo);
ui->send->setEnabled(true);
}
Secret Transact::findSecret(u256 _totalReq) const
{
if (!ethereum())
return Secret();
Address best;
u256 bestBalance = 0;
for (auto const& i: m_accounts)
{
auto b = ethereum()->balanceAt(i, PendingBlock);
if (b >= _totalReq)
{
best = i;
break;
}
if (b > bestBalance)
bestBalance = b, best = i;
}
return m_main->retrieveSecret(best);
}
Address Transact::fromAccount()
{
if (ui->from->currentIndex() < 0 || ui->from->currentIndex() >= (int)m_accounts.size())
return Address();
auto it = m_accounts.begin();
std::advance(it, ui->from->currentIndex());
return *it;
}
void Transact::updateNonce()
{
u256 n = ethereum()->countAt(fromAccount(), PendingBlock);
ui->nonce->setMaximum((unsigned)n);
ui->nonce->setMinimum(0);
ui->nonce->setValue((unsigned)n);
}
void Transact::on_send_clicked()
{
// Secret s = findSecret(value() + fee());
u256 nonce = ui->autoNonce->isChecked() ? ethereum()->countAt(fromAccount(), PendingBlock) : ui->nonce->value();
auto a = fromAccount();
auto b = ethereum()->balanceAt(a, PendingBlock);
if (!a || b < value() + fee())
{
QMessageBox::critical(nullptr, "Transaction Failed", "Couldn't make transaction: account doesn't contain at least the required amount.", QMessageBox::Ok);
return;
}
Secret s = m_main->retrieveSecret(a);
if (!s)
return;
if (isCreation())
{
// If execution is a contract creation, add Natspec to
// a local Natspec LEVELDB
ethereum()->submitTransaction(s, value(), m_data, gas(), gasPrice(), nonce);
#if ETH_SOLIDITY
string src = ui->data->toPlainText().toStdString();
if (sourceIsSolidity(src))
try
{
dev::solidity::CompilerStack compiler(true);
m_data = compiler.compile(src, ui->optimize->isChecked());
for (string const& s: compiler.getContractNames())
{
h256 contractHash = compiler.getContractCodeHash(s);
m_natSpecDB->add(contractHash, compiler.getMetadata(s, dev::solidity::DocumentationType::NatspecUser));
}
}
catch (...) {}
#endif
}
else
// TODO: cache like m_data.
ethereum()->submitTransaction(s, value(), toAccount().first, m_data, gas(), gasPrice(), nonce);
close();
}
void Transact::on_debug_clicked()
{
// Secret s = findSecret(value() + fee());
Address from = fromAccount();
auto b = ethereum()->balanceAt(from, PendingBlock);
if (!from || b < value() + fee())
{
QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: account doesn't contain at least the required amount.");
return;
}
try
{
Block postState(ethereum()->postState());
Transaction t = isCreation() ?
Transaction(value(), gasPrice(), gas(), m_data, postState.transactionsFrom(from)) :
Transaction(value(), gasPrice(), gas(), toAccount().first, m_data, postState.transactionsFrom(from));
t.forceSender(from);
Debugger dw(m_main, this);
Executive e(postState, ethereum()->blockChain(), 0);
dw.populate(e, t);
dw.exec();
}
catch (dev::Exception const& _e)
{
QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction. Low-level error: " + QString::fromStdString(diagnostic_information(_e)));
// this output is aimed at developers, reconsider using _e.what for more user friendly output.
}
}

124
alethzero/Transact.h

@ -1,124 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Transact.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <libdevcore/RLP.h>
#include <libethcore/Common.h>
#include <libethereum/Transaction.h>
#include <QDialog>
#include <QMap>
#include <QList>
#include "MainFace.h"
namespace Ui { class Transact; }
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
{
Q_OBJECT
public:
explicit Transact(MainFace* _context, QWidget* _parent = 0);
~Transact();
void resetGasPrice();
void setEnvironment(dev::AddressHash const& _accounts, dev::eth::Client* _eth, NatSpecFace* _natSpecDB);
private slots:
void on_from_currentIndexChanged(int) { updateNonce(); rejigData(); }
void on_destination_currentTextChanged(QString);
void on_value_valueChanged(int) { updateFee(); rejigData(); }
void on_gas_valueChanged(int) { updateFee(); rejigData(); }
void on_valueUnits_currentIndexChanged(int) { updateFee(); rejigData(); }
void on_gasPriceUnits_currentIndexChanged(int) { updateFee(); rejigData(); }
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(); }
private:
dev::eth::Client* ethereum() const { return m_ethereum; }
void rejigData();
void updateNonce();
void updateBounds();
void finaliseBounds();
dev::Address fromAccount();
std::pair<dev::Address, bytes> toAccount();
void updateDestination();
void updateFee();
bool isCreation() const;
dev::u256 fee() const;
dev::u256 gas() const;
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;
void timerEvent(QTimerEvent*) override;
Ui::Transact* ui = nullptr;
unsigned m_backupGas = 0;
dev::bytes m_data;
dev::AddressHash m_accounts;
dev::eth::Client* m_ethereum = nullptr;
MainFace* m_main = nullptr;
NatSpecFace* m_natSpecDB = nullptr;
QString m_dataInfo;
qint64 m_startLowerBound = 0;
qint64 m_startUpperBound = 0;
qint64 m_lowerBound = 0;
qint64 m_upperBound = 0;
eth::ExecutionResult m_lastGood;
int m_gasCalcTimer = 0;
};
}
}

336
alethzero/Transact.ui

@ -1,336 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Transact</class>
<widget class="QDialog" name="Transact">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>604</width>
<height>695</height>
</rect>
</property>
<property name="windowTitle">
<string>Transact</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="10" column="2">
<widget class="QPushButton" name="debug">
<property name="text">
<string>&amp;Debug</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="gas">
<property name="specialValueText">
<string>Automatic</string>
</property>
<property name="suffix">
<string> gas</string>
</property>
<property name="minimum">
<number>-1</number>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QComboBox" name="valueUnits"/>
</item>
<item row="4" column="3">
<widget class="QComboBox" name="gasPriceUnits"/>
</item>
<item row="2" column="1" colspan="3">
<widget class="QLineEdit" name="calculatedName">
<property name="enabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="optimize">
<property name="text">
<string>&amp;Optimise</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="10" column="3">
<widget class="QPushButton" name="send">
<property name="text">
<string>&amp;Execute</string>
</property>
<property name="default">
<bool>false</bool>
</property>
</widget>
</item>
<item row="7" column="3">
<widget class="QSpinBox" name="nonce">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="8" column="0" colspan="4">
<widget class="QSplitter" name="splitter_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QPlainTextEdit" name="data">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
<widget class="QTextEdit" name="code">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QSpinBox" name="value">
<property name="suffix">
<string/>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QPushButton" name="copyUnsigned">
<property name="text">
<string>Copy &amp;Unsigned</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QComboBox" name="from"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>&amp;Gas</string>
</property>
<property name="buddy">
<cstring>gas</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;To</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QPushButton" name="cancel">
<property name="text">
<string>&amp;Cancel</string>
</property>
<property name="shortcut">
<string>Esc</string>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QCheckBox" name="autoNonce">
<property name="text">
<string>Auto Nonce</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="autoRepeat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="QComboBox" name="destination">
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>(Create Contract)</string>
</property>
</item>
</widget>
</item>
<item row="9" column="0" colspan="4">
<widget class="QLabel" name="total">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label5_2">
<property name="text">
<string>&amp;Amount</string>
</property>
<property name="buddy">
<cstring>value</cstring>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>D&amp;ata</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>data</cstring>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>&amp;From</string>
</property>
<property name="buddy">
<cstring>from</cstring>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QSpinBox" name="gasPrice">
<property name="prefix">
<string>@ </string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>430000000</number>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QSpinBox" name="maxGas">
<property name="suffix">
<string> gas</string>
</property>
<property name="prefix">
<string>max </string>
</property>
<property name="maximum">
<number>450000000</number>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QSpinBox" name="minGas">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="suffix">
<string> gas</string>
</property>
<property name="prefix">
<string>min </string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>450000000</number>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QProgressBar" name="progressGas">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="value">
<number>24</number>
</property>
<property name="format">
<string>Calculating gas...</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>autoNonce</sender>
<signal>toggled(bool)</signal>
<receiver>nonce</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>374</x>
<y>196</y>
</hint>
<hint type="destinationlabel">
<x>451</x>
<y>190</y>
</hint>
</hints>
</connection>
</connections>
</ui>

30
alethzero/WebPage.cpp

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

51
alethzero/WebPage.h

@ -1,51 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file WebPage.h
* @author Arkadiy Paronyan arkadiy@ethdev.com>
* @date 2015
*/
#pragma once
#include <QString>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic" //QtWebEngineWidgets/qwebenginecertificateerror.h:78:348: error: extra ';'
#include <QtWebEngineWidgets/QWebEnginePage>
#pragma GCC diagnostic pop
namespace dev
{
namespace az
{
class WebPage: public QWebEnginePage
{
Q_OBJECT
public:
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;
};
}
}

BIN
alethzero/alethzero.icns

Binary file not shown.

BIN
alethzero/alethzero.ico

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 KiB

1
alethzero/alethzero.rc

@ -1 +0,0 @@
APP_ICON ICON DISCARDABLE "alethzero.ico"

12
alethzero/main.cpp

@ -1,12 +0,0 @@
#include "MainWin.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Q_INIT_RESOURCE(js);
dev::az::Main w;
w.show();
return a.exec();
}

144
alethzero/plugins/blockchain/AllAccounts.cpp

@ -1,144 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AllAccounts.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#if ETH_FATDB || !ETH_TRUE
#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;
DEV_AZ_NOTE_PLUGIN(AllAccounts);
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->onlyKnown, 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 onlyKnown = m_ui->onlyKnown->isChecked();
Addresses as;
if (onlyKnown)
as = main()->allKnownAddresses();
else
as = ethereum()->addresses();
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);
(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));
}
m_ui->accounts->sortItems();
#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);
u256s keys = keysOf(storage);
sort(keys.begin(), keys.end());
for (auto const& i: keys)
s << "@" << showbase << hex << main()->prettyU256(i) << "&nbsp;&nbsp;&nbsp;&nbsp;" << showbase << hex << main()->prettyU256(storage[i]) << "<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())));
}
}
#endif

64
alethzero/plugins/blockchain/AllAccounts.h

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

137
alethzero/plugins/blockchain/AllAccounts.ui

@ -1,137 +0,0 @@
<?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>405</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>
<property name="checked">
<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="onlyKnown">
<property name="text">
<string>Only Known</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</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>

208
alethzero/plugins/blockchain/ExportState.cpp

@ -1,208 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ExportState.cpp
* @author Arkadiy Paronyan <arkadiy@ethdev.com>
* @date 2015
*/
#if ETH_FATDB
#include "ExportState.h"
#include <fstream>
#include <QFileDialog>
#include <QTextStream>
#include <libethereum/Client.h>
#include "ui_ExportState.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(ExportStateDialog);
ExportStateDialog::ExportStateDialog(MainFace* _m):
QDialog(_m),
Plugin(_m, "Export State"),
m_ui(new Ui::ExportState)
{
m_ui->setupUi(this);
connect(m_ui->close, &QPushButton::clicked, this, &ExportStateDialog::close);
connect(m_ui->accounts, &QListWidget::itemSelectionChanged, this, &ExportStateDialog::generateJSON);
connect(m_ui->contracts, &QListWidget::itemSelectionChanged, this, &ExportStateDialog::generateJSON);
fillBlocks();
connect(addMenuItem("Export State...", "menuTools", true), SIGNAL(triggered()), SLOT(exec()));
}
ExportStateDialog::~ExportStateDialog()
{
}
void ExportStateDialog::showEvent(QShowEvent*)
{
m_ui->block->clear();
m_ui->block->clearEditText();
m_ui->accounts->clear();
m_ui->contracts->clear();
fillBlocks();
}
void ExportStateDialog::on_block_editTextChanged()
{
QString text = m_ui->block->currentText();
int i = m_ui->block->count();
while (i-- >= 0)
if (m_ui->block->itemText(i) == text)
return;
fillBlocks();
}
void ExportStateDialog::on_block_currentIndexChanged(int _index)
{
m_block = m_ui->block->itemData(_index).toUInt();
fillContracts();
}
void ExportStateDialog::fillBlocks()
{
BlockChain const& bc = ethereum()->blockChain();
QStringList filters = m_ui->block->currentText().toLower().split(QRegExp("\\s+"), QString::SkipEmptyParts);
const unsigned numLastBlocks = 10;
if (m_ui->block->count() == 0)
{
unsigned i = numLastBlocks;
for (auto h = bc.currentHash(); bc.details(h) && i; h = bc.details(h).parent, --i)
{
auto d = bc.details(h);
m_ui->block->addItem(QString("#%1 %2").arg(d.number).arg(h.abridged().c_str()), d.number);
if (h == bc.genesisHash())
break;
}
if (m_ui->block->currentIndex() < 0)
m_ui->block->setCurrentIndex(0);
m_recentBlocks = numLastBlocks - i;
}
int i = m_ui->block->count();
while (i > 0 && i >= m_recentBlocks)
m_ui->block->removeItem(i--);
h256Hash blocks;
for (QString f: filters)
{
if (f.startsWith("#"))
f = f.remove(0, 1);
if (f.size() == 64)
{
h256 h(f.toStdString());
if (bc.isKnown(h))
blocks.insert(h);
for (auto const& b: bc.withBlockBloom(LogBloom().shiftBloom<3>(sha3(h)), 0, -1))
blocks.insert(bc.numberHash(b));
}
else if (f.toLongLong() <= bc.number())
blocks.insert(bc.numberHash((unsigned)f.toLongLong()));
else if (f.size() == 40)
{
Address h(f.toStdString());
for (auto const& b: bc.withBlockBloom(LogBloom().shiftBloom<3>(sha3(h)), 0, -1))
blocks.insert(bc.numberHash(b));
}
}
for (auto const& h: blocks)
{
auto d = bc.details(h);
m_ui->block->addItem(QString("#%1 %2").arg(d.number).arg(h.abridged().c_str()), d.number);
}
}
void ExportStateDialog::fillContracts()
{
m_ui->accounts->clear();
m_ui->contracts->clear();
m_ui->accounts->setEnabled(true);
m_ui->contracts->setEnabled(true);
try
{
for (auto i: ethereum()->addresses(m_block))
{
string r = main()->render(i);
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), ethereum()->codeAt(i).empty() ? m_ui->accounts : m_ui->contracts))
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size));
}
}
catch (InterfaceNotSupported const&)
{
m_ui->accounts->setEnabled(false);
m_ui->contracts->setEnabled(false);
m_ui->json->setEnabled(false);
m_ui->json->setText(QString("This feature requires compilation with FATDB support."));
}
}
void ExportStateDialog::generateJSON()
{
std::stringstream json;
json << "{\n";
std::string prefix;
for(QListWidgetItem* item: m_ui->accounts->selectedItems())
{
auto hba = item->data(Qt::UserRole).toByteArray();
auto address = Address((byte const*)hba.data(), Address::ConstructFromPointer);
json << prefix << "\t\"" << toHex(address.ref()) << "\": { \"wei\": \"" << ethereum()->balanceAt(address, m_block) << "\" }";
prefix = ",\n";
}
for(QListWidgetItem* item: m_ui->contracts->selectedItems())
{
auto hba = item->data(Qt::UserRole).toByteArray();
auto address = Address((byte const*)hba.data(), Address::ConstructFromPointer);
json << prefix << "\t\"" << toHex(address.ref()) << "\":\n\t{\n\t\t\"wei\": \"" << ethereum()->balanceAt(address, m_block) << "\",\n";
json << "\t\t\"code\": \"" << toHex(ethereum()->codeAt(address, m_block)) << "\",\n";
std::unordered_map<u256, u256> storage = ethereum()->storageAt(address, m_block);
if (!storage.empty())
{
json << "\t\t\"storage\":\n\t\t{\n";
std::string storagePrefix;
for (auto s: storage)
{
json << storagePrefix << "\t\t\t\"" << toHex(s.first) << "\": \"" << toHex(s.second) << "\"";
storagePrefix = ",\n";
}
json << "\n\t\t}\n";
}
json << "\t}";
prefix = ",\n";
}
json << "\n}";
json.flush();
m_ui->json->setEnabled(true);
m_ui->json->setText(QString::fromStdString(json.str()));
m_ui->saveButton->setEnabled(true);
}
void ExportStateDialog::on_saveButton_clicked()
{
QString fn = QFileDialog::getSaveFileName(this, "Save state", QString(), "JSON Files (*.json)");
if (!fn.endsWith(".json"))
fn = fn.append(".json");
ofstream file(fn.toStdString());
if (file.is_open())
file << m_ui->json->toPlainText().toStdString();
}
#endif //ETH_FATDB

70
alethzero/plugins/blockchain/ExportState.h

@ -1,70 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ExportState.h
* @author Arkadiy Paronyan <arkadiy@ethdev.com>
* @date 2015
*/
#pragma once
#if ETH_FATDB
#include <memory>
#include <QDialog>
#include <libethcore/Common.h>
#include "MainFace.h"
namespace Ui { class ExportState; }
namespace dev
{
namespace eth { class Client; }
namespace az
{
class ExportStateDialog: public QDialog, public Plugin
{
Q_OBJECT
public:
ExportStateDialog(MainFace* _m);
virtual ~ExportStateDialog();
private slots:
void on_block_editTextChanged();
void on_block_currentIndexChanged(int _index);
void on_saveButton_clicked();
private:
void showEvent(QShowEvent* _event) override;
void fillBlocks();
void fillContracts();
void generateJSON();
private:
std::unique_ptr<Ui::ExportState> m_ui;
int m_recentBlocks = 0;
eth::BlockNumber m_block = eth::LatestBlock;
};
}
}
#endif //ETH_FATDB

183
alethzero/plugins/blockchain/ExportState.ui

@ -1,183 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExportState</class>
<widget class="QDialog" name="ExportState">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>490</width>
<height>522</height>
</rect>
</property>
<property name="windowTitle">
<string>Export State</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;Block</string>
</property>
<property name="buddy">
<cstring>block</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="block">
<property name="editable">
<bool>true</bool>
</property>
<property name="currentText">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>&amp;Accounts</string>
</property>
<property name="buddy">
<cstring>accounts</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QListWidget" name="accounts">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>&amp;Contracts</string>
</property>
<property name="buddy">
<cstring>contracts</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QListWidget" name="contracts">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;JSON</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>json</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QTextEdit" name="json">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>2</verstretch>
</sizepolicy>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="saveButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;Save...</string>
</property>
<property name="shortcut">
<string>Esc</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="close">
<property name="text">
<string>&amp;Close</string>
</property>
<property name="shortcut">
<string>Esc</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

69
alethzero/plugins/brainwallet/BrainWallet.cpp

@ -1,69 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <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;
DEV_AZ_NOTE_PLUGIN(BrainWallet);
BrainWallet::BrainWallet(MainFace* _m):
Plugin(_m, "BrainWallet")
{
connect(addMenuItem("New Brain Wallet...", "menuTools", true), 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/plugins/brainwallet/BrainWallet.h

@ -1,44 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <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/plugins/brainwallet/BrainWallet.ui

@ -1,136 +0,0 @@
<?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 generally a Bad Plan. Unless used properly they're a terrible idea for protecteding anything of value. Read up on them and know the risks before using this functionality!&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 use the Generate button and memorise the list of words it gives you. This is the only way to guarantee a strong brainwallet. 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, hit the Generate button and memorize what ends up here.</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>

222
alethzero/plugins/keys/ImportKey.cpp

@ -1,222 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ImportKey.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "ImportKey.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QInputDialog>
#include <libdevcore/Log.h>
#include <libethcore/KeyManager.h>
#include <libethcore/ICAP.h>
#include <libethereum/Client.h>
#include "ui_ImportKey.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(ImportKey);
ImportKey::ImportKey(MainFace* _m):
Plugin(_m, "ImportKey")
{
connect(addMenuItem("Import Key...", "menuTools", true), SIGNAL(triggered()), SLOT(import()));
}
ImportKey::~ImportKey()
{
}
void ImportKey::import()
{
QDialog d;
Ui_ImportKey u;
u.setupUi(&d);
d.setWindowTitle("Import Key");
string lastKey;
Secret lastSecret;
string lastPassword;
Address lastAddress;
auto updateAction = [&](){
if (!u.import_2->isEnabled())
u.action->clear();
else if (lastKey.empty() && !lastSecret)
u.action->setText("Import brainwallet with given address and hint");
else if (!lastKey.empty() && !lastSecret)
{
h256 ph;
DEV_IGNORE_EXCEPTIONS(ph = h256(u.passwordHash->text().toStdString()));
if (ph)
u.action->setText("Import untouched key with given address and hint");
else
u.action->setText("Import untouched key with given address, password hash and hint");
}
else
{
bool mp = u.noPassword->isChecked();
if (mp)
u.action->setText("Import recast key using master password and given hint");
else
u.action->setText("Import recast key with given password and hint");
}
};
auto updateImport = [&](){
u.import_2->setDisabled(u.addressOut->text().isEmpty() || u.name->text().isEmpty() || !(u.oldPassword->isChecked() || u.newPassword->isChecked() || u.noPassword->isChecked()));
updateAction();
};
auto updateAddress = [&](){
lastAddress.clear();
string as = u.address->text().toStdString();
try
{
lastAddress = eth::toAddress(as);
u.addressOut->setText(QString::fromStdString(main()->render(lastAddress)));
}
catch (...)
{
u.addressOut->setText("");
}
updateImport();
};
auto updatePassword = [&](){
u.passwordHash->setText(QString::fromStdString(sha3(u.password->text().toStdString()).hex()));
updateAction();
};
function<void()> updateKey = [&](){
// update according to key.
if (lastKey == u.key->text().toStdString())
return;
lastKey = u.key->text().toStdString();
lastSecret.clear();
u.address->clear();
u.oldPassword->setEnabled(false);
u.oldPassword->setChecked(false);
bytes b;
DEV_IGNORE_EXCEPTIONS(b = fromHex(lastKey, WhenError::Throw));
if (b.size() == 32)
{
lastSecret = Secret(b);
bytesRef(&b).cleanse();
}
while (!lastKey.empty() && !lastSecret)
{
bool ok;
lastPassword = QInputDialog::getText(&d, "Open Key File", "Enter the password protecting this key file. Cancel if you do not want to provide te password.", QLineEdit::Password, QString(), &ok).toStdString();
if (!ok)
{
lastSecret.clear();
break;
}
// Try to open as a file.
lastSecret = KeyManager::presaleSecret(contentsString(lastKey), [&](bool first){ return first ? lastPassword : string(); }).secret();
if (!lastSecret)
lastSecret = Secret(SecretStore::secret(contentsString(lastKey), lastPassword));
if (!lastSecret && QMessageBox::warning(&d, "Invalid Password or Key File", "The given password could not be used to decrypt the key file given. Are you sure it is a valid key file and that the password is correct?", QMessageBox::Abort, QMessageBox::Retry) == QMessageBox::Abort)
{
u.key->clear();
updateKey();
return;
}
}
u.oldPassword->setEnabled(!!lastSecret);
u.newPassword->setEnabled(!!lastSecret);
u.noPassword->setEnabled(!!lastSecret);
u.masterLabel->setEnabled(!!lastSecret);
u.oldLabel->setEnabled(!!lastSecret);
u.showPassword->setEnabled(!!lastSecret);
u.password->setEnabled(!!lastSecret);
u.passwordHash->setReadOnly(!!lastSecret);
u.address->setReadOnly(!!lastSecret);
if (lastSecret)
{
u.oldPassword->setEnabled(!lastPassword.empty());
if (lastPassword.empty())
u.oldPassword->setChecked(false);
u.address->setText(QString::fromStdString(ICAP(toAddress(lastSecret)).encoded()));
updateAddress();
}
else
u.address->clear();
updateImport();
};
connect(u.noPassword, &QRadioButton::clicked, [&](){
u.passwordHash->clear();
u.hint->setText("No additional password (same as master password).");
updateAction();
});
connect(u.oldPassword, &QRadioButton::clicked, [&](){
u.passwordHash->setText(QString::fromStdString(sha3(lastPassword).hex()));
u.hint->setText("Same as original password for file " + QString::fromStdString(lastKey));
updateAction();
});
connect(u.newPassword, &QRadioButton::clicked, [&](){
u.hint->setText("");
updatePassword();
});
connect(u.password, &QLineEdit::textChanged, [&](){ updatePassword(); });
connect(u.address, &QLineEdit::textChanged, [&](){ updateAddress(); });
connect(u.key, &QLineEdit::textEdited, [&](){ updateKey(); });
connect(u.name, &QLineEdit::textEdited, [&](){ updateImport(); });
connect(u.showPassword, &QCheckBox::toggled, [&](bool show){ u.password->setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password); });
connect(u.openKey, &QToolButton::clicked, [&](){
QString fn = QFileDialog::getOpenFileName(main(), "Open Key File", QDir::homePath(), "JSON Files (*.json);;All Files (*)");
if (!fn.isEmpty())
{
u.key->setText(fn);
updateKey();
}
});
if (d.exec() == QDialog::Accepted)
{
Address a = lastAddress;
string n = u.name->text().toStdString();
string h = u.hint->text().toStdString();
// check for a brain wallet import
if (lastKey.empty() && !lastSecret)
main()->keyManager().importExistingBrain(a, n, h);
else if (!lastKey.empty() && !lastSecret)
{
h256 ph;
DEV_IGNORE_EXCEPTIONS(ph = h256(u.passwordHash->text().toStdString()));
main()->keyManager().importExisting(main()->keyManager().store().importKey(lastKey), n, a, ph, h);
}
else
{
bool mp = u.noPassword->isChecked();
string p = mp ? string() : u.oldPassword ? lastPassword : u.password->text().toStdString();
if (mp)
main()->keyManager().import(lastSecret, n);
else
main()->keyManager().import(lastSecret, n, p, h);
}
main()->noteKeysChanged();
}
}

44
alethzero/plugins/keys/ImportKey.h

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

336
alethzero/plugins/keys/ImportKey.ui

@ -1,336 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ImportKey</class>
<widget class="QDialog" name="ImportKey">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>530</width>
<height>389</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="10" column="2" colspan="3">
<widget class="QLineEdit" name="passwordHash">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="3" colspan="2">
<widget class="QCheckBox" name="showPassword">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Show</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&amp;Address:</string>
</property>
<property name="buddy">
<cstring>address</cstring>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QToolButton" name="openKey">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="8" column="0" colspan="2">
<widget class="QRadioButton" name="newPassword">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>New &amp;Password:</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="4" column="2" colspan="3">
<widget class="QLineEdit" name="address">
<property name="placeholderText">
<string>Place the address of the key here</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>&amp;Name:</string>
</property>
<property name="buddy">
<cstring>name</cstring>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QRadioButton" name="noPassword">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Master password</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="11" column="2" colspan="3">
<widget class="QLineEdit" name="hint"/>
</item>
<item row="7" column="0" colspan="2">
<widget class="QRadioButton" name="oldPassword">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Old password</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="8" column="2">
<widget class="QLineEdit" name="password">
<property name="placeholderText">
<string>Enter the password you wish to use for the key here</string>
</property>
</widget>
</item>
<item row="2" column="2" colspan="3">
<widget class="QLineEdit" name="name">
<property name="placeholderText">
<string>Enter this key's name here</string>
</property>
</widget>
</item>
<item row="10" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Password &amp;Hash:</string>
</property>
<property name="buddy">
<cstring>passwordHash</cstring>
</property>
</widget>
</item>
<item row="11" column="0" colspan="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Password Hin&amp;t:</string>
</property>
<property name="buddy">
<cstring>hint</cstring>
</property>
</widget>
</item>
<item row="6" column="2" colspan="3">
<widget class="QLabel" name="masterLabel">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Use same password for the key as for the master.</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="2" colspan="2">
<widget class="QLineEdit" name="key">
<property name="placeholderText">
<string>Brain wallet (no key file)</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>&amp;Key:</string>
</property>
<property name="buddy">
<cstring>key</cstring>
</property>
</widget>
</item>
<item row="7" column="2" colspan="3">
<widget class="QLabel" name="oldLabel">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Use the same password as in the key file.</string>
</property>
</widget>
</item>
<item row="5" column="2" colspan="3">
<widget class="QLineEdit" name="addressOut">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string>Unknown Address</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="action">
<property name="text">
<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>
<property name="shortcut">
<string>Esc</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="import_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Import</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<tabstops>
<tabstop>name</tabstop>
<tabstop>key</tabstop>
<tabstop>openKey</tabstop>
<tabstop>address</tabstop>
<tabstop>addressOut</tabstop>
<tabstop>noPassword</tabstop>
<tabstop>oldPassword</tabstop>
<tabstop>newPassword</tabstop>
<tabstop>password</tabstop>
<tabstop>showPassword</tabstop>
<tabstop>passwordHash</tabstop>
<tabstop>hint</tabstop>
<tabstop>cancel</tabstop>
<tabstop>import_2</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>import_2</sender>
<signal>clicked()</signal>
<receiver>ImportKey</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>519</x>
<y>378</y>
</hint>
<hint type="destinationlabel">
<x>449</x>
<y>388</y>
</hint>
</hints>
</connection>
<connection>
<sender>cancel</sender>
<signal>clicked()</signal>
<receiver>ImportKey</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>433</x>
<y>378</y>
</hint>
<hint type="destinationlabel">
<x>351</x>
<y>388</y>
</hint>
</hints>
</connection>
<connection>
<sender>newPassword</sender>
<signal>pressed()</signal>
<receiver>password</receiver>
<slot>setFocus()</slot>
<hints>
<hint type="sourcelabel">
<x>80</x>
<y>211</y>
</hint>
<hint type="destinationlabel">
<x>185</x>
<y>215</y>
</hint>
</hints>
</connection>
</connections>
<buttongroups>
<buttongroup name="buttonGroup"/>
</buttongroups>
</ui>

98
alethzero/plugins/log/LogPanel.cpp

@ -1,98 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <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"), "");
}
DEV_AZ_NOTE_PLUGIN(LogPanel);
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/plugins/log/LogPanel.h

@ -1,64 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <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/plugins/log/LogPanel.ui

@ -1,99 +0,0 @@
<?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>

108
alethzero/plugins/namers/NameRegNamer.cpp

@ -1,108 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file NameRegNamer.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "NameRegNamer.h"
#include <QSettings>
#include <libdevcore/Log.h>
#include <libethereum/Client.h>
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(NameRegNamer);
NameRegNamer::NameRegNamer(MainFace* _m):
AccountNamerPlugin(_m, "NameRegNamer")
{
}
NameRegNamer::~NameRegNamer()
{
}
string NameRegNamer::toName(Address const& _a) const
{
for (auto const& r: m_registrars)
{
string n = abiOut<string>(main()->ethereum()->call(Address(1), 0, r, abiIn("name(address)", _a), 1000000, DefaultGasPrice, PendingBlock, FudgeFactor::Lenient).output);
if (!n.empty())
return n;
}
return string();
}
Address NameRegNamer::toAddress(std::string const& _n) const
{
for (auto const& r: m_registrars)
if (Address a = abiOut<Address>(main()->ethereum()->call(r, abiIn("addr(string)", _n)).output))
return a;
return Address();
}
Addresses NameRegNamer::knownAddresses() const
{
return m_knownCache;
}
void NameRegNamer::killRegistrar(Address const& _r)
{
if (m_filters.count(_r))
{
main()->uninstallWatch(m_filters.at(_r));
m_filters.erase(_r);
}
for (auto i = m_registrars.begin(); i != m_registrars.end();)
if (*i == _r)
i = m_registrars.erase(i);
else
++i;
}
void NameRegNamer::updateCache()
{
// m_forwardCache.clear();
// m_reverseCache.clear();
m_knownCache.clear();
#if ETH_FATDB || !ETH_TRUE
for (auto const& r: m_registrars)
for (u256 const& a: keysOf(ethereum()->storageAt(r)))
if (a < u256(1) << 160)
m_knownCache.push_back(Address((u160)a - 1));
#endif
}
void NameRegNamer::readSettings(QSettings const& _s)
{
(void)_s;
while (!m_registrars.empty())
killRegistrar(m_registrars.back());
Address a("047cdba9627a8686bb24b3a65d87dab7efa53d31");
m_registrars.push_back(a);
m_filters[a] = main()->installWatch(LogFilter().address(a), [=](LocalisedLogEntries const&){ updateCache(); });
noteKnownChanged();
}
void NameRegNamer::writeSettings(QSettings&)
{
}

59
alethzero/plugins/namers/NameRegNamer.h

@ -1,59 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file NameRegNamer.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include "MainFace.h"
namespace dev
{
namespace az
{
class NameRegNamer: public QObject, public AccountNamerPlugin
{
Q_OBJECT
public:
NameRegNamer(MainFace* _m);
~NameRegNamer();
private:
void readSettings(QSettings const&) override;
void writeSettings(QSettings&) override;
std::string toName(Address const&) const override;
Address toAddress(std::string const&) const override;
Addresses knownAddresses() const override;
void updateCache();
void killRegistrar(Address const& _r);
Addresses m_registrars;
std::unordered_map<Address, unsigned> m_filters;
mutable Addresses m_knownCache;
// mutable std::unordered_map<Address, std::string> m_forwardCache;
// mutable std::unordered_map<std::string, Address> m_reverseCache;
};
}
}

171
alethzero/plugins/namers/NewAccount.cpp

@ -1,171 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file NewAccount.h
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#include "NewAccount.h"
#include <QMenu>
#include <QDialog>
#include <libdevcore/Log.h>
#include <libethcore/KeyManager.h>
#include <libethereum/Client.h>
#include "ui_NewAccount.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
bool beginsWith(Address _a, bytes const& _b)
{
for (unsigned i = 0; i < min<unsigned>(20, _b.size()); ++i)
if (_a[i] != _b[i])
return false;
return true;
}
DEV_AZ_NOTE_PLUGIN(NewAccount);
NewAccount::NewAccount(MainFace* _m):
Plugin(_m, "NewAccount")
{
connect(addMenuItem("New Account...", "menuTools", true), SIGNAL(triggered()), SLOT(create()));
}
NewAccount::~NewAccount()
{
}
void NewAccount::create()
{
QDialog d;
Ui::NewAccount u;
u.setupUi(&d);
d.setWindowTitle("New Account Wallet");
u.hexText->setEnabled(false);
u.passwordText->setEnabled(false);
u.passwordAgainText->setEnabled(false);
u.hintText->setEnabled(false);
QStringList items =
{
"No vanity (instant)",
"Direct ICAP address",
"Two pairs first (a few seconds)",
"Two pairs first and second (a few minutes)",
"Three pairs first (a few minutes)",
"Four pairs first (several hours)",
"Specific hex string"
};
u.typeComboBox->addItems(items);
void (QComboBox:: *indexChangedSignal)(int) = &QComboBox::currentIndexChanged;
connect(u.typeComboBox, indexChangedSignal, [&](int index)
{
u.hexText->setEnabled(index == StringMatch);
});
connect(u.additionalCheckBox, &QCheckBox::clicked, [&]()
{
bool checked = u.additionalCheckBox->checkState() == Qt::CheckState::Checked;
u.passwordText->setEnabled(checked);
u.passwordAgainText->setEnabled(checked);
u.hintText->setEnabled(checked);
});
connect(u.create, &QPushButton::clicked, [&]()
{
if (u.additionalCheckBox->checkState() == Qt::CheckState::Checked && !validatePassword(u))
{
u.passwordAgainLabel->setStyleSheet("QLabel { color : red }");
u.passwordAgainLabel->setText("Invalid! Please re-enter password correctly:");
return;
}
d.accept();
});
if (d.exec() == QDialog::Accepted)
onDialogAccepted(u);
}
bool NewAccount::validatePassword(Ui::NewAccount const& _u)
{
return QString::compare(_u.passwordText->toPlainText(), _u.passwordAgainText->toPlainText()) == 0;
}
void NewAccount::onDialogAccepted(Ui::NewAccount const& _u)
{
Type v = (Type)_u.typeComboBox->currentIndex();
bytes bs = fromHex(_u.hexText->toPlainText().toStdString());
KeyPair p = newKeyPair(v, bs);
QString s = _u.nameText->toPlainText();
if (_u.additionalCheckBox->checkState() == Qt::CheckState::Checked)
{
std::string hint = _u.hintText->toPlainText().toStdString();
std::string password = _u.passwordText->toPlainText().toStdString();
main()->keyManager().import(p.secret(), s.toStdString(), password, hint);
}
else
main()->keyManager().import(p.secret(), s.toStdString());
main()->noteKeysChanged();
}
KeyPair NewAccount::newKeyPair(Type _type, bytes const& _prefix)
{
KeyPair p;
bool keepGoing = true;
unsigned done = 0;
function<void()> f = [&]() {
KeyPair lp;
while (keepGoing)
{
done++;
if (done % 1000 == 0)
cnote << "Tried" << done << "keys";
lp = KeyPair::create();
auto a = lp.address();
if (_type == NoVanity ||
(_type == DirectICAP && !a[0]) ||
(_type == FirstTwo && a[0] == a[1]) ||
(_type == FirstTwoNextTwo && a[0] == a[1] && a[2] == a[3]) ||
(_type == FirstThree && a[0] == a[1] && a[1] == a[2]) ||
(_type == FirstFour && a[0] == a[1] && a[1] == a[2] && a[2] == a[3]) ||
(_type == StringMatch && beginsWith(lp.address(), _prefix))
)
break;
}
if (keepGoing)
p = lp;
keepGoing = false;
};
vector<std::thread*> ts;
for (unsigned t = 0; t < std::thread::hardware_concurrency() - 1; ++t)
ts.push_back(new std::thread(f));
f();
for (std::thread* t: ts)
{
t->join();
delete t;
}
return p;
}

56
alethzero/plugins/namers/NewAccount.h

@ -1,56 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file NewAccount.h
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
#pragma once
#include "MainFace.h"
namespace Ui
{
class NewAccount;
}
namespace dev
{
namespace az
{
class NewAccount: public QObject, public Plugin
{
Q_OBJECT
public:
NewAccount(MainFace* _m);
~NewAccount();
private slots:
void create();
private:
enum Type { NoVanity = 0, DirectICAP, FirstTwo, FirstTwoNextTwo, FirstThree, FirstFour, StringMatch };
bool validatePassword(Ui::NewAccount const& _u);
void onDialogAccepted(Ui::NewAccount const& _u);
KeyPair newKeyPair(Type _type, bytes const& _prefix);
};
}
}

260
alethzero/plugins/namers/NewAccount.ui

@ -1,260 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NewAccount</class>
<widget class="QDialog" name="NewAccount">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>511</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="typeLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<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;Select new account type:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="typeComboBox">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="hexLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enter some hex digits it should begin with.&lt;br/&gt;NOTE: The more you enter, the longer generation will take.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="hexText">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="nameLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<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;Enter this account name:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="nameText">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="additionalLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>100</height>
</size>
</property>
<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;Would you like to add additional security for this key? This lets you protect it with a different password to other keys, but also means that you need to re-enter the key's password every time you wish to use the account.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="additionalCheckBox">
<property name="text">
<string>Yes</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="passwordLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<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;Enter password:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="passwordText">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="passwordAgainLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<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;Enter password again:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="passwordAgainText">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="hintLabel">
<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;Enter hint:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="hintText">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<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="maximumSize">
<size>
<width>83</width>
<height>16777215</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="create">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>83</width>
<height>16777215</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<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>cancel</sender>
<signal>clicked()</signal>
<receiver>NewAccount</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>

99
alethzero/plugins/namers/OtherAccounts.cpp

@ -1,99 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file OtherAccounts.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "OtherAccounts.h"
#include <QSettings>
#include <QMessageBox>
#include <libdevcore/Log.h>
#include <libethereum/Client.h>
#include <ui_OtherAccounts.h>
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(OtherAccounts);
OtherAccounts::OtherAccounts(MainFace* _m):
AccountNamerPlugin(_m, "OtherAccounts")
{
connect(addMenuItem("Register Third-party Address Names...", "menuTools", true), SIGNAL(triggered()), SLOT(import()));
}
void OtherAccounts::import()
{
QDialog d;
Ui_OtherAccounts u;
u.setupUi(&d);
d.setWindowTitle("Add Named Accounts");
if (d.exec() == QDialog::Accepted)
{
QStringList sl = u.accounts->toPlainText().split("\n");
unsigned line = 1;
for (QString const& s: sl)
{
try
{
Address addr = dev::eth::toAddress(s.section(QRegExp("[ \\0\\t]+"), 0, 0).trimmed().toStdString());
string name = s.section(QRegExp("[ \\0\\t]+"), 1).trimmed().toStdString();
m_toName[addr] = name;
m_toAddress[name] = addr;
}
catch (...)
{
if (QMessageBox::warning(&d, "Invalid Line Format", "Line format or address given on line " + QString::number(line) + " is invalid:\n" + s, QMessageBox::Abort, QMessageBox::Ignore) == QMessageBox::Abort)
break;
}
line++;
}
main()->noteSettingsChanged();
noteKnownChanged();
}
}
void OtherAccounts::readSettings(QSettings const& _s)
{
m_toName.clear();
m_toAddress.clear();
for (QVariant const& i: _s.value("OtherAccounts", QVariantList()).toList())
{
QStringList l = i.toStringList();
if (l.size() == 2)
{
m_toName[Address(l[0].toStdString())] = l[1].toStdString();
m_toAddress[l[1].toStdString()] = Address(l[0].toStdString());
}
}
noteKnownChanged();
}
void OtherAccounts::writeSettings(QSettings& _s)
{
QVariantList r;
for (auto const& i: m_toName)
{
QStringList l;
l += QString::fromStdString(i.first.hex());
l += QString::fromStdString(i.second);
r += QVariant(l);
}
_s.setValue("OtherAccounts", r);
}

55
alethzero/plugins/namers/OtherAccounts.h

@ -1,55 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file OtherAccounts.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include "MainFace.h"
namespace dev
{
namespace az
{
class OtherAccounts: public QObject, public AccountNamerPlugin
{
Q_OBJECT
public:
OtherAccounts(MainFace* _m);
protected:
std::string toName(Address const& _a) const override { if (m_toName.count(_a)) return m_toName.at(_a); return std::string(); }
Address toAddress(std::string const& _n) const override { if (m_toAddress.count(_n)) return m_toAddress.at(_n); return Address(); }
Addresses knownAddresses() const override { return keysOf(m_toName); }
private slots:
void import();
private:
void readSettings(QSettings const&) override;
void writeSettings(QSettings&) override;
std::unordered_map<std::string, Address> m_toAddress;
std::unordered_map<Address, std::string> m_toName;
};
}
}

95
alethzero/plugins/namers/OtherAccounts.ui

@ -1,95 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OtherAccounts</class>
<widget class="QDialog" name="OtherAccounts">
<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="QTextEdit" name="accounts">
<property name="placeholderText">
<string>Write the accounts you wish to name here, one address/name pair per line, the name following the address split only be a single space character.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<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;Import</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>OtherAccounts</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>OtherAccounts</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>

67
alethzero/plugins/namers/OurAccounts.cpp

@ -1,67 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file OurAccounts.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "OurAccounts.h"
#include <libdevcore/Log.h>
#include <libethereum/Client.h>
#include <libethcore/KeyManager.h>
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(OurAccounts);
OurAccounts::OurAccounts(MainFace* _m):
AccountNamerPlugin(_m, "OurAccounts")
{
connect(main(), SIGNAL(keyManagerChanged()), SLOT(updateNames()));
updateNames();
}
OurAccounts::~OurAccounts()
{
}
std::string OurAccounts::toName(Address const& _a) const
{
return main()->keyManager().accountName(_a);
}
Address OurAccounts::toAddress(std::string const& _n) const
{
if (m_names.count(_n))
return m_names.at(_n);
return Address();
}
Addresses OurAccounts::knownAddresses() const
{
return main()->keyManager().accounts();
}
void OurAccounts::updateNames()
{
m_names.clear();
for (Address const& i: main()->keyManager().accounts())
m_names[main()->keyManager().accountName(i)] = i;
noteKnownChanged();
}

52
alethzero/plugins/namers/OurAccounts.h

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

87
alethzero/plugins/special/InjectTransactions.cpp

@ -1,87 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file InjectTransactions.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "InjectTransactions.h"
#include <QMessageBox>
#include <QInputDialog>
#include <libdevcore/Log.h>
#include <libethereum/Client.h>
#include "ui_InjectTransactions.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(InjectTransactions);
InjectTransactions::InjectTransactions(MainFace* _m):
Plugin(_m, "InjectTransactions")
{
connect(addMenuItem("Inject Transaction...", "menuSpecial", true), SIGNAL(triggered()), SLOT(injectOne()));
connect(addMenuItem("Bulk Inject Transactions...", "menuSpecial", false), SIGNAL(triggered()), SLOT(injectBulk()));
}
InjectTransactions::~InjectTransactions()
{
}
void InjectTransactions::injectOne()
{
bool ok;
QString s = QInputDialog::getText(main(), "Inject Transaction", "Enter transaction dump in hex", QLineEdit::Normal, QString(), &ok);
if (ok)
doInject(s);
}
void InjectTransactions::injectBulk()
{
QDialog d;
Ui_InjectTransactions u;
u.setupUi(&d);
d.setWindowTitle("Bulk Inject Transactions");
if (d.exec() == QDialog::Accepted)
for (QString const& s: u.transactions->toPlainText().split("\n"))
doInject(s);
}
void InjectTransactions::doInject(QString _txHex)
{
try
{
bytes b = fromHex(_txHex.toStdString(), WhenError::Throw);
main()->ethereum()->injectTransaction(b, IfDropped::Retry);
}
catch (BadHexCharacter& _e)
{
if (QMessageBox::warning(main(), "Invalid Transaction Hex", "Invalid hex character in:\n" + _txHex + "\nTransaction rejected.", QMessageBox::Ignore, QMessageBox::Abort) == QMessageBox::Abort)
return;
}
catch (Exception& _e)
{
if (QMessageBox::warning(main(), "Transaction Rejected", "Invalid transaction; due to" + QString::fromStdString(_e.what()) + "\n" + _txHex + "\nTransaction rejected.", QMessageBox::Ignore, QMessageBox::Abort) == QMessageBox::Abort)
return;
}
catch (...)
{
// Should not happen under normal circumstances.
return;
}
}

48
alethzero/plugins/special/InjectTransactions.h

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

95
alethzero/plugins/special/InjectTransactions.ui

@ -1,95 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>InjectTransactions</class>
<widget class="QDialog" name="InjectTransactions">
<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="QTextEdit" name="transactions">
<property name="placeholderText">
<string>Write the transactions you wish to inject here, in hex, one per line.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<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="inject">
<property name="text">
<string>&amp;Import</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>inject</sender>
<signal>clicked()</signal>
<receiver>InjectTransactions</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>InjectTransactions</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>

178
alethzero/plugins/whisper/Whisper.cpp

@ -1,178 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Whisper.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "Whisper.h"
#include <QSettings>
#include <libethereum/Client.h>
#include <libethereum/Utility.h>
#include <libwhisper/WhisperHost.h>
#include <libweb3jsonrpc/WebThreeStubServerBase.h>
#include "OurWebThreeStubServer.h"
#include "ui_Whisper.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(Whisper);
static Public stringToPublic(QString const& _a)
{
string sn = _a.toStdString();
if (_a.size() == sizeof(Public) * 2)
return Public(fromHex(_a.toStdString()));
else if (_a.size() == sizeof(Public) * 2 + 2 && _a.startsWith("0x"))
return Public(fromHex(_a.mid(2).toStdString()));
else
return Public();
}
static shh::Topics topicFromText(QString _s)
{
shh::BuildTopic ret;
while (_s.size())
{
QRegExp r("(@|\\$)?\"([^\"]*)\"(\\s.*)?");
QRegExp d("(@|\\$)?([0-9]+)(\\s*(ether)|(finney)|(szabo))?(\\s.*)?");
QRegExp h("(@|\\$)?(0x)?(([a-fA-F0-9])+)(\\s.*)?");
bytes part;
if (r.exactMatch(_s))
{
for (auto i: r.cap(2))
part.push_back((byte)i.toLatin1());
if (r.cap(1) != "$")
for (int i = r.cap(2).size(); i < 32; ++i)
part.push_back(0);
else
part.push_back(0);
_s = r.cap(3);
}
else if (d.exactMatch(_s))
{
u256 v(d.cap(2).toStdString());
if (d.cap(6) == "szabo")
v *= szabo;
else if (d.cap(5) == "finney")
v *= finney;
else if (d.cap(4) == "ether")
v *= ether;
bytes bs = dev::toCompactBigEndian(v);
if (d.cap(1) != "$")
for (auto i = bs.size(); i < 32; ++i)
part.push_back(0);
for (auto b: bs)
part.push_back(b);
_s = d.cap(7);
}
else if (h.exactMatch(_s))
{
bytes bs = fromHex((((h.cap(3).size() & 1) ? "0" : "") + h.cap(3)).toStdString());
if (h.cap(1) != "$")
for (auto i = bs.size(); i < 32; ++i)
part.push_back(0);
for (auto b: bs)
part.push_back(b);
_s = h.cap(5);
}
else
_s = _s.mid(1);
ret.shift(part);
}
return ret;
}
Whisper::Whisper(MainFace* _m):
Plugin(_m, "Whisper"),
m_ui(new Ui::Whisper)
{
dock(Qt::RightDockWidgetArea, "Whisper")->setWidget(new QWidget);
m_ui->setupUi(dock()->widget());
connect(addMenuItem("New Whisper identity.", "menuNetwork", true), &QAction::triggered, this, &Whisper::on_newIdentity_triggered);
connect(_m->web3Server(), &OurWebThreeStubServer::onNewId, this, &Whisper::addNewId);
}
void Whisper::readSettings(QSettings const& _s)
{
m_myIdentities.clear();
QByteArray b = _s.value("identities").toByteArray();
if (!b.isEmpty())
{
Secret k;
for (unsigned i = 0; i < b.size() / sizeof(Secret); ++i)
{
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));
}
}
main()->web3Server()->setIdentities(keysAsVector(m_myIdentities));
refreshWhisper();
}
void Whisper::writeSettings(QSettings& _s)
{
QByteArray b;
b.resize(sizeof(Secret) * m_myIdentities.size());
auto p = b.data();
for (auto i: m_myIdentities)
{
memcpy(p, &(i.secret()), sizeof(Secret));
p += sizeof(Secret);
}
_s.setValue("identities", b);
}
void Whisper::addNewId(QString _ids)
{
KeyPair kp(jsToSecret(_ids.toStdString()));
m_myIdentities.push_back(kp);
main()->web3Server()->setIdentities(keysAsVector(m_myIdentities));
refreshWhisper();
}
void Whisper::refreshWhisper()
{
m_ui->shhFrom->clear();
for (auto i: main()->web3Server()->ids())
m_ui->shhFrom->addItem(QString::fromStdString(toHex(i.first.ref())));
}
void Whisper::on_newIdentity_triggered()
{
KeyPair kp = KeyPair::create();
m_myIdentities.append(kp);
main()->web3Server()->setIdentities(keysAsVector(m_myIdentities));
refreshWhisper();
}
void Whisper::on_post_clicked()
{
return;
shh::Message m;
m.setTo(stringToPublic(m_ui->shhTo->currentText()));
m.setPayload(parseData(m_ui->shhData->toPlainText().toStdString()));
Public f = stringToPublic(m_ui->shhFrom->currentText());
Secret from;
if (main()->web3Server()->ids().count(f))
from = main()->web3Server()->ids().at(f);
whisper()->inject(m.seal(from, topicFromText(m_ui->shhTopic->toPlainText()), m_ui->shhTtl->value(), m_ui->shhWork->value()));
}

60
alethzero/plugins/whisper/Whisper.h

@ -1,60 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Whisper.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 Whisper;
}
namespace dev
{
namespace az
{
class Whisper: public QObject, public Plugin
{
Q_OBJECT
public:
Whisper(MainFace* _m);
private:
void readSettings(QSettings const&) override;
void writeSettings(QSettings&) override;
void refreshWhisper();
void addNewId(QString _ids);
void on_newIdentity_triggered();
void on_post_clicked();
Ui::Whisper* m_ui;
QList<KeyPair> m_myIdentities;
};
}
}

176
alethzero/plugins/whisper/Whisper.ui

@ -1,176 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Whisper</class>
<widget class="QWidget" name="WhisperWidget">
<layout class="QGridLayout" name="gridLayout_4">
<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="2" colspan="2">
<widget class="QLabel" name="label5_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Work to Prove</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="4">
<widget class="QPlainTextEdit" name="shhData">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</item>
<item row="3" column="1" colspan="4">
<widget class="QPlainTextEdit" name="shhTopic">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</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="3" column="0">
<widget class="QLabel" name="label_9">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<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>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label5_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>To</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="4">
<widget class="QComboBox" name="shhTo">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="shhTtl">
<property name="suffix">
<string> seconds</string>
</property>
<property name="minimum">
<number>5</number>
</property>
<property name="maximum">
<number>259200</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label5_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<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>
</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>
</layout>
</widget>
<resources/>
<connections/>
</ui>

78
alethzero/plugins/whisper/WhisperPeers.cpp

@ -1,78 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file WhisperPeers.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "WhisperPeers.h"
#include <QSettings>
#include <libethereum/Client.h>
#include <libwhisper/WhisperHost.h>
#include <libweb3jsonrpc/WebThreeStubServerBase.h>
#include "OurWebThreeStubServer.h"
#include "ui_WhisperPeers.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
DEV_AZ_NOTE_PLUGIN(WhisperPeers);
WhisperPeers::WhisperPeers(MainFace* _m):
Plugin(_m, "WhisperPeers"),
m_ui(new Ui::WhisperPeers)
{
dock(Qt::RightDockWidgetArea, "Active Whispers")->setWidget(new QWidget);
m_ui->setupUi(dock()->widget());
startTimer(1000);
}
void WhisperPeers::timerEvent(QTimerEvent*)
{
refreshWhispers();
}
void WhisperPeers::refreshWhispers()
{
return;
m_ui->whispers->clear();
for (auto const& w: whisper()->all())
{
shh::Envelope const& e = w.second;
shh::Message m;
for (pair<Public, Secret> const& i: main()->web3Server()->ids())
if (!!(m = e.open(shh::Topics(), i.second)))
break;
if (!m)
m = e.open(shh::Topics());
QString msg;
if (m.from())
// Good message.
msg = QString("{%1 -> %2} %3").arg(m.from() ? m.from().abridged().c_str() : "???").arg(m.to() ? m.to().abridged().c_str() : "*").arg(toHex(m.payload()).c_str());
else if (m)
// Maybe message.
msg = QString("{%1 -> %2} %3 (?)").arg(m.from() ? m.from().abridged().c_str() : "???").arg(m.to() ? m.to().abridged().c_str() : "*").arg(toHex(m.payload()).c_str());
time_t ex = e.expiry();
QString t(ctime(&ex));
t.chop(1);
QString item = QString("[%1 - %2s] *%3 %5 %4").arg(t).arg(e.ttl()).arg(e.workProved()).arg(toString(e.topic()).c_str()).arg(msg);
m_ui->whispers->addItem(item);
}
}

55
alethzero/plugins/whisper/WhisperPeers.h

@ -1,55 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file WhisperPeers.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 WhisperPeers;
}
namespace dev
{
namespace az
{
class WhisperPeers: public QObject, public Plugin
{
Q_OBJECT
public:
WhisperPeers(MainFace* _m);
private:
void timerEvent(QTimerEvent*) override;
void refreshWhispers();
Ui::WhisperPeers* m_ui;
};
}
}

32
alethzero/plugins/whisper/WhisperPeers.ui

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WhisperPeers</class>
<widget class="QWidget" name="whisperPeersWidget">
<layout class="QHBoxLayout" name="whisperPeersLayout">
<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="QListWidget" name="whispers">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

7
cmake/scripts/buildinfo.cmake

@ -9,6 +9,12 @@
# example usage: # example usage:
# cmake -DETH_SOURCE_DIR=. -DETH_DST_DIR=build -DETH_BUILD_TYPE=Debug -DETH_BUILD_PLATFORM=mac -P scripts/buildinfo.cmake # cmake -DETH_SOURCE_DIR=. -DETH_DST_DIR=build -DETH_BUILD_TYPE=Debug -DETH_BUILD_PLATFORM=mac -P scripts/buildinfo.cmake
if (ETH_FATDB)
set(ETH_FATDB 1)
else()
set(ETH_FATDB 0)
endif()
if (NOT ETH_BUILD_TYPE) if (NOT ETH_BUILD_TYPE)
set(ETH_BUILD_TYPE "unknown") set(ETH_BUILD_TYPE "unknown")
endif() endif()
@ -41,6 +47,7 @@ set(INFILE "${ETH_SOURCE_DIR}/BuildInfo.h.in")
set(TMPFILE "${ETH_DST_DIR}/BuildInfo.h.tmp") set(TMPFILE "${ETH_DST_DIR}/BuildInfo.h.tmp")
set(OUTFILE "${ETH_DST_DIR}/BuildInfo.h") set(OUTFILE "${ETH_DST_DIR}/BuildInfo.h")
message("ETH_FATDB: ${ETH_FATDB}")
configure_file("${INFILE}" "${TMPFILE}") configure_file("${INFILE}" "${TMPFILE}")
include("${ETH_SOURCE_DIR}/cmake/EthUtils.cmake") include("${ETH_SOURCE_DIR}/cmake/EthUtils.cmake")

4
eth/main.cpp

@ -314,7 +314,7 @@ int main(int argc, char** argv)
unsigned peers = 11; unsigned peers = 11;
unsigned peerStretch = 7; unsigned peerStretch = 7;
std::map<NodeId, pair<NodeIPEndpoint,bool>> preferredNodes; std::map<NodeID, pair<NodeIPEndpoint,bool>> preferredNodes;
bool bootstrap = true; bool bootstrap = true;
bool disableDiscovery = false; bool disableDiscovery = false;
bool pinning = false; bool pinning = false;
@ -1089,7 +1089,7 @@ int main(int argc, char** argv)
for (auto const& i: Host::pocHosts()) for (auto const& i: Host::pocHosts())
web3.requirePeer(i.first, i.second); web3.requirePeer(i.first, i.second);
if (!remoteHost.empty()) if (!remoteHost.empty())
web3.addNode(p2p::NodeId(), remoteHost + ":" + toString(remotePort)); web3.addNode(p2p::NodeID(), remoteHost + ":" + toString(remotePort));
signal(SIGABRT, &Client::exitHandler); signal(SIGABRT, &Client::exitHandler);
signal(SIGTERM, &Client::exitHandler); signal(SIGTERM, &Client::exitHandler);

7
libdevcore/Common.h

@ -279,6 +279,13 @@ private:
#define DEV_TIMED_FUNCTION_ABOVE(MS) DEV_TIMED_SCOPE_ABOVE(__PRETTY_FUNCTION__, MS) #define DEV_TIMED_FUNCTION_ABOVE(MS) DEV_TIMED_SCOPE_ABOVE(__PRETTY_FUNCTION__, MS)
#endif #endif
#ifdef _MSC_VER
// TODO.
#define DEV_UNUSED
#else
#define DEV_UNUSED __attribute__((unused))
#endif
enum class WithExisting: int enum class WithExisting: int
{ {
Trust = 0, Trust = 0,

39
libdevcore/Log.h

@ -111,11 +111,11 @@ std::string getThreadName();
/// The default logging channels. Each has an associated verbosity and three-letter prefix (name() ). /// The default logging channels. Each has an associated verbosity and three-letter prefix (name() ).
/// Channels should inherit from LogChannel and define name() and verbosity. /// Channels should inherit from LogChannel and define name() and verbosity.
struct LogChannel { static const char* name(); static const int verbosity = 1; }; struct LogChannel { static const char* name(); static const int verbosity = 1; static const bool debug = true; };
struct LeftChannel: public LogChannel { static const char* name(); }; struct LeftChannel: public LogChannel { static const char* name(); };
struct RightChannel: public LogChannel { static const char* name(); }; struct RightChannel: public LogChannel { static const char* name(); };
struct WarnChannel: public LogChannel { static const char* name(); static const int verbosity = 0; }; struct WarnChannel: public LogChannel { static const char* name(); static const int verbosity = 0; static const bool debug = false; };
struct NoteChannel: public LogChannel { static const char* name(); }; struct NoteChannel: public LogChannel { static const char* name(); static const bool debug = false; };
struct DebugChannel: public LogChannel { static const char* name(); static const int verbosity = 0; }; struct DebugChannel: public LogChannel { static const char* name(); static const int verbosity = 0; };
enum class LogTag enum class LogTag
@ -259,30 +259,29 @@ public:
template <class T> LogOutputStream& operator<<(T const& _t) { if (Id::verbosity <= g_logVerbosity) { if (_AutoSpacing && m_sstr.str().size() && m_sstr.str().back() != ' ') m_sstr << " "; append(_t); } return *this; } template <class T> LogOutputStream& operator<<(T const& _t) { if (Id::verbosity <= g_logVerbosity) { if (_AutoSpacing && m_sstr.str().size() && m_sstr.str().back() != ' ') m_sstr << " "; append(_t); } return *this; }
}; };
// Simple cout-like stream objects for accessing common log channels.
// Dirties the global namespace, but oh so convenient...
#define cnote dev::LogOutputStream<dev::NoteChannel, true>()
#define cwarn dev::LogOutputStream<dev::WarnChannel, true>()
// Null stream-like objects.
#define ndebug if (true) {} else dev::NullOutputStream()
#define nlog(X) if (true) {} else dev::NullOutputStream()
#define nslog(X) if (true) {} else dev::NullOutputStream()
// Kill debugging log channel when we're in release mode.
#if NDEBUG
#define cdebug ndebug
#else
#define cdebug dev::LogOutputStream<dev::DebugChannel, true>()
#endif
// Kill all logs when when NLOG is defined. // Kill all logs when when NLOG is defined.
#if NLOG #if NLOG
#define clog(X) nlog(X) #define clog(X) nlog(X)
#define cslog(X) nslog(X) #define cslog(X) nslog(X)
#else #else
#if NDEBUG
#define clog(X) if (X::debug) {} else dev::LogOutputStream<X, true>()
#define cslog(X) if (X::debug) {} else dev::LogOutputStream<X, false>()
#else
#define clog(X) dev::LogOutputStream<X, true>() #define clog(X) dev::LogOutputStream<X, true>()
#define cslog(X) dev::LogOutputStream<X, false>() #define cslog(X) dev::LogOutputStream<X, false>()
#endif #endif
#endif
// Simple cout-like stream objects for accessing common log channels.
// Dirties the global namespace, but oh so convenient...
#define cdebug clog(dev::DebugChannel)
#define cnote clog(dev::NoteChannel)
#define cwarn clog(dev::WarnChannel)
// Null stream-like objects.
#define ndebug if (true) {} else dev::NullOutputStream()
#define nlog(X) if (true) {} else dev::NullOutputStream()
#define nslog(X) if (true) {} else dev::NullOutputStream()
} }

1
libethcore/BlockInfo.cpp

@ -20,6 +20,7 @@
*/ */
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/Log.h>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcore/TrieDB.h> #include <libdevcore/TrieDB.h>
#include <libdevcore/TrieHash.h> #include <libdevcore/TrieHash.h>

4
libethereum/EthereumHost.h

@ -74,7 +74,7 @@ public:
DownloadMan const& downloadMan() const { return m_man; } DownloadMan const& downloadMan() const { return m_man; }
DownloadMan& downloadMan() { return m_man; } DownloadMan& downloadMan() { return m_man; }
bool isSyncing() const; bool isSyncing() const;
bool isBanned(p2p::NodeId const& _id) const { return !!m_banned.count(_id); } bool isBanned(p2p::NodeID const& _id) const { return !!m_banned.count(_id); }
void noteNewTransactions() { m_newTransactions = true; } void noteNewTransactions() { m_newTransactions = true; }
void noteNewBlocks() { m_newBlocks = true; } void noteNewBlocks() { m_newBlocks = true; }
@ -129,7 +129,7 @@ private:
h256 m_latestBlockSent; h256 m_latestBlockSent;
h256Hash m_transactionsSent; h256Hash m_transactionsSent;
std::unordered_set<p2p::NodeId> m_banned; std::unordered_set<p2p::NodeID> m_banned;
bool m_newTransactions = false; bool m_newTransactions = false;
bool m_newBlocks = false; bool m_newBlocks = false;

58
libp2p/Common.cpp

@ -20,6 +20,7 @@
*/ */
#include "Common.h" #include "Common.h"
#include "Network.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::p2p; using namespace dev::p2p;
@ -29,7 +30,7 @@ const unsigned dev::p2p::c_defaultIPPort = 30303;
static_assert(dev::p2p::c_protocolVersion == 4, "Replace v3 compatbility with v4 compatibility before updating network version."); static_assert(dev::p2p::c_protocolVersion == 4, "Replace v3 compatbility with v4 compatibility before updating network version.");
const dev::p2p::NodeIPEndpoint dev::p2p::UnspecifiedNodeIPEndpoint = NodeIPEndpoint(bi::address(), 0, 0); const dev::p2p::NodeIPEndpoint dev::p2p::UnspecifiedNodeIPEndpoint = NodeIPEndpoint(bi::address(), 0, 0);
const dev::p2p::Node dev::p2p::UnspecifiedNode = dev::p2p::Node(NodeId(), UnspecifiedNodeIPEndpoint); const dev::p2p::Node dev::p2p::UnspecifiedNode = dev::p2p::Node(NodeID(), UnspecifiedNodeIPEndpoint);
bool dev::p2p::NodeIPEndpoint::test_allowLocal = false; bool dev::p2p::NodeIPEndpoint::test_allowLocal = false;
@ -199,7 +200,60 @@ void DeadlineOps::reap()
}); });
} }
namespace dev { Node::Node(NodeSpec const& _s, PeerType _p):
id(_s.id()),
endpoint(_s.nodeIPEndpoint()),
peerType(_p)
{}
NodeSpec::NodeSpec(string const& _user)
{
m_address = _user;
if (m_address.substr(0, 8) == "enode://" && m_address.find('@') == 136)
{
m_id = p2p::NodeID(m_address.substr(8, 128));
m_address = m_address.substr(137);
}
size_t colon = m_address.find_first_of(":");
if (colon != string::npos)
{
string ports = m_address.substr(colon + 1);
m_address = m_address.substr(0, colon);
size_t p2 = ports.find_first_of(".");
if (p2 != string::npos)
{
m_udpPort = stoi(ports.substr(p2 + 1));
m_tcpPort = stoi(ports.substr(0, p2));
}
else
m_tcpPort = m_udpPort = stoi(ports);
}
}
NodeIPEndpoint NodeSpec::nodeIPEndpoint() const
{
return NodeIPEndpoint(p2p::Network::resolveHost(m_address).address(), m_udpPort, m_tcpPort);
}
std::string NodeSpec::enode() const
{
string ret = m_address;
if (m_tcpPort)
if (m_udpPort && m_tcpPort != m_udpPort)
ret += ":" + toString(m_tcpPort) + "." + toString(m_udpPort);
else
ret += ":" + toString(m_tcpPort);
else if (m_udpPort)
ret += ":" + toString(m_udpPort);
if (m_id)
return "enode://" + m_id.hex() + "@" + ret;
return ret;
}
namespace dev
{
std::ostream& operator<<(std::ostream& _out, dev::p2p::NodeIPEndpoint const& _ep) std::ostream& operator<<(std::ostream& _out, dev::p2p::NodeIPEndpoint const& _ep)
{ {

73
libp2p/Common.h

@ -54,12 +54,12 @@ namespace p2p
extern const unsigned c_protocolVersion; extern const unsigned c_protocolVersion;
extern const unsigned c_defaultIPPort; extern const unsigned c_defaultIPPort;
struct NodeIPEndpoint; class NodeIPEndpoint;
struct Node; class Node;
extern const NodeIPEndpoint UnspecifiedNodeIPEndpoint; extern const NodeIPEndpoint UnspecifiedNodeIPEndpoint;
extern const Node UnspecifiedNode; extern const Node UnspecifiedNode;
using NodeId = h512; using NodeID = h512;
bool isPrivateAddress(bi::address const& _addressToCheck); bool isPrivateAddress(bi::address const& _addressToCheck);
bool isPrivateAddress(std::string const& _addressToCheck); bool isPrivateAddress(std::string const& _addressToCheck);
@ -150,7 +150,7 @@ using CapDescs = std::vector<CapDesc>;
*/ */
struct PeerSessionInfo struct PeerSessionInfo
{ {
NodeId const id; NodeID const id;
std::string const clientVersion; std::string const clientVersion;
std::string const host; std::string const host;
unsigned short const port; unsigned short const port;
@ -163,11 +163,18 @@ struct PeerSessionInfo
using PeerSessionInfos = std::vector<PeerSessionInfo>; using PeerSessionInfos = std::vector<PeerSessionInfo>;
enum class PeerType
{
Optional,
Required
};
/** /**
* @brief IPv4,UDP/TCP endpoints. * @brief IPv4,UDP/TCP endpoints.
*/ */
struct NodeIPEndpoint class NodeIPEndpoint
{ {
public:
enum RLPAppend enum RLPAppend
{ {
StreamList, StreamList,
@ -181,10 +188,6 @@ struct NodeIPEndpoint
NodeIPEndpoint(bi::address _addr, uint16_t _udp, uint16_t _tcp): address(_addr), udpPort(_udp), tcpPort(_tcp) {} NodeIPEndpoint(bi::address _addr, uint16_t _udp, uint16_t _tcp): address(_addr), udpPort(_udp), tcpPort(_tcp) {}
NodeIPEndpoint(RLP const& _r) { interpretRLP(_r); } NodeIPEndpoint(RLP const& _r) { interpretRLP(_r); }
bi::address address = bi::address();
uint16_t udpPort = 0;
uint16_t tcpPort = 0;
operator bi::udp::endpoint() const { return bi::udp::endpoint(address, udpPort); } operator bi::udp::endpoint() const { return bi::udp::endpoint(address, udpPort); }
operator bi::tcp::endpoint() const { return bi::tcp::endpoint(address, tcpPort); } operator bi::tcp::endpoint() const { return bi::tcp::endpoint(address, tcpPort); }
@ -194,25 +197,61 @@ struct NodeIPEndpoint
void streamRLP(RLPStream& _s, RLPAppend _append = StreamList) const; void streamRLP(RLPStream& _s, RLPAppend _append = StreamList) const;
void interpretRLP(RLP const& _r); void interpretRLP(RLP const& _r);
// TODO: make private, give accessors and rename m_...
bi::address address;
uint16_t udpPort = 0;
uint16_t tcpPort = 0;
}; };
struct Node struct NodeSpec
{ {
Node(Public _pubk, NodeIPEndpoint const& _ip, bool _required = false): id(_pubk), endpoint(_ip), required(_required) {} NodeSpec() {}
/// Accepts user-readable strings of the form (enode://pubkey@)host({:port,:tcpport.udpport})
NodeSpec(std::string const& _user);
NodeSpec(std::string const& _addr, uint16_t _port, int _udpPort = -1):
m_address(_addr),
m_tcpPort(_port),
m_udpPort(_udpPort == -1 ? _port : (uint16_t)_udpPort)
{}
NodeID id() const { return m_id; }
virtual NodeId const& address() const { return id; } NodeIPEndpoint nodeIPEndpoint() const;
std::string enode() const;
private:
std::string m_address;
uint16_t m_tcpPort = 0;
uint16_t m_udpPort = 0;
NodeID m_id;
};
class Node
{
public:
Node() = default;
Node(Node const&) = default;
Node(Public _publicKey, NodeIPEndpoint const& _ip, PeerType _peerType = PeerType::Optional): id(_publicKey), endpoint(_ip), peerType(_peerType) {}
Node(NodeSpec const& _s, PeerType _peerType = PeerType::Optional);
virtual NodeID const& address() const { return id; }
virtual Public const& publicKey() const { return id; } virtual Public const& publicKey() const { return id; }
NodeId id; virtual operator bool() const { return (bool)id; }
// TODO: make private, give accessors and rename m_...
NodeID id;
/// Endpoints by which we expect to reach node. /// Endpoints by which we expect to reach node.
// TODO: make private, give accessors and rename m_...
NodeIPEndpoint endpoint; NodeIPEndpoint endpoint;
/// If true, node will not be removed from Node list.
// TODO: p2p implement // TODO: p2p implement
bool required = false; PeerType peerType = PeerType::Optional;
virtual operator bool() const { return (bool)id; }
}; };
class DeadlineOps class DeadlineOps

52
libp2p/Host.cpp

@ -50,7 +50,7 @@ std::chrono::milliseconds const c_keepAliveTimeOut = std::chrono::milliseconds(1
HostNodeTableHandler::HostNodeTableHandler(Host& _host): m_host(_host) {} HostNodeTableHandler::HostNodeTableHandler(Host& _host): m_host(_host) {}
void HostNodeTableHandler::processEvent(NodeId const& _n, NodeTableEventType const& _e) void HostNodeTableHandler::processEvent(NodeID const& _n, NodeTableEventType const& _e)
{ {
m_host.onNodeTableEvent(_n, _e); m_host.onNodeTableEvent(_n, _e);
} }
@ -305,7 +305,7 @@ void Host::startPeerSession(Public const& _id, RLP const& _rlp, unique_ptr<RLPXF
StructuredLogger::p2pConnected(_id.abridged(), ps->m_peer->endpoint, ps->m_peer->m_lastConnected, clientVersion, peerCount()); StructuredLogger::p2pConnected(_id.abridged(), ps->m_peer->endpoint, ps->m_peer->m_lastConnected, clientVersion, peerCount());
} }
void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e) void Host::onNodeTableEvent(NodeID const& _n, NodeTableEventType const& _e)
{ {
if (_e == NodeEntryAdded) if (_e == NodeEntryAdded)
{ {
@ -336,7 +336,7 @@ void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e)
{ {
clog(NetP2PNote) << "p2p.host.nodeTable.events.NodeEntryDropped " << _n; clog(NetP2PNote) << "p2p.host.nodeTable.events.NodeEntryDropped " << _n;
RecursiveGuard l(x_sessions); RecursiveGuard l(x_sessions);
if (m_peers.count(_n) && !m_peers[_n]->required) if (m_peers.count(_n) && m_peers[_n]->peerType == PeerType::Optional)
m_peers.erase(_n); m_peers.erase(_n);
} }
} }
@ -450,7 +450,15 @@ std::unordered_map<Public, std::string> const& Host::pocHosts()
return c_ret; return c_ret;
} }
void Host::addNode(NodeId const& _node, NodeIPEndpoint const& _endpoint) void Host::addPeer(NodeSpec const& _s, PeerType _t)
{
if (_t == PeerType::Optional)
addNode(_s.id(), _s.nodeIPEndpoint());
else
requirePeer(_s.id(), _s.nodeIPEndpoint());
}
void Host::addNode(NodeID const& _node, NodeIPEndpoint const& _endpoint)
{ {
// return if network is stopped while waiting on Host::run() or nodeTable to start // return if network is stopped while waiting on Host::run() or nodeTable to start
while (!haveNetwork()) while (!haveNetwork())
@ -466,12 +474,12 @@ void Host::addNode(NodeId const& _node, NodeIPEndpoint const& _endpoint)
m_nodeTable->addNode(Node(_node, _endpoint)); m_nodeTable->addNode(Node(_node, _endpoint));
} }
void Host::requirePeer(NodeId const& _n, NodeIPEndpoint const& _endpoint) void Host::requirePeer(NodeID const& _n, NodeIPEndpoint const& _endpoint)
{ {
if (!m_run) if (!m_run)
return; return;
Node node(_n, _endpoint, true); Node node(_n, _endpoint, PeerType::Required);
if (_n) if (_n)
{ {
// create or update m_peers entry // create or update m_peers entry
@ -481,7 +489,7 @@ void Host::requirePeer(NodeId const& _n, NodeIPEndpoint const& _endpoint)
{ {
p = m_peers[_n]; p = m_peers[_n];
p->endpoint = node.endpoint; p->endpoint = node.endpoint;
p->required = true; p->peerType = PeerType::Required;
} }
else else
{ {
@ -506,7 +514,7 @@ void Host::requirePeer(NodeId const& _n, NodeIPEndpoint const& _endpoint)
} }
} }
void Host::relinquishPeer(NodeId const& _node) void Host::relinquishPeer(NodeID const& _node)
{ {
Guard l(x_requiredPeers); Guard l(x_requiredPeers);
if (m_requiredPeers.count(_node)) if (m_requiredPeers.count(_node))
@ -524,7 +532,7 @@ void Host::connect(std::shared_ptr<Peer> const& _p)
return; return;
} }
if (!!m_nodeTable && !m_nodeTable->haveNode(_p->id) && !_p->required) if (!!m_nodeTable && !m_nodeTable->haveNode(_p->id) && _p->peerType == PeerType::Optional)
return; return;
// prevent concurrently connecting to a node // prevent concurrently connecting to a node
@ -638,7 +646,7 @@ void Host::run(boost::system::error_code const&)
for (auto const& p: m_peers) for (auto const& p: m_peers)
{ {
bool haveSession = havePeerSession(p.second->id); bool haveSession = havePeerSession(p.second->id);
bool required = p.second->required; bool required = p.second->peerType == PeerType::Required;
if (haveSession && required) if (haveSession && required)
reqConn++; reqConn++;
else if (!haveSession && p.second->shouldReconnect() && (!m_netPrefs.pin || required)) else if (!haveSession && p.second->shouldReconnect() && (!m_netPrefs.pin || required))
@ -647,7 +655,7 @@ void Host::run(boost::system::error_code const&)
} }
for (auto p: toConnect) for (auto p: toConnect)
if (p->required && reqConn++ < m_idealPeerCount) if (p->peerType == PeerType::Required && reqConn++ < m_idealPeerCount)
connect(p); connect(p);
if (!m_netPrefs.pin) if (!m_netPrefs.pin)
@ -658,7 +666,7 @@ void Host::run(boost::system::error_code const&)
int openSlots = m_idealPeerCount - peerCount() - pendingCount + reqConn; int openSlots = m_idealPeerCount - peerCount() - pendingCount + reqConn;
if (openSlots > 0) if (openSlots > 0)
for (auto p: toConnect) for (auto p: toConnect)
if (!p->required && openSlots--) if (p->peerType == PeerType::Optional && openSlots--)
connect(p); connect(p);
} }
@ -780,11 +788,11 @@ bytes Host::saveNetwork() const
continue; continue;
// Only save peers which have connected within 2 days, with properly-advertised port and public IP address // Only save peers which have connected within 2 days, with properly-advertised port and public IP address
if (chrono::system_clock::now() - p.m_lastConnected < chrono::seconds(3600 * 48) && !!p.endpoint && p.id != id() && (p.required || p.endpoint.isAllowed())) if (chrono::system_clock::now() - p.m_lastConnected < chrono::seconds(3600 * 48) && !!p.endpoint && p.id != id() && (p.peerType == PeerType::Required || p.endpoint.isAllowed()))
{ {
network.appendList(11); network.appendList(11);
p.endpoint.streamRLP(network, NodeIPEndpoint::StreamInline); p.endpoint.streamRLP(network, NodeIPEndpoint::StreamInline);
network << p.id << p.required network << p.id << (p.peerType == PeerType::Required ? true : false)
<< chrono::duration_cast<chrono::seconds>(p.m_lastConnected.time_since_epoch()).count() << chrono::duration_cast<chrono::seconds>(p.m_lastConnected.time_since_epoch()).count()
<< chrono::duration_cast<chrono::seconds>(p.m_lastAttempted.time_since_epoch()).count() << chrono::duration_cast<chrono::seconds>(p.m_lastAttempted.time_since_epoch()).count()
<< p.m_failedAttempts << (unsigned)p.m_lastDisconnect << p.m_score << p.m_rating; << p.m_failedAttempts << (unsigned)p.m_lastDisconnect << p.m_score << p.m_rating;
@ -843,13 +851,13 @@ void Host::restoreNetwork(bytesConstRef _b)
if (i.itemCount() == 4 || i.itemCount() == 11) if (i.itemCount() == 4 || i.itemCount() == 11)
{ {
Node n((NodeId)i[3], NodeIPEndpoint(i)); Node n((NodeID)i[3], NodeIPEndpoint(i));
if (i.itemCount() == 4 && n.endpoint.isAllowed()) if (i.itemCount() == 4 && n.endpoint.isAllowed())
m_nodeTable->addNode(n); m_nodeTable->addNode(n);
else if (i.itemCount() == 11) else if (i.itemCount() == 11)
{ {
n.required = i[4].toInt<bool>(); n.peerType = i[4].toInt<bool>() ? PeerType::Required : PeerType::Optional;
if (!n.endpoint.isAllowed() && !n.required) if (!n.endpoint.isAllowed() && n.peerType == PeerType::Optional)
continue; continue;
shared_ptr<Peer> p = make_shared<Peer>(n); shared_ptr<Peer> p = make_shared<Peer>(n);
p->m_lastConnected = chrono::system_clock::time_point(chrono::seconds(i[5].toInt<unsigned>())); p->m_lastConnected = chrono::system_clock::time_point(chrono::seconds(i[5].toInt<unsigned>()));
@ -859,7 +867,7 @@ void Host::restoreNetwork(bytesConstRef _b)
p->m_score = (int)i[9].toInt<unsigned>(); p->m_score = (int)i[9].toInt<unsigned>();
p->m_rating = (int)i[10].toInt<unsigned>(); p->m_rating = (int)i[10].toInt<unsigned>();
m_peers[p->id] = p; m_peers[p->id] = p;
if (p->required) if (p->peerType == PeerType::Required)
requirePeer(p->id, n.endpoint); requirePeer(p->id, n.endpoint);
else else
m_nodeTable->addNode(*p.get(), NodeTable::NodeRelation::Known); m_nodeTable->addNode(*p.get(), NodeTable::NodeRelation::Known);
@ -867,13 +875,13 @@ void Host::restoreNetwork(bytesConstRef _b)
} }
else if (i.itemCount() == 3 || i.itemCount() == 10) else if (i.itemCount() == 3 || i.itemCount() == 10)
{ {
Node n((NodeId)i[2], NodeIPEndpoint(bi::address_v4(i[0].toArray<byte, 4>()), i[1].toInt<uint16_t>(), i[1].toInt<uint16_t>())); Node n((NodeID)i[2], NodeIPEndpoint(bi::address_v4(i[0].toArray<byte, 4>()), i[1].toInt<uint16_t>(), i[1].toInt<uint16_t>()));
if (i.itemCount() == 3 && n.endpoint.isAllowed()) if (i.itemCount() == 3 && n.endpoint.isAllowed())
m_nodeTable->addNode(n); m_nodeTable->addNode(n);
else if (i.itemCount() == 10) else if (i.itemCount() == 10)
{ {
n.required = i[3].toInt<bool>(); n.peerType = i[3].toInt<bool>() ? PeerType::Required : PeerType::Optional;
if (!n.endpoint.isAllowed() && !n.required) if (!n.endpoint.isAllowed() && n.peerType == PeerType::Optional)
continue; continue;
shared_ptr<Peer> p = make_shared<Peer>(n); shared_ptr<Peer> p = make_shared<Peer>(n);
p->m_lastConnected = chrono::system_clock::time_point(chrono::seconds(i[4].toInt<unsigned>())); p->m_lastConnected = chrono::system_clock::time_point(chrono::seconds(i[4].toInt<unsigned>()));
@ -883,7 +891,7 @@ void Host::restoreNetwork(bytesConstRef _b)
p->m_score = (int)i[8].toInt<unsigned>(); p->m_score = (int)i[8].toInt<unsigned>();
p->m_rating = (int)i[9].toInt<unsigned>(); p->m_rating = (int)i[9].toInt<unsigned>();
m_peers[p->id] = p; m_peers[p->id] = p;
if (p->required) if (p->peerType == PeerType::Required)
requirePeer(p->id, n.endpoint); requirePeer(p->id, n.endpoint);
else else
m_nodeTable->addNode(*p.get(), NodeTable::NodeRelation::Known); m_nodeTable->addNode(*p.get(), NodeTable::NodeRelation::Known);

39
libp2p/Host.h

@ -47,11 +47,11 @@ namespace bi = ba::ip;
namespace std namespace std
{ {
template<> struct hash<pair<dev::p2p::NodeId, string>> template<> struct hash<pair<dev::p2p::NodeID, string>>
{ {
size_t operator()(pair<dev::p2p::NodeId, string> const& _value) const size_t operator()(pair<dev::p2p::NodeID, string> const& _value) const
{ {
size_t ret = hash<dev::p2p::NodeId>()(_value.first); size_t ret = hash<dev::p2p::NodeID>()(_value.first);
return ret ^ (hash<string>()(_value.second) + 0x9e3779b9 + (ret << 6) + (ret >> 2)); return ret ^ (hash<string>()(_value.second) + 0x9e3779b9 + (ret << 6) + (ret >> 2));
} }
}; };
@ -73,7 +73,7 @@ public:
Host const& host() const { return m_host; } Host const& host() const { return m_host; }
private: private:
virtual void processEvent(NodeId const& _n, NodeTableEventType const& _e); virtual void processEvent(NodeID const& _n, NodeTableEventType const& _e);
Host& m_host; Host& m_host;
}; };
@ -101,19 +101,19 @@ public:
bytes data(Session const& _s, std::string const& _subs) const; bytes data(Session const& _s, std::string const& _subs) const;
private: private:
std::unordered_map<std::pair<p2p::NodeId, std::string>, Reputation> m_nodes; ///< Nodes that were impolite while syncing. We avoid syncing from these if possible. std::unordered_map<std::pair<p2p::NodeID, std::string>, Reputation> m_nodes; ///< Nodes that were impolite while syncing. We avoid syncing from these if possible.
SharedMutex mutable x_nodes; SharedMutex mutable x_nodes;
}; };
struct NodeInfo struct NodeInfo
{ {
NodeInfo() = default; NodeInfo() = default;
NodeInfo(NodeId const& _id, std::string const& _address, unsigned _port, std::string const& _version): NodeInfo(NodeID const& _id, std::string const& _address, unsigned _port, std::string const& _version):
id(_id), address(_address), port(_port), version(_version) {} id(_id), address(_address), port(_port), version(_version) {}
std::string enode() const { return "enode://" + id.hex() + "@" + address + ":" + toString(port); } std::string enode() const { return "enode://" + id.hex() + "@" + address + ":" + toString(port); }
NodeId id; NodeID id;
std::string address; std::string address;
unsigned port; unsigned port;
std::string version; std::string version;
@ -156,17 +156,20 @@ public:
CapDescs caps() const { CapDescs ret; for (auto const& i: m_capabilities) ret.push_back(i.first); return ret; } CapDescs caps() const { CapDescs ret; for (auto const& i: m_capabilities) ret.push_back(i.first); return ret; }
template <class T> std::shared_ptr<T> cap() const { try { return std::static_pointer_cast<T>(m_capabilities.at(std::make_pair(T::staticName(), T::staticVersion()))); } catch (...) { return nullptr; } } template <class T> std::shared_ptr<T> cap() const { try { return std::static_pointer_cast<T>(m_capabilities.at(std::make_pair(T::staticName(), T::staticVersion()))); } catch (...) { return nullptr; } }
/// Add a potential peer.
void addPeer(NodeSpec const& _s, PeerType _t);
/// Add node as a peer candidate. Node is added if discovery ping is successful and table has capacity. /// Add node as a peer candidate. Node is added if discovery ping is successful and table has capacity.
void addNode(NodeId const& _node, NodeIPEndpoint const& _endpoint); void addNode(NodeID const& _node, NodeIPEndpoint const& _endpoint);
/// Create Peer and attempt keeping peer connected. /// Create Peer and attempt keeping peer connected.
void requirePeer(NodeId const& _node, NodeIPEndpoint const& _endpoint); void requirePeer(NodeID const& _node, NodeIPEndpoint const& _endpoint);
/// Create Peer and attempt keeping peer connected. /// Create Peer and attempt keeping peer connected.
void requirePeer(NodeId const& _node, bi::address const& _addr, unsigned short _udpPort, unsigned short _tcpPort) { requirePeer(_node, NodeIPEndpoint(_addr, _udpPort, _tcpPort)); } void requirePeer(NodeID const& _node, bi::address const& _addr, unsigned short _udpPort, unsigned short _tcpPort) { requirePeer(_node, NodeIPEndpoint(_addr, _udpPort, _tcpPort)); }
/// Note peer as no longer being required. /// Note peer as no longer being required.
void relinquishPeer(NodeId const& _node); void relinquishPeer(NodeID const& _node);
/// Set ideal number of peers. /// Set ideal number of peers.
void setIdealPeerCount(unsigned _n) { m_idealPeerCount = _n; } void setIdealPeerCount(unsigned _n) { m_idealPeerCount = _n; }
@ -216,10 +219,10 @@ public:
void startPeerSession(Public const& _id, RLP const& _hello, std::unique_ptr<RLPXFrameCoder>&& _io, std::shared_ptr<RLPXSocket> const& _s); void startPeerSession(Public const& _id, RLP const& _hello, std::unique_ptr<RLPXFrameCoder>&& _io, std::shared_ptr<RLPXSocket> const& _s);
/// Get session by id /// Get session by id
std::shared_ptr<Session> peerSession(NodeId const& _id) { RecursiveGuard l(x_sessions); return m_sessions.count(_id) ? m_sessions[_id].lock() : std::shared_ptr<Session>(); } std::shared_ptr<Session> peerSession(NodeID const& _id) { RecursiveGuard l(x_sessions); return m_sessions.count(_id) ? m_sessions[_id].lock() : std::shared_ptr<Session>(); }
/// Get our current node ID. /// Get our current node ID.
NodeId id() const { return m_alias.pub(); } NodeID id() const { return m_alias.pub(); }
/// Get the public TCP endpoint. /// Get the public TCP endpoint.
bi::tcp::endpoint const& tcpPublic() const { return m_tcpPublic; } bi::tcp::endpoint const& tcpPublic() const { return m_tcpPublic; }
@ -231,7 +234,7 @@ public:
p2p::NodeInfo nodeInfo() const { return NodeInfo(id(), (networkPreferences().publicIPAddress.empty() ? m_tcpPublic.address().to_string() : networkPreferences().publicIPAddress), m_tcpPublic.port(), m_clientVersion); } p2p::NodeInfo nodeInfo() const { return NodeInfo(id(), (networkPreferences().publicIPAddress.empty() ? m_tcpPublic.address().to_string() : networkPreferences().publicIPAddress), m_tcpPublic.port(), m_clientVersion); }
protected: protected:
void onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e); void onNodeTableEvent(NodeID const& _n, NodeTableEventType const& _e);
/// Deserialise the data and populate the set of known peers. /// Deserialise the data and populate the set of known peers.
void restoreNetwork(bytesConstRef _b); void restoreNetwork(bytesConstRef _b);
@ -241,7 +244,7 @@ private:
unsigned peerSlots(PeerSlotType _type) { return _type == Egress ? m_idealPeerCount : m_idealPeerCount * m_stretchPeers; } unsigned peerSlots(PeerSlotType _type) { return _type == Egress ? m_idealPeerCount : m_idealPeerCount * m_stretchPeers; }
bool havePeerSession(NodeId const& _id) { return !!peerSession(_id); } bool havePeerSession(NodeID const& _id) { return !!peerSession(_id); }
/// Determines and sets m_tcpPublic to publicly advertised address. /// Determines and sets m_tcpPublic to publicly advertised address.
void determinePublic(); void determinePublic();
@ -302,15 +305,15 @@ private:
std::shared_ptr<NodeTable> m_nodeTable; ///< Node table (uses kademlia-like discovery). std::shared_ptr<NodeTable> m_nodeTable; ///< Node table (uses kademlia-like discovery).
/// Shared storage of Peer objects. Peers are created or destroyed on demand by the Host. Active sessions maintain a shared_ptr to a Peer; /// Shared storage of Peer objects. Peers are created or destroyed on demand by the Host. Active sessions maintain a shared_ptr to a Peer;
std::unordered_map<NodeId, std::shared_ptr<Peer>> m_peers; std::unordered_map<NodeID, std::shared_ptr<Peer>> m_peers;
/// Peers we try to connect regardless of p2p network. /// Peers we try to connect regardless of p2p network.
std::set<NodeId> m_requiredPeers; std::set<NodeID> m_requiredPeers;
Mutex x_requiredPeers; Mutex x_requiredPeers;
/// The nodes to which we are currently connected. Used by host to service peer requests and keepAlivePeers and for shutdown. (see run()) /// The nodes to which we are currently connected. Used by host to service peer requests and keepAlivePeers and for shutdown. (see run())
/// Mutable because we flush zombie entries (null-weakptrs) as regular maintenance from a const method. /// Mutable because we flush zombie entries (null-weakptrs) as regular maintenance from a const method.
mutable std::unordered_map<NodeId, std::weak_ptr<Session>> m_sessions; mutable std::unordered_map<NodeID, std::weak_ptr<Session>> m_sessions;
mutable RecursiveMutex x_sessions; mutable RecursiveMutex x_sessions;
std::list<std::weak_ptr<RLPXHandshake>> m_connecting; ///< Pending connections. std::list<std::weak_ptr<RLPXHandshake>> m_connecting; ///< Pending connections.

18
libp2p/NodeTable.cpp

@ -38,7 +38,7 @@ const char* NodeTableAllDetail::name() { return "=P="; }
const char* NodeTableEgress::name() { return ">>P"; } const char* NodeTableEgress::name() { return ">>P"; }
const char* NodeTableIngress::name() { return "<<P"; } const char* NodeTableIngress::name() { return "<<P"; }
NodeEntry::NodeEntry(NodeId const& _src, Public const& _pubk, NodeIPEndpoint const& _gw): Node(_pubk, _gw), distance(NodeTable::distance(_src, _pubk)) {} NodeEntry::NodeEntry(NodeID const& _src, Public const& _pubk, NodeIPEndpoint const& _gw): Node(_pubk, _gw), distance(NodeTable::distance(_src, _pubk)) {}
NodeTable::NodeTable(ba::io_service& _io, KeyPair const& _alias, NodeIPEndpoint const& _endpoint, bool _enabled): NodeTable::NodeTable(ba::io_service& _io, KeyPair const& _alias, NodeIPEndpoint const& _endpoint, bool _enabled):
m_node(Node(_alias.pub(), _endpoint)), m_node(Node(_alias.pub(), _endpoint)),
@ -115,9 +115,9 @@ shared_ptr<NodeEntry> NodeTable::addNode(Node const& _node, NodeRelation _relati
return ret; return ret;
} }
list<NodeId> NodeTable::nodes() const list<NodeID> NodeTable::nodes() const
{ {
list<NodeId> nodes; list<NodeID> nodes;
DEV_GUARDED(x_nodes) DEV_GUARDED(x_nodes)
for (auto& i: m_nodes) for (auto& i: m_nodes)
nodes.push_back(i.second->id); nodes.push_back(i.second->id);
@ -135,24 +135,24 @@ list<NodeEntry> NodeTable::snapshot() const
return ret; return ret;
} }
Node NodeTable::node(NodeId const& _id) Node NodeTable::node(NodeID const& _id)
{ {
Guard l(x_nodes); Guard l(x_nodes);
if (m_nodes.count(_id)) if (m_nodes.count(_id))
{ {
auto entry = m_nodes[_id]; auto entry = m_nodes[_id];
return Node(_id, entry->endpoint, entry->required); return Node(_id, entry->endpoint, entry->peerType);
} }
return UnspecifiedNode; return UnspecifiedNode;
} }
shared_ptr<NodeEntry> NodeTable::nodeEntry(NodeId _id) shared_ptr<NodeEntry> NodeTable::nodeEntry(NodeID _id)
{ {
Guard l(x_nodes); Guard l(x_nodes);
return m_nodes.count(_id) ? m_nodes[_id] : shared_ptr<NodeEntry>(); return m_nodes.count(_id) ? m_nodes[_id] : shared_ptr<NodeEntry>();
} }
void NodeTable::doDiscover(NodeId _node, unsigned _round, shared_ptr<set<shared_ptr<NodeEntry>>> _tried) void NodeTable::doDiscover(NodeID _node, unsigned _round, shared_ptr<set<shared_ptr<NodeEntry>>> _tried)
{ {
// NOTE: ONLY called by doDiscovery! // NOTE: ONLY called by doDiscovery!
@ -214,7 +214,7 @@ void NodeTable::doDiscover(NodeId _node, unsigned _round, shared_ptr<set<shared_
}); });
} }
vector<shared_ptr<NodeEntry>> NodeTable::nearestNodeEntries(NodeId _target) vector<shared_ptr<NodeEntry>> NodeTable::nearestNodeEntries(NodeID _target)
{ {
// send s_alpha FindNode packets to nodes we know, closest to target // send s_alpha FindNode packets to nodes we know, closest to target
static unsigned lastBin = s_bins - 1; static unsigned lastBin = s_bins - 1;
@ -611,7 +611,7 @@ void NodeTable::doDiscovery()
return; return;
clog(NodeTableEvent) << "performing random discovery"; clog(NodeTableEvent) << "performing random discovery";
NodeId randNodeId; NodeID randNodeId;
crypto::Nonce::get().ref().copyTo(randNodeId.ref().cropped(0, h256::size)); crypto::Nonce::get().ref().copyTo(randNodeId.ref().cropped(0, h256::size));
crypto::Nonce::get().ref().copyTo(randNodeId.ref().cropped(h256::size, h256::size)); crypto::Nonce::get().ref().copyTo(randNodeId.ref().cropped(h256::size, h256::size));
doDiscover(randNodeId); doDiscover(randNodeId);

40
libp2p/NodeTable.h

@ -40,7 +40,7 @@ namespace p2p
*/ */
struct NodeEntry: public Node struct NodeEntry: public Node
{ {
NodeEntry(NodeId const& _src, Public const& _pubk, NodeIPEndpoint const& _gw); NodeEntry(NodeID const& _src, Public const& _pubk, NodeIPEndpoint const& _gw);
unsigned const distance; ///< Node's distance (xor of _src as integer). unsigned const distance; ///< Node's distance (xor of _src as integer).
bool pending = true; ///< Node will be ignored until Pong is received bool pending = true; ///< Node will be ignored until Pong is received
}; };
@ -56,13 +56,13 @@ class NodeTableEventHandler
{ {
friend class NodeTable; friend class NodeTable;
public: public:
virtual void processEvent(NodeId const& _n, NodeTableEventType const& _e) = 0; virtual void processEvent(NodeID const& _n, NodeTableEventType const& _e) = 0;
protected: protected:
/// Called by NodeTable on behalf of an implementation (Host) to process new events without blocking nodetable. /// Called by NodeTable on behalf of an implementation (Host) to process new events without blocking nodetable.
void processEvents() void processEvents()
{ {
std::list<std::pair<NodeId, NodeTableEventType>> events; std::list<std::pair<NodeID, NodeTableEventType>> events;
{ {
Guard l(x_events); Guard l(x_events);
if (!m_nodeEventHandler.size()) if (!m_nodeEventHandler.size())
@ -78,11 +78,11 @@ protected:
} }
/// Called by NodeTable to append event. /// Called by NodeTable to append event.
virtual void appendEvent(NodeId _n, NodeTableEventType _e) { Guard l(x_events); m_nodeEventHandler.push_back(_n); m_events[_n] = _e; } virtual void appendEvent(NodeID _n, NodeTableEventType _e) { Guard l(x_events); m_nodeEventHandler.push_back(_n); m_events[_n] = _e; }
Mutex x_events; Mutex x_events;
std::list<NodeId> m_nodeEventHandler; std::list<NodeID> m_nodeEventHandler;
std::unordered_map<NodeId, NodeTableEventType> m_events; std::unordered_map<NodeID, NodeTableEventType> m_events;
}; };
class NodeTable; class NodeTable;
@ -123,8 +123,8 @@ class NodeTable: UDPSocketEvents, public std::enable_shared_from_this<NodeTable>
friend std::ostream& operator<<(std::ostream& _out, NodeTable const& _nodeTable); friend std::ostream& operator<<(std::ostream& _out, NodeTable const& _nodeTable);
using NodeSocket = UDPSocket<NodeTable, 1280>; using NodeSocket = UDPSocket<NodeTable, 1280>;
using TimePoint = std::chrono::steady_clock::time_point; ///< Steady time point. using TimePoint = std::chrono::steady_clock::time_point; ///< Steady time point.
using NodeIdTimePoint = std::pair<NodeId, TimePoint>; using NodeIdTimePoint = std::pair<NodeID, TimePoint>;
using EvictionTimeout = std::pair<NodeIdTimePoint, NodeId>; ///< First NodeId (NodeIdTimePoint) may be evicted and replaced with second NodeId. using EvictionTimeout = std::pair<NodeIdTimePoint, NodeID>; ///< First NodeID (NodeIdTimePoint) may be evicted and replaced with second NodeID.
public: public:
enum NodeRelation { Unknown = 0, Known }; enum NodeRelation { Unknown = 0, Known };
@ -135,7 +135,7 @@ public:
~NodeTable(); ~NodeTable();
/// Returns distance based on xor metric two node ids. Used by NodeEntry and NodeTable. /// Returns distance based on xor metric two node ids. Used by NodeEntry and NodeTable.
static unsigned distance(NodeId const& _a, NodeId const& _b) { u256 d = sha3(_a) ^ sha3(_b); unsigned ret; for (ret = 0; d >>= 1; ++ret) {}; return ret; } static unsigned distance(NodeID const& _a, NodeID const& _b) { u256 d = sha3(_a) ^ sha3(_b); unsigned ret; for (ret = 0; d >>= 1; ++ret) {}; return ret; }
/// Set event handler for NodeEntryAdded and NodeEntryDropped events. /// Set event handler for NodeEntryAdded and NodeEntryDropped events.
void setEventHandler(NodeTableEventHandler* _handler) { m_nodeEventHandler.reset(_handler); } void setEventHandler(NodeTableEventHandler* _handler) { m_nodeEventHandler.reset(_handler); }
@ -143,11 +143,11 @@ public:
/// Called by implementation which provided handler to process NodeEntryAdded/NodeEntryDropped events. Events are coalesced by type whereby old events are ignored. /// Called by implementation which provided handler to process NodeEntryAdded/NodeEntryDropped events. Events are coalesced by type whereby old events are ignored.
void processEvents(); void processEvents();
/// Add node. Node will be pinged and empty shared_ptr is returned if node has never been seen or NodeId is empty. /// Add node. Node will be pinged and empty shared_ptr is returned if node has never been seen or NodeID is empty.
std::shared_ptr<NodeEntry> addNode(Node const& _node, NodeRelation _relation = NodeRelation::Unknown); std::shared_ptr<NodeEntry> addNode(Node const& _node, NodeRelation _relation = NodeRelation::Unknown);
/// Returns list of node ids active in node table. /// Returns list of node ids active in node table.
std::list<NodeId> nodes() const; std::list<NodeID> nodes() const;
/// Returns node count. /// Returns node count.
unsigned count() const { return m_nodes.size(); } unsigned count() const { return m_nodes.size(); }
@ -156,10 +156,10 @@ public:
std::list<NodeEntry> snapshot() const; std::list<NodeEntry> snapshot() const;
/// Returns true if node id is in node table. /// Returns true if node id is in node table.
bool haveNode(NodeId const& _id) { Guard l(x_nodes); return m_nodes.count(_id) > 0; } bool haveNode(NodeID const& _id) { Guard l(x_nodes); return m_nodes.count(_id) > 0; }
/// Returns the Node to the corresponding node id or the empty Node if that id is not found. /// Returns the Node to the corresponding node id or the empty Node if that id is not found.
Node node(NodeId const& _id); Node node(NodeID const& _id);
#if defined(BOOST_AUTO_TEST_SUITE) || defined(_MSC_VER) // MSVC includes access specifier in symbol name #if defined(BOOST_AUTO_TEST_SUITE) || defined(_MSC_VER) // MSVC includes access specifier in symbol name
protected: protected:
@ -202,14 +202,14 @@ private:
NodeEntry center() const { return NodeEntry(m_node.id, m_node.publicKey(), m_node.endpoint); } NodeEntry center() const { return NodeEntry(m_node.id, m_node.publicKey(), m_node.endpoint); }
/// Used by asynchronous operations to return NodeEntry which is active and managed by node table. /// Used by asynchronous operations to return NodeEntry which is active and managed by node table.
std::shared_ptr<NodeEntry> nodeEntry(NodeId _id); std::shared_ptr<NodeEntry> nodeEntry(NodeID _id);
/// Used to discovery nodes on network which are close to the given target. /// Used to discovery nodes on network which are close to the given target.
/// Sends s_alpha concurrent requests to nodes nearest to target, for nodes nearest to target, up to s_maxSteps rounds. /// Sends s_alpha concurrent requests to nodes nearest to target, for nodes nearest to target, up to s_maxSteps rounds.
void doDiscover(NodeId _target, unsigned _round = 0, std::shared_ptr<std::set<std::shared_ptr<NodeEntry>>> _tried = std::shared_ptr<std::set<std::shared_ptr<NodeEntry>>>()); void doDiscover(NodeID _target, unsigned _round = 0, std::shared_ptr<std::set<std::shared_ptr<NodeEntry>>> _tried = std::shared_ptr<std::set<std::shared_ptr<NodeEntry>>>());
/// Returns nodes from node table which are closest to target. /// Returns nodes from node table which are closest to target.
std::vector<std::shared_ptr<NodeEntry>> nearestNodeEntries(NodeId _target); std::vector<std::shared_ptr<NodeEntry>> nearestNodeEntries(NodeID _target);
/// Asynchronously drops _leastSeen node if it doesn't reply and adds _new node, otherwise _new node is thrown away. /// Asynchronously drops _leastSeen node if it doesn't reply and adds _new node, otherwise _new node is thrown away.
void evict(std::shared_ptr<NodeEntry> _leastSeen, std::shared_ptr<NodeEntry> _new); void evict(std::shared_ptr<NodeEntry> _leastSeen, std::shared_ptr<NodeEntry> _new);
@ -247,7 +247,7 @@ private:
Secret m_secret; ///< This nodes secret key. Secret m_secret; ///< This nodes secret key.
mutable Mutex x_nodes; ///< LOCK x_state first if both locks are required. Mutable for thread-safe copy in nodes() const. mutable Mutex x_nodes; ///< LOCK x_state first if both locks are required. Mutable for thread-safe copy in nodes() const.
std::unordered_map<NodeId, std::shared_ptr<NodeEntry>> m_nodes; ///< Known Node Endpoints std::unordered_map<NodeID, std::shared_ptr<NodeEntry>> m_nodes; ///< Known Node Endpoints
mutable Mutex x_state; ///< LOCK x_state first if both x_nodes and x_state locks are required. mutable Mutex x_state; ///< LOCK x_state first if both x_nodes and x_state locks are required.
std::array<NodeBucket, s_bins> m_state; ///< State of p2p node network. std::array<NodeBucket, s_bins> m_state; ///< State of p2p node network.
@ -333,13 +333,13 @@ struct Pong: RLPXDatagram<Pong>
* Minimum Encoded Size: 21 bytes * Minimum Encoded Size: 21 bytes
* Maximum Encoded Size: 30 bytes * Maximum Encoded Size: 30 bytes
* *
* target: NodeId of node. The responding node will send back nodes closest to the target. * target: NodeID of node. The responding node will send back nodes closest to the target.
* *
*/ */
struct FindNode: RLPXDatagram<FindNode> struct FindNode: RLPXDatagram<FindNode>
{ {
FindNode(bi::udp::endpoint _ep): RLPXDatagram<FindNode>(_ep) {} FindNode(bi::udp::endpoint _ep): RLPXDatagram<FindNode>(_ep) {}
FindNode(bi::udp::endpoint _ep, NodeId _target): RLPXDatagram<FindNode>(_ep), target(_target), ts(futureFromEpoch(std::chrono::seconds(60))) {} FindNode(bi::udp::endpoint _ep, NodeID _target): RLPXDatagram<FindNode>(_ep), target(_target), ts(futureFromEpoch(std::chrono::seconds(60))) {}
static const uint8_t type = 3; static const uint8_t type = 3;
@ -360,7 +360,7 @@ struct Neighbours: RLPXDatagram<Neighbours>
Neighbour(Node const& _node): endpoint(_node.endpoint), node(_node.id) {} Neighbour(Node const& _node): endpoint(_node.endpoint), node(_node.id) {}
Neighbour(RLP const& _r): endpoint(_r) { node = h512(_r[3].toBytes()); } Neighbour(RLP const& _r): endpoint(_r) { node = h512(_r[3].toBytes()); }
NodeIPEndpoint endpoint; NodeIPEndpoint endpoint;
NodeId node; NodeID node;
void streamRLP(RLPStream& _s) const { _s.appendList(4); endpoint.streamRLP(_s, NodeIPEndpoint::StreamInline); _s << node; } void streamRLP(RLPStream& _s) const { _s.appendList(4); endpoint.streamRLP(_s, NodeIPEndpoint::StreamInline); _s << node; }
}; };

2
libp2p/Peer.cpp

@ -38,7 +38,7 @@ bool Peer::shouldReconnect() const
unsigned Peer::fallbackSeconds() const unsigned Peer::fallbackSeconds() const
{ {
if (required) if (peerType == PeerType::Required)
return 5; return 5;
switch (m_lastDisconnect) switch (m_lastDisconnect)
{ {

2
libp2p/Peer.h

@ -58,7 +58,7 @@ class Peer: public Node
public: public:
/// Construct Peer from Node. /// Construct Peer from Node.
Peer(Node const& _node): Node(_node.id, _node.endpoint, _node.required) {} Peer(Node const& _node): Node(_node) {}
bool isOffline() const { return !m_session.lock(); } bool isOffline() const { return !m_session.lock(); }

4
libp2p/RLPxHandshake.h

@ -66,7 +66,7 @@ public:
RLPXHandshake(Host* _host, std::shared_ptr<RLPXSocket> const& _socket): m_host(_host), m_originated(false), m_socket(_socket), m_idleTimer(m_socket->ref().get_io_service()) { crypto::Nonce::get().ref().copyTo(m_nonce.ref()); } RLPXHandshake(Host* _host, std::shared_ptr<RLPXSocket> const& _socket): m_host(_host), m_originated(false), m_socket(_socket), m_idleTimer(m_socket->ref().get_io_service()) { crypto::Nonce::get().ref().copyTo(m_nonce.ref()); }
/// Setup outbound connection. /// Setup outbound connection.
RLPXHandshake(Host* _host, std::shared_ptr<RLPXSocket> const& _socket, NodeId _remote): m_host(_host), m_remote(_remote), m_originated(true), m_socket(_socket), m_idleTimer(m_socket->ref().get_io_service()) { crypto::Nonce::get().ref().copyTo(m_nonce.ref()); } RLPXHandshake(Host* _host, std::shared_ptr<RLPXSocket> const& _socket, NodeID _remote): m_host(_host), m_remote(_remote), m_originated(true), m_socket(_socket), m_idleTimer(m_socket->ref().get_io_service()) { crypto::Nonce::get().ref().copyTo(m_nonce.ref()); }
~RLPXHandshake() {} ~RLPXHandshake() {}
@ -104,7 +104,7 @@ protected:
Host* m_host; ///< Host which provides m_alias, protocolVersion(), m_clientVersion, caps(), and TCP listenPort(). Host* m_host; ///< Host which provides m_alias, protocolVersion(), m_clientVersion, caps(), and TCP listenPort().
/// Node id of remote host for socket. /// Node id of remote host for socket.
NodeId m_remote; ///< Public address of remote host. NodeID m_remote; ///< Public address of remote host.
bool m_originated = false; ///< True if connection is outbound. bool m_originated = false; ///< True if connection is outbound.
/// Buffers for encoded and decoded handshake phases /// Buffers for encoded and decoded handshake phases

4
libp2p/Session.cpp

@ -76,9 +76,9 @@ ReputationManager& Session::repMan() const
return m_server->repMan(); return m_server->repMan();
} }
NodeId Session::id() const NodeID Session::id() const
{ {
return m_peer ? m_peer->id : NodeId(); return m_peer ? m_peer->id : NodeID();
} }
void Session::addRating(int _r) void Session::addRating(int _r)

2
libp2p/Session.h

@ -65,7 +65,7 @@ public:
bool isConnected() const { return m_socket->ref().is_open(); } bool isConnected() const { return m_socket->ref().is_open(); }
NodeId id() const; NodeID id() const;
unsigned socketId() const { Guard l(x_info); return m_info.socketId; } unsigned socketId() const { Guard l(x_info); return m_info.socketId; }
template <class PeerCap> template <class PeerCap>

14
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -525,19 +525,7 @@ bool WebThreeStubServerBase::admin_net_stop(std::string const& _session)
bool WebThreeStubServerBase::admin_net_connect(std::string const& _node, std::string const& _session) bool WebThreeStubServerBase::admin_net_connect(std::string const& _node, std::string const& _session)
{ {
ADMIN; ADMIN;
p2p::NodeId id; network()->addPeer(p2p::NodeSpec(_node), p2p::PeerType::Required);
bi::tcp::endpoint ep;
if (_node.substr(0, 8) == "enode://" && _node.find('@') == 136)
{
id = p2p::NodeId(_node.substr(8, 128));
ep = p2p::Network::resolveHost(_node.substr(137));
}
else
ep = p2p::Network::resolveHost(_node);
if (ep == bi::tcp::endpoint())
return false;
network()->requirePeer(id, ep);
return true; return true;
} }

8
libwebthree/WebThree.cpp

@ -128,14 +128,18 @@ bytes WebThreeDirect::saveNetwork()
return m_net.saveNetwork(); return m_net.saveNetwork();
} }
void WebThreeDirect::addNode(NodeId const& _node, bi::tcp::endpoint const& _host) void WebThreeDirect::addNode(NodeID const& _node, bi::tcp::endpoint const& _host)
{ {
m_net.addNode(_node, NodeIPEndpoint(_host.address(), _host.port(), _host.port())); m_net.addNode(_node, NodeIPEndpoint(_host.address(), _host.port(), _host.port()));
} }
void WebThreeDirect::requirePeer(NodeId const& _node, bi::tcp::endpoint const& _host) void WebThreeDirect::requirePeer(NodeID const& _node, bi::tcp::endpoint const& _host)
{ {
m_net.requirePeer(_node, NodeIPEndpoint(_host.address(), _host.port(), _host.port())); m_net.requirePeer(_node, NodeIPEndpoint(_host.address(), _host.port(), _host.port()));
} }
void WebThreeDirect::addPeer(NodeSpec const& _s, PeerType _t)
{
m_net.addPeer(_s, _t);
}

26
libwebthree/WebThree.h

@ -62,11 +62,14 @@ public:
/// Same as peers().size(), but more efficient. /// Same as peers().size(), but more efficient.
virtual size_t peerCount() const = 0; virtual size_t peerCount() const = 0;
/// Generalised peer addition.
virtual void addPeer(p2p::NodeSpec const& _node, p2p::PeerType _t) = 0;
/// Add node to connect to. /// Add node to connect to.
virtual void addNode(p2p::NodeId const& _node, bi::tcp::endpoint const& _hostEndpoint) = 0; virtual void addNode(p2p::NodeID const& _node, bi::tcp::endpoint const& _hostEndpoint) = 0;
/// Require connection to peer. /// Require connection to peer.
virtual void requirePeer(p2p::NodeId const& _node, bi::tcp::endpoint const& _endpoint) = 0; virtual void requirePeer(p2p::NodeID const& _node, bi::tcp::endpoint const& _endpoint) = 0;
/// Save peers /// Save peers
virtual dev::bytes saveNetwork() = 0; virtual dev::bytes saveNetwork() = 0;
@ -79,7 +82,7 @@ public:
virtual p2p::NetworkPreferences const& networkPreferences() const = 0; virtual p2p::NetworkPreferences const& networkPreferences() const = 0;
virtual void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers) = 0; virtual void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers) = 0;
virtual p2p::NodeId id() const = 0; virtual p2p::NodeID id() const = 0;
/// Gets the nodes. /// Gets the nodes.
virtual p2p::Peers nodes() const = 0; virtual p2p::Peers nodes() const = 0;
@ -147,23 +150,26 @@ public:
/// Same as peers().size(), but more efficient. /// Same as peers().size(), but more efficient.
size_t peerCount() const override; size_t peerCount() const override;
/// Generalised peer addition.
virtual void addPeer(p2p::NodeSpec const& _node, p2p::PeerType _t) override;
/// Add node to connect to. /// Add node to connect to.
virtual void addNode(p2p::NodeId const& _node, bi::tcp::endpoint const& _hostEndpoint) override; virtual void addNode(p2p::NodeID const& _node, bi::tcp::endpoint const& _hostEndpoint) override;
/// Add node to connect to. /// Add node to connect to.
void addNode(p2p::NodeId const& _node, std::string const& _hostString) { addNode(_node, p2p::Network::resolveHost(_hostString)); } void addNode(p2p::NodeID const& _node, std::string const& _hostString) { addNode(_node, p2p::Network::resolveHost(_hostString)); }
/// Add node to connect to. /// Add node to connect to.
void addNode(bi::tcp::endpoint const& _endpoint) { addNode(p2p::NodeId(), _endpoint); } void addNode(bi::tcp::endpoint const& _endpoint) { addNode(p2p::NodeID(), _endpoint); }
/// Add node to connect to. /// Add node to connect to.
void addNode(std::string const& _hostString) { addNode(p2p::NodeId(), _hostString); } void addNode(std::string const& _hostString) { addNode(p2p::NodeID(), _hostString); }
/// Require connection to peer. /// Require connection to peer.
void requirePeer(p2p::NodeId const& _node, bi::tcp::endpoint const& _endpoint) override; void requirePeer(p2p::NodeID const& _node, bi::tcp::endpoint const& _endpoint) override;
/// Require connection to peer. /// Require connection to peer.
void requirePeer(p2p::NodeId const& _node, std::string const& _hostString) { requirePeer(_node, p2p::Network::resolveHost(_hostString)); } void requirePeer(p2p::NodeID const& _node, std::string const& _hostString) { requirePeer(_node, p2p::Network::resolveHost(_hostString)); }
/// Save peers /// Save peers
dev::bytes saveNetwork() override; dev::bytes saveNetwork() override;
@ -182,7 +188,7 @@ public:
p2p::NodeInfo nodeInfo() const override { return m_net.nodeInfo(); } p2p::NodeInfo nodeInfo() const override { return m_net.nodeInfo(); }
p2p::NodeId id() const override { return m_net.id(); } p2p::NodeID id() const override { return m_net.id(); }
std::string enode() const override { return m_net.enode(); } std::string enode() const override { return m_net.enode(); }

14
mix/Web3Server.cpp

@ -44,13 +44,19 @@ class EmptyNetwork : public dev::WebThreeNetworkFace
return 0; return 0;
} }
void addNode(p2p::NodeId const& _node, bi::tcp::endpoint const& _hostEndpoint) override void addPeer(p2p::NodeSpec const& _node, p2p::PeerType _t) override
{
(void)_node;
(void)_t;
}
void addNode(p2p::NodeID const& _node, bi::tcp::endpoint const& _hostEndpoint) override
{ {
(void)_node; (void)_node;
(void)_hostEndpoint; (void)_hostEndpoint;
} }
void requirePeer(p2p::NodeId const& _node, bi::tcp::endpoint const& _endpoint) override void requirePeer(p2p::NodeID const& _node, bi::tcp::endpoint const& _endpoint) override
{ {
(void)_node; (void)_node;
(void)_endpoint; (void)_endpoint;
@ -87,9 +93,9 @@ class EmptyNetwork : public dev::WebThreeNetworkFace
std::string enode() const override { return ""; } std::string enode() const override { return ""; }
p2p::NodeId id() const override p2p::NodeID id() const override
{ {
return p2p::NodeId(); return p2p::NodeID();
} }
p2p::Peers nodes() const override p2p::Peers nodes() const override

4
test/libp2p/capability.cpp

@ -73,14 +73,14 @@ public:
TestHostCapability(): Worker("test") {} TestHostCapability(): Worker("test") {}
virtual ~TestHostCapability() {} virtual ~TestHostCapability() {}
void sendTestMessage(NodeId const& _id, int _x) void sendTestMessage(NodeID const& _id, int _x)
{ {
for (auto i: peerSessions()) for (auto i: peerSessions())
if (_id == i.second->id) if (_id == i.second->id)
i.first->cap<TestCapability>().get()->sendTestMessage(_x); i.first->cap<TestCapability>().get()->sendTestMessage(_x);
} }
std::pair<int, int> retrieveTestData(NodeId const& _id) std::pair<int, int> retrieveTestData(NodeID const& _id)
{ {
int cnt = 0; int cnt = 0;
int checksum = 0; int checksum = 0;

8
test/libp2p/net.cpp

@ -159,13 +159,13 @@ BOOST_AUTO_TEST_CASE(requestTimeout)
return; return;
using TimePoint = std::chrono::steady_clock::time_point; using TimePoint = std::chrono::steady_clock::time_point;
using RequestTimeout = std::pair<NodeId, TimePoint>; using RequestTimeout = std::pair<NodeID, TimePoint>;
std::chrono::milliseconds timeout(300); std::chrono::milliseconds timeout(300);
std::list<RequestTimeout> timeouts; std::list<RequestTimeout> timeouts;
NodeId nodeA(sha3("a")); NodeID nodeA(sha3("a"));
NodeId nodeB(sha3("b")); NodeID nodeB(sha3("b"));
timeouts.push_back(make_pair(nodeA, chrono::steady_clock::now())); timeouts.push_back(make_pair(nodeA, chrono::steady_clock::now()));
this_thread::sleep_for(std::chrono::milliseconds(100)); this_thread::sleep_for(std::chrono::milliseconds(100));
timeouts.push_back(make_pair(nodeB, chrono::steady_clock::now())); timeouts.push_back(make_pair(nodeB, chrono::steady_clock::now()));
@ -385,7 +385,7 @@ BOOST_AUTO_TEST_CASE(nodeTableReturnsUnspecifiedNode)
ba::io_service io; ba::io_service io;
NodeTable t(io, KeyPair::create(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), 30303, 30303)); NodeTable t(io, KeyPair::create(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), 30303, 30303));
if (Node n = t.node(NodeId())) if (Node n = t.node(NodeID()))
BOOST_REQUIRE(false); BOOST_REQUIRE(false);
else else
BOOST_REQUIRE(n == UnspecifiedNode); BOOST_REQUIRE(n == UnspecifiedNode);

6
test/libp2p/peer.cpp

@ -217,15 +217,15 @@ BOOST_AUTO_TEST_CASE(emptySharedPeer)
shared_ptr<Peer> p; shared_ptr<Peer> p;
BOOST_REQUIRE(!p); BOOST_REQUIRE(!p);
std::map<NodeId, std::shared_ptr<Peer>> peers; std::map<NodeID, std::shared_ptr<Peer>> peers;
p = peers[NodeId()]; p = peers[NodeID()];
BOOST_REQUIRE(!p); BOOST_REQUIRE(!p);
p.reset(new Peer(UnspecifiedNode)); p.reset(new Peer(UnspecifiedNode));
BOOST_REQUIRE(!p->id); BOOST_REQUIRE(!p->id);
BOOST_REQUIRE(!*p); BOOST_REQUIRE(!*p);
p.reset(new Peer(Node(NodeId(EmptySHA3), UnspecifiedNodeIPEndpoint))); p.reset(new Peer(Node(NodeID(EmptySHA3), UnspecifiedNodeIPEndpoint)));
BOOST_REQUIRE(!(!*p)); BOOST_REQUIRE(!(!*p));
BOOST_REQUIRE(*p); BOOST_REQUIRE(*p);
BOOST_REQUIRE(p); BOOST_REQUIRE(p);

Loading…
Cancel
Save