subtly
10 years ago
207 changed files with 12975 additions and 5537 deletions
@ -0,0 +1,123 @@ |
|||
<?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> |
@ -0,0 +1,322 @@ |
|||
# - Find the Windows SDK aka Platform SDK |
|||
# |
|||
# Relevant Wikipedia article: http://en.wikipedia.org/wiki/Microsoft_Windows_SDK |
|||
# |
|||
# Variables: |
|||
# WINDOWSSDK_FOUND - if any version of the windows or platform SDK was found that is usable with the current version of visual studio |
|||
# WINDOWSSDK_LATEST_DIR |
|||
# WINDOWSSDK_LATEST_NAME |
|||
# WINDOWSSDK_FOUND_PREFERENCE - if we found an entry indicating a "preferred" SDK listed for this visual studio version |
|||
# WINDOWSSDK_PREFERRED_DIR |
|||
# WINDOWSSDK_PREFERRED_NAME |
|||
# |
|||
# WINDOWSSDK_DIRS - contains no duplicates, ordered most recent first. |
|||
# WINDOWSSDK_PREFERRED_FIRST_DIRS - contains no duplicates, ordered with preferred first, followed by the rest in descending recency |
|||
# |
|||
# Functions: |
|||
# windowssdk_name_lookup(<directory> <output variable>) - Find the name corresponding with the SDK directory you pass in, or |
|||
# NOTFOUND if not recognized. Your directory must be one of WINDOWSSDK_DIRS for this to work. |
|||
# |
|||
# get_windowssdk_from_component(<file or dir> <output variable>) - Given a library or include dir, |
|||
# find the Windows SDK root dir corresponding to it, or NOTFOUND if unrecognized. |
|||
# |
|||
# get_windowssdk_library_dirs(<directory> <output variable>) - Find the architecture-appropriate |
|||
# library directories corresponding to the SDK directory you pass in (or NOTFOUND if none) |
|||
# |
|||
# get_windowssdk_include_dirs(<directory> <output variable>) - Find the |
|||
# include directories corresponding to the SDK directory you pass in (or NOTFOUND if none) |
|||
# |
|||
# Requires these CMake modules: |
|||
# FindPackageHandleStandardArgs (known included with CMake >=2.6.2) |
|||
# |
|||
# Original Author: |
|||
# 2012 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net> |
|||
# http://academic.cleardefinition.com |
|||
# Iowa State University HCI Graduate Program/VRAC |
|||
# |
|||
# Copyright Iowa State University 2012. |
|||
# Distributed under the Boost Software License, Version 1.0. |
|||
# (See accompanying file LICENSE_1_0.txt or copy at |
|||
# http://www.boost.org/LICENSE_1_0.txt) |
|||
|
|||
set(_preferred_sdk_dirs) |
|||
set(_win_sdk_dirs) |
|||
set(_win_sdk_versanddirs) |
|||
if(MSVC_VERSION GREATER 1310) # Newer than VS .NET/VS Toolkit 2003 |
|||
|
|||
# Environment variable for SDK dir |
|||
if(EXISTS "$ENV{WindowsSDKDir}" AND (NOT "$ENV{WindowsSDKDir}" STREQUAL "")) |
|||
message(STATUS "Got $ENV{WindowsSDKDir} - Windows/Platform SDK directories: ${_win_sdk_dirs}") |
|||
list(APPEND _preferred_sdk_dirs "$ENV{WindowsSDKDir}") |
|||
endif() |
|||
|
|||
if(MSVC_VERSION LESS 1600) |
|||
# Per-user current Windows SDK for VS2005/2008 |
|||
get_filename_component(_sdkdir |
|||
"[HKEY_CURRENT_USER\\Software\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" |
|||
ABSOLUTE) |
|||
if(EXISTS "${_sdkdir}") |
|||
list(APPEND _preferred_sdk_dirs "${_sdkdir}") |
|||
endif() |
|||
|
|||
# System-wide current Windows SDK for VS2005/2008 |
|||
get_filename_component(_sdkdir |
|||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" |
|||
ABSOLUTE) |
|||
if(EXISTS "${_sdkdir}") |
|||
list(APPEND _preferred_sdk_dirs "${_sdkdir}") |
|||
endif() |
|||
endif() |
|||
|
|||
if(MSVC_VERSION LESS 1700) |
|||
# VC 10 and older has broad target support |
|||
set(_winsdk_vistaonly) |
|||
else() |
|||
# VC 11 by default targets Vista and later only, so we can add a few more SDKs that (might?) only work on vista+ |
|||
if("${CMAKE_VS_PLATFORM_TOOLSET}" MATCHES "_xp") |
|||
# This is the XP-compatible v110 toolset |
|||
elseif("${CMAKE_VS_PLATFORM_TOOLSET}" STREQUAL "v100") |
|||
# This is the VS2010 toolset |
|||
else() |
|||
if(NOT WINDOWSSDK_FOUND AND NOT WindowsSDK_FIND_QUIETLY) |
|||
message(STATUS "FindWindowsSDK: Detected Visual Studio 2012 or newer, not using the _xp toolset variant: including SDK versions that drop XP support in search!") |
|||
endif() |
|||
# These versions have no XP (and possibly Vista pre-SP1) support |
|||
set(_winsdk_vistaonly) |
|||
if(NOT MSVC_VERSION LESS 1800) |
|||
list(APPEND _winsdk_vistaonly |
|||
# Windows Software Development Kit (SDK) for Windows 8.1 |
|||
# http://msdn.microsoft.com/en-gb/windows/desktop/bg162891 |
|||
v8.1) |
|||
endif() |
|||
list(APPEND _winsdk_vistaonly |
|||
# Included in Visual Studio 2012 |
|||
v8.0A |
|||
|
|||
# Microsoft Windows SDK for Windows 8 and .NET Framework 4.5 |
|||
# This is the first version to also include the DirectX SDK |
|||
# http://msdn.microsoft.com/en-US/windows/desktop/hh852363.aspx |
|||
v8.0 |
|||
|
|||
# Microsoft Windows SDK for Windows 7 and .NET Framework 4 |
|||
# http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b |
|||
v7.1 |
|||
) |
|||
endif() |
|||
endif() |
|||
foreach(_winsdkver |
|||
${_winsdk_vistaonly} |
|||
|
|||
# Included in Visual Studio 2013 |
|||
# Includes the v120_xp toolset |
|||
v8.1A |
|||
|
|||
# Included with VS 2012 Update 1 or later |
|||
# Introduces v110_xp toolset |
|||
v7.1A |
|||
|
|||
# Included with VS 2010 |
|||
v7.0A |
|||
|
|||
# Windows SDK for Windows 7 and .NET Framework 3.5 SP1 |
|||
# Works with VC9 |
|||
#http://www.microsoft.com/en-us/download/details.aspx?id=18950 |
|||
v7.0 |
|||
|
|||
# Two versions call themselves "v6.1": |
|||
# Older: |
|||
# Windows Vista Update & .NET 3.0 SDK |
|||
# http://www.microsoft.com/en-us/download/details.aspx?id=14477 |
|||
|
|||
# Newer: |
|||
# Windows Server 2008 & .NET 3.5 SDK |
|||
# may have broken VS9SP1? they recommend v7.0 instead, or a KB... |
|||
# http://www.microsoft.com/en-us/download/details.aspx?id=24826 |
|||
v6.1 |
|||
|
|||
# Included in VS 2008 |
|||
v6.0A |
|||
|
|||
# Microsoft Windows Software Development Kit for Windows Vista and .NET Framework 3.0 Runtime Components |
|||
# http://blogs.msdn.com/b/stanley/archive/2006/11/08/microsoft-windows-software-development-kit-for-windows-vista-and-net-framework-3-0-runtime-components.aspx |
|||
v6.0) |
|||
|
|||
get_filename_component(_sdkdir |
|||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\${_winsdkver};InstallationFolder]" |
|||
ABSOLUTE) |
|||
if(EXISTS "${_sdkdir}") |
|||
list(APPEND _win_sdk_dirs "${_sdkdir}") |
|||
list(APPEND |
|||
_win_sdk_versanddirs |
|||
"Windows SDK ${_winsdkver}" |
|||
"${_sdkdir}") |
|||
endif() |
|||
endforeach() |
|||
endif() |
|||
if(MSVC_VERSION GREATER 1200) |
|||
foreach(_platformsdkinfo |
|||
"D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1_Microsoft Platform SDK for Windows Server 2003 R2" |
|||
"8F9E5EF3-A9A5-491B-A889-C58EFFECE8B3_Microsoft Platform SDK for Windows Server 2003 SP1") |
|||
string(SUBSTRING "${_platformsdkinfo}" 0 36 _platformsdkguid) |
|||
string(SUBSTRING "${_platformsdkinfo}" 37 -1 _platformsdkname) |
|||
foreach(HIVE HKEY_LOCAL_MACHINE HKEY_CURRENT_USER) |
|||
get_filename_component(_sdkdir |
|||
"[${HIVE}\\SOFTWARE\\Microsoft\\MicrosoftSDK\\InstalledSDKs\\${_platformsdkguid};Install Dir]" |
|||
ABSOLUTE) |
|||
if(EXISTS "${_sdkdir}") |
|||
list(APPEND _win_sdk_dirs "${_sdkdir}") |
|||
list(APPEND _win_sdk_versanddirs "${_platformsdkname}" "${_sdkdir}") |
|||
endif() |
|||
endforeach() |
|||
endforeach() |
|||
endif() |
|||
|
|||
set(_win_sdk_versanddirs |
|||
"${_win_sdk_versanddirs}" |
|||
CACHE |
|||
INTERNAL |
|||
"mapping between windows sdk version locations and names" |
|||
FORCE) |
|||
|
|||
function(windowssdk_name_lookup _dir _outvar) |
|||
list(FIND _win_sdk_versanddirs "${_dir}" _diridx) |
|||
math(EXPR _nameidx "${_diridx} - 1") |
|||
if(${_nameidx} GREATER -1) |
|||
list(GET _win_sdk_versanddirs ${_nameidx} _sdkname) |
|||
else() |
|||
set(_sdkname "NOTFOUND") |
|||
endif() |
|||
set(${_outvar} "${_sdkname}" PARENT_SCOPE) |
|||
endfunction() |
|||
|
|||
if(_win_sdk_dirs) |
|||
# Remove duplicates |
|||
list(REMOVE_DUPLICATES _win_sdk_dirs) |
|||
list(GET _win_sdk_dirs 0 WINDOWSSDK_LATEST_DIR) |
|||
windowssdk_name_lookup("${WINDOWSSDK_LATEST_DIR}" |
|||
WINDOWSSDK_LATEST_NAME) |
|||
set(WINDOWSSDK_DIRS ${_win_sdk_dirs}) |
|||
endif() |
|||
if(_preferred_sdk_dirs) |
|||
list(GET _preferred_sdk_dirs 0 WINDOWSSDK_PREFERRED_DIR) |
|||
windowssdk_name_lookup("${WINDOWSSDK_LATEST_DIR}" |
|||
WINDOWSSDK_PREFERRED_NAME) |
|||
set(WINDOWSSDK_PREFERRED_FIRST_DIRS |
|||
${_preferred_sdk_dirs} |
|||
${_win_sdk_dirs}) |
|||
list(REMOVE_DUPLICATES WINDOWSSDK_PREFERRED_FIRST_DIRS) |
|||
set(WINDOWSSDK_FOUND_PREFERENCE ON) |
|||
|
|||
# In case a preferred dir was found that isn't found otherwise |
|||
#set(WINDOWSSDK_DIRS ${WINDOWSSDK_DIRS} ${WINDOWSSDK_PREFERRED_FIRST_DIRS}) |
|||
#list(REMOVE_DUPLICATES WINDOWSSDK_DIRS) |
|||
else() |
|||
set(WINDOWSSDK_PREFERRED_DIR "${WINDOWSSDK_LATEST_DIR}") |
|||
set(WINDOWSSDK_PREFERRED_NAME "${WINDOWSSDK_LATEST_NAME}") |
|||
set(WINDOWSSDK_PREFERRED_FIRST_DIRS ${WINDOWSSDK_DIRS}) |
|||
set(WINDOWSSDK_FOUND_PREFERENCE OFF) |
|||
endif() |
|||
|
|||
include(FindPackageHandleStandardArgs) |
|||
find_package_handle_standard_args(WindowsSDK |
|||
"No compatible version of the Windows SDK or Platform SDK found." |
|||
WINDOWSSDK_DIRS) |
|||
|
|||
if(WINDOWSSDK_FOUND) |
|||
if(NOT _winsdk_remembered_dirs STREQUAL WINDOWSSDK_DIRS) |
|||
set(_winsdk_remembered_dirs |
|||
"${WINDOWSSDK_DIRS}" |
|||
CACHE |
|||
INTERNAL |
|||
"" |
|||
FORCE) |
|||
if(NOT WindowsSDK_FIND_QUIETLY) |
|||
foreach(_sdkdir ${WINDOWSSDK_DIRS}) |
|||
windowssdk_name_lookup("${_sdkdir}" _sdkname) |
|||
message(STATUS " - Found ${_sdkname} at ${_sdkdir}") |
|||
endforeach() |
|||
endif() |
|||
endif() |
|||
|
|||
# Internal: Architecture-appropriate library directory names. |
|||
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "ARM") |
|||
set(_winsdk_archbare /arm) # what the architecture used to be called in oldest SDKs |
|||
set(_winsdk_arch arm) # what the architecture used to be called |
|||
set(_winsdk_arch8 arm) # what the WDK for Win8+ calls this architecture |
|||
else() |
|||
if(CMAKE_SIZEOF_VOID_P MATCHES "8") |
|||
set(_winsdk_archbare /x64) # what the architecture used to be called in oldest SDKs |
|||
set(_winsdk_arch amd64) # what the architecture used to be called |
|||
set(_winsdk_arch8 x64) # what the WDK for Win8+ calls this architecture |
|||
else() |
|||
set(_winsdk_archbare ) # what the architecture used to be called in oldest SDKs |
|||
set(_winsdk_arch i386) # what the architecture used to be called |
|||
set(_winsdk_arch8 x86) # what the WDK for Win8+ calls this architecture |
|||
endif() |
|||
endif() |
|||
|
|||
function(get_windowssdk_from_component _component _var) |
|||
get_filename_component(_component "${_component}" ABSOLUTE) |
|||
file(TO_CMAKE_PATH "${_component}" _component) |
|||
foreach(_sdkdir ${WINDOWSSDK_DIRS}) |
|||
get_filename_component(_sdkdir "${_sdkdir}" ABSOLUTE) |
|||
string(LENGTH "${_sdkdir}" _sdklen) |
|||
file(RELATIVE_PATH _rel "${_sdkdir}" "${_component}") |
|||
# If we don't have any "parent directory" items... |
|||
if(NOT "${_rel}" MATCHES "[.][.]") |
|||
set(${_var} "${_sdkdir}" PARENT_SCOPE) |
|||
return() |
|||
endif() |
|||
endforeach() |
|||
# Fail. |
|||
set(${_var} "NOTFOUND" PARENT_SCOPE) |
|||
endfunction() |
|||
function(get_windowssdk_library_dirs _winsdk_dir _var) |
|||
set(_result) |
|||
foreach(_suffix |
|||
"lib${_winsdk_archbare}" # SDKs like 7.1A |
|||
"lib/w2k/${_winsdk_arch}" # Win2k min requirement |
|||
"lib/wxp/${_winsdk_arch}" # WinXP min requirement |
|||
"lib/wnet/${_winsdk_arch}" # Win Server 2003 min requirement |
|||
"lib/wlh/${_winsdk_arch}" # Win Vista ("Long Horn") min requirement |
|||
"lib/wlh/um/${_winsdk_arch8}" # Win Vista ("Long Horn") min requirement |
|||
"lib/win7/${_winsdk_arch}" # Win 7 min requirement |
|||
"lib/win7/um/${_winsdk_arch8}" # Win 7 min requirement |
|||
"lib/win8/um/${_winsdk_arch8}" # Win 8 min requirement |
|||
"lib/win8/km/${_winsdk_arch8}" # Win 8 min requirement |
|||
"lib/winv6.3/km/${_winsdk_arch8}" # Win 8.1 min requirement |
|||
"lib/winv6.3/um/${_winsdk_arch8}" # Win 8.1 min requirement |
|||
) |
|||
# Check to see if a library actually exists here. |
|||
file(GLOB _libs "${_winsdk_dir}/${_suffix}/*.lib") |
|||
if(_libs) |
|||
list(APPEND _result "${_winsdk_dir}/${_suffix}") |
|||
endif() |
|||
endforeach() |
|||
if(NOT _result) |
|||
set(_result NOTFOUND) |
|||
endif() |
|||
set(${_var} ${_result} PARENT_SCOPE) |
|||
endfunction() |
|||
function(get_windowssdk_include_dirs _winsdk_dir _var) |
|||
set(_result) |
|||
foreach(_suffix |
|||
"Include" |
|||
"Include/shared" |
|||
"Include/um" |
|||
"Include/winrt" |
|||
"Include/km" |
|||
"Include/wdf" |
|||
) |
|||
# Check to see if a header file actually exists here. |
|||
file(GLOB _headers "${_winsdk_dir}/${_suffix}/*.h") |
|||
if(_headers) |
|||
list(APPEND _result "${_winsdk_dir}/${_suffix}") |
|||
endif() |
|||
endforeach() |
|||
if(NOT _result) |
|||
set(_result NOTFOUND) |
|||
endif() |
|||
set(${_var} ${_result} PARENT_SCOPE) |
|||
endfunction() |
|||
endif() |
@ -0,0 +1,33 @@ |
|||
cmake_policy(SET CMP0015 NEW) |
|||
set(CMAKE_AUTOMOC OFF) |
|||
|
|||
aux_source_directory(. SRC_LIST) |
|||
|
|||
include_directories(BEFORE ..) |
|||
include_directories(${Boost_INCLUDE_DIRS}) |
|||
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) |
|||
|
|||
if (JSCONSOLE) |
|||
include_directories(${V8_INCLUDE_DIRS}) |
|||
endif() |
|||
|
|||
set(EXECUTABLE ethkey) |
|||
|
|||
file(GLOB HEADERS "*.h") |
|||
|
|||
add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) |
|||
|
|||
add_dependencies(${EXECUTABLE} BuildInfo.h) |
|||
|
|||
target_link_libraries(${EXECUTABLE} devcrypto) |
|||
target_link_libraries(${EXECUTABLE} ethcore) |
|||
|
|||
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) |
|||
eth_copy_dlls("${EXECUTABLE}" MHD_DLLS) |
|||
endif() |
|||
|
|||
if (APPLE) |
|||
install(TARGETS ${EXECUTABLE} DESTINATION bin) |
|||
else() |
|||
eth_install_executable(${EXECUTABLE}) |
|||
endif() |
@ -0,0 +1,431 @@ |
|||
#pragma once |
|||
|
|||
/*
|
|||
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 KeyAux.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
* CLI module for key management. |
|||
*/ |
|||
|
|||
#include <thread> |
|||
#include <chrono> |
|||
#include <fstream> |
|||
#include <iostream> |
|||
#include <boost/algorithm/string.hpp> |
|||
#include <boost/algorithm/string/trim_all.hpp> |
|||
#include <libdevcore/SHA3.h> |
|||
#include <libdevcore/FileSystem.h> |
|||
#include <libethcore/KeyManager.h> |
|||
#include <libethcore/ICAP.h> |
|||
#include "BuildInfo.h" |
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::eth; |
|||
using namespace boost::algorithm; |
|||
|
|||
#undef RETURN |
|||
|
|||
class BadArgument: public Exception {}; |
|||
|
|||
string getAccountPassword(KeyManager& keyManager, Address const& a) |
|||
{ |
|||
return getPassword("Enter password for address " + keyManager.accountDetails()[a].first + " (" + a.abridged() + "; hint:" + keyManager.accountDetails()[a].second + "): "); |
|||
} |
|||
|
|||
string createPassword(std::string const& _prompt) |
|||
{ |
|||
string ret; |
|||
while (true) |
|||
{ |
|||
ret = getPassword(_prompt); |
|||
string confirm = getPassword("Please confirm the password by entering it again: "); |
|||
if (ret == confirm) |
|||
break; |
|||
cout << "Passwords were different. Try again." << endl; |
|||
} |
|||
return ret; |
|||
// cout << "Enter a hint to help you remember this password: " << flush;
|
|||
// cin >> hint;
|
|||
// return make_pair(ret, hint);
|
|||
} |
|||
|
|||
pair<string, string> createPassword(KeyManager& _keyManager, std::string const& _prompt, std::string const& _pass = std::string(), std::string const& _hint = std::string()) |
|||
{ |
|||
string pass = _pass; |
|||
if (pass.empty()) |
|||
while (true) |
|||
{ |
|||
pass = getPassword(_prompt); |
|||
string confirm = getPassword("Please confirm the password by entering it again: "); |
|||
if (pass == confirm) |
|||
break; |
|||
cout << "Passwords were different. Try again." << endl; |
|||
} |
|||
string hint = _hint; |
|||
if (hint.empty() && !pass.empty() && !_keyManager.haveHint(pass)) |
|||
{ |
|||
cout << "Enter a hint to help you remember this password: " << flush; |
|||
getline(cin, hint); |
|||
} |
|||
return make_pair(pass, hint); |
|||
} |
|||
|
|||
class KeyCLI |
|||
{ |
|||
public: |
|||
enum class OperationMode |
|||
{ |
|||
None, |
|||
ListBare, |
|||
NewBare, |
|||
ImportBare, |
|||
ExportBare, |
|||
RecodeBare, |
|||
KillBare, |
|||
InspectBare, |
|||
CreateWallet, |
|||
List, |
|||
New, |
|||
Import, |
|||
Export, |
|||
Recode, |
|||
Kill |
|||
}; |
|||
|
|||
KeyCLI(OperationMode _mode = OperationMode::None): m_mode(_mode) {} |
|||
|
|||
bool interpretOption(int& i, int argc, char** argv) |
|||
{ |
|||
string arg = argv[i]; |
|||
if (arg == "--wallet-path" && i + 1 < argc) |
|||
m_walletPath = argv[++i]; |
|||
else if (arg == "--secrets-path" && i + 1 < argc) |
|||
m_secretsPath = argv[++i]; |
|||
else if ((arg == "-m" || arg == "--master") && i + 1 < argc) |
|||
m_masterPassword = argv[++i]; |
|||
else if (arg == "--unlock" && i + 1 < argc) |
|||
m_unlocks.push_back(argv[++i]); |
|||
else if (arg == "--lock" && i + 1 < argc) |
|||
m_lock = argv[++i]; |
|||
else if (arg == "--kdf" && i + 1 < argc) |
|||
m_kdf = argv[++i]; |
|||
else if (arg == "--kdf-param" && i + 2 < argc) |
|||
{ |
|||
auto n = argv[++i]; |
|||
auto v = argv[++i]; |
|||
m_kdfParams[n] = v; |
|||
} |
|||
else if (arg == "--new-bare") |
|||
m_mode = OperationMode::NewBare; |
|||
else if (arg == "--import-bare") |
|||
m_mode = OperationMode::ImportBare; |
|||
else if (arg == "--list-bare") |
|||
m_mode = OperationMode::ListBare; |
|||
else if (arg == "--export-bare") |
|||
m_mode = OperationMode::ExportBare; |
|||
else if (arg == "--inspect-bare") |
|||
m_mode = OperationMode::InspectBare; |
|||
else if (arg == "--recode-bare") |
|||
m_mode = OperationMode::RecodeBare; |
|||
else if (arg == "--kill-bare") |
|||
m_mode = OperationMode::KillBare; |
|||
else if (arg == "--create-wallet") |
|||
m_mode = OperationMode::CreateWallet; |
|||
else if (arg == "--list") |
|||
m_mode = OperationMode::List; |
|||
else if ((arg == "-n" || arg == "--new") && i + 1 < argc) |
|||
{ |
|||
m_mode = OperationMode::New; |
|||
m_name = argv[++i]; |
|||
} |
|||
else if ((arg == "-i" || arg == "--import") && i + 2 < argc) |
|||
{ |
|||
m_mode = OperationMode::Import; |
|||
m_inputs = strings(1, argv[++i]); |
|||
m_name = argv[++i]; |
|||
} |
|||
else if (arg == "--export") |
|||
m_mode = OperationMode::Export; |
|||
else if (arg == "--recode") |
|||
m_mode = OperationMode::Recode; |
|||
else if (arg == "--no-icap") |
|||
m_icap = false; |
|||
else if (m_mode == OperationMode::ImportBare || m_mode == OperationMode::InspectBare || m_mode == OperationMode::KillBare || m_mode == OperationMode::Recode || m_mode == OperationMode::Export || m_mode == OperationMode::RecodeBare || m_mode == OperationMode::ExportBare) |
|||
m_inputs.push_back(arg); |
|||
else |
|||
return false; |
|||
return true; |
|||
} |
|||
|
|||
KeyPair makeKey() const |
|||
{ |
|||
KeyPair k(Secret::random()); |
|||
while (m_icap && k.address()[0]) |
|||
k = KeyPair(sha3(k.secret())); |
|||
return k; |
|||
} |
|||
|
|||
void execute() |
|||
{ |
|||
if (m_mode == OperationMode::CreateWallet) |
|||
{ |
|||
KeyManager wallet(m_walletPath, m_secretsPath); |
|||
if (m_masterPassword.empty()) |
|||
m_masterPassword = createPassword("Please enter a MASTER password to protect your key store (make it strong!): "); |
|||
if (m_masterPassword.empty()) |
|||
cerr << "Aborted (empty password not allowed)." << endl; |
|||
else |
|||
wallet.create(m_masterPassword); |
|||
} |
|||
else if (m_mode < OperationMode::CreateWallet) |
|||
{ |
|||
SecretStore store(m_secretsPath); |
|||
switch (m_mode) |
|||
{ |
|||
case OperationMode::ListBare: |
|||
for (h128 const& u: std::set<h128>() + store.keys()) |
|||
cout << toUUID(u) << endl; |
|||
break; |
|||
case OperationMode::NewBare: |
|||
{ |
|||
if (m_lock.empty()) |
|||
m_lock = createPassword("Enter a password with which to secure this account: "); |
|||
auto k = makeKey(); |
|||
h128 u = store.importSecret(k.secret().asBytes(), m_lock); |
|||
cout << "Created key " << toUUID(u) << endl; |
|||
cout << " Address: " << k.address().hex() << endl; |
|||
cout << " ICAP: " << ICAP(k.address()).encoded() << endl; |
|||
break; |
|||
} |
|||
case OperationMode::ImportBare: |
|||
for (string const& i: m_inputs) |
|||
{ |
|||
h128 u; |
|||
bytes b; |
|||
b = fromHex(i); |
|||
if (b.size() != 32) |
|||
{ |
|||
std::string s = contentsString(i); |
|||
b = fromHex(s); |
|||
if (b.size() != 32) |
|||
u = store.importKey(i); |
|||
} |
|||
if (!u && b.size() == 32) |
|||
u = store.importSecret(b, lockPassword(toAddress(Secret(b)).abridged())); |
|||
if (!u) |
|||
{ |
|||
cerr << "Cannot import " << i << " not a file or secret." << endl; |
|||
continue; |
|||
} |
|||
cout << "Successfully imported " << i << " as " << toUUID(u); |
|||
} |
|||
break; |
|||
case OperationMode::InspectBare: |
|||
for (auto const& i: m_inputs) |
|||
if (!contents(i).empty()) |
|||
{ |
|||
h128 u = store.readKey(i, false); |
|||
bytes s = store.secret(u, [&](){ return getPassword("Enter password for key " + i + ": "); }); |
|||
cout << "Key " << i << ":" << endl; |
|||
cout << " UUID: " << toUUID(u) << ":" << endl; |
|||
cout << " Address: " << toAddress(Secret(s)).hex() << endl; |
|||
cout << " Secret: " << Secret(s).abridged() << endl; |
|||
} |
|||
else if (h128 u = fromUUID(i)) |
|||
{ |
|||
bytes s = store.secret(u, [&](){ return getPassword("Enter password for key " + toUUID(u) + ": "); }); |
|||
cout << "Key " << i << ":" << endl; |
|||
cout << " Address: " << toAddress(Secret(s)).hex() << endl; |
|||
cout << " Secret: " << Secret(s).abridged() << endl; |
|||
} |
|||
else |
|||
cerr << "Couldn't inspect " << i << "; not found." << endl; |
|||
break; |
|||
case OperationMode::ExportBare: break; |
|||
case OperationMode::RecodeBare: |
|||
for (auto const& i: m_inputs) |
|||
if (h128 u = fromUUID(i)) |
|||
if (store.recode(u, lockPassword(toUUID(u)), [&](){ return getPassword("Enter password for key " + toUUID(u) + ": "); }, kdf())) |
|||
cerr << "Re-encoded " << toUUID(u) << endl; |
|||
else |
|||
cerr << "Couldn't re-encode " << toUUID(u) << "; key corrupt or incorrect password supplied." << endl; |
|||
else |
|||
cerr << "Couldn't re-encode " << i << "; not found." << endl; |
|||
case OperationMode::KillBare: |
|||
for (auto const& i: m_inputs) |
|||
if (h128 u = fromUUID(i)) |
|||
store.kill(u); |
|||
else |
|||
cerr << "Couldn't kill " << i << "; not found." << endl; |
|||
break; |
|||
default: break; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
KeyManager wallet(m_walletPath, m_secretsPath); |
|||
if (wallet.exists()) |
|||
while (true) |
|||
{ |
|||
if (wallet.load(m_masterPassword)) |
|||
break; |
|||
if (!m_masterPassword.empty()) |
|||
{ |
|||
cout << "Password invalid. Try again." << endl; |
|||
m_masterPassword.clear(); |
|||
} |
|||
m_masterPassword = getPassword("Please enter your MASTER password: "); |
|||
} |
|||
else |
|||
{ |
|||
cerr << "Couldn't open wallet. Does it exist?" << endl; |
|||
exit(-1); |
|||
} |
|||
switch (m_mode) |
|||
{ |
|||
case OperationMode::New: |
|||
{ |
|||
tie(m_lock, m_lockHint) = createPassword(wallet, "Enter a password with which to secure this account (or nothing to use the master password): ", m_lock, m_lockHint); |
|||
auto k = makeKey(); |
|||
bool usesMaster = m_lock.empty(); |
|||
h128 u = usesMaster ? wallet.import(k.secret(), m_name) : wallet.import(k.secret(), m_name, m_lock, m_lockHint); |
|||
cout << "Created key " << toUUID(u) << endl; |
|||
cout << " Name: " << m_name << endl; |
|||
if (usesMaster) |
|||
cout << " Uses master password." << endl; |
|||
else |
|||
cout << " Password hint: " << m_lockHint << endl; |
|||
cout << " Address: " << k.address().hex() << endl; |
|||
cout << " ICAP: " << ICAP(k.address()).encoded() << endl; |
|||
break; |
|||
} |
|||
case OperationMode::List: |
|||
{ |
|||
vector<u128> bare; |
|||
vector<u128> nonIcap; |
|||
for (auto const& u: wallet.store().keys()) |
|||
if (Address a = wallet.address(u)) |
|||
if (a[0]) |
|||
nonIcap.push_back(u); |
|||
else |
|||
{ |
|||
std::pair<std::string, std::string> info = wallet.accountDetails()[a]; |
|||
cout << toUUID(u) << " " << a.abridged(); |
|||
cout << " " << ICAP(a).encoded(); |
|||
cout << " " << info.first << endl; |
|||
} |
|||
else |
|||
bare.push_back(u); |
|||
for (auto const& u: nonIcap) |
|||
if (Address a = wallet.address(u)) |
|||
{ |
|||
std::pair<std::string, std::string> info = wallet.accountDetails()[a]; |
|||
cout << toUUID(u) << " " << a.abridged(); |
|||
cout << " (Not ICAP) "; |
|||
cout << " " << info.first << endl; |
|||
} |
|||
for (auto const& u: bare) |
|||
cout << toUUID(u) << " (Bare)" << endl; |
|||
} |
|||
default: break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
std::string lockPassword(std::string const& _accountName) |
|||
{ |
|||
return m_lock.empty() ? createPassword("Enter a password with which to secure account " + _accountName + ": ") : m_lock; |
|||
} |
|||
|
|||
static void streamHelp(ostream& _out) |
|||
{ |
|||
_out |
|||
<< "Secret-store (\"bare\") operation modes:" << endl |
|||
<< " --list-bare List all secret available in secret-store." << endl |
|||
<< " --new-bare Generate and output a key without interacting with wallet and dump the JSON." << endl |
|||
<< " --import-bare [ <file>|<secret-hex> , ... ] Import keys from given sources." << endl |
|||
<< " --recode-bare [ <uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl |
|||
// << " --export-bare [ <uuid> , ... ] Export given keys." << endl
|
|||
<< " --kill-bare [ <uuid> , ... ] Delete given keys." << endl |
|||
<< "Secret-store configuration:" << endl |
|||
<< " --secrets-path <path> Specify Web3 secret-store path (default: " << SecretStore::defaultPath() << ")" << endl |
|||
<< endl |
|||
<< "Wallet operating modes:" << endl |
|||
<< " -l,--list List all keys available in wallet." << endl |
|||
<< " -n,--new <name> Create a new key with given name and add it in the wallet." << endl |
|||
<< " -i,--import [<uuid>|<file>|<secret-hex>] <name> Import keys from given source and place in wallet." << endl |
|||
<< " -e,--export [ <address>|<uuid> , ... ] Export given keys." << endl |
|||
<< " -r,--recode [ <address>|<uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl |
|||
<< "Wallet configuration:" << endl |
|||
<< " --create-wallet Create an Ethereum master wallet." << endl |
|||
<< " --wallet-path <path> Specify Ethereum wallet path (default: " << KeyManager::defaultPath() << ")" << endl |
|||
<< " -m, --master <password> Specify wallet (master) password." << endl |
|||
<< endl |
|||
<< "Encryption configuration:" << endl |
|||
<< " --kdf <kdfname> Specify KDF to use when encrypting (default: sc rypt)" << endl |
|||
<< " --kdf-param <name> <value> Specify a parameter for the KDF." << endl |
|||
// << " --cipher <ciphername> Specify cipher to use when encrypting (default: aes-128-ctr)" << endl
|
|||
// << " --cipher-param <name> <value> Specify a parameter for the cipher." << endl
|
|||
<< " --lock <password> Specify password for when encrypting a (the) key." << endl |
|||
<< " --hint <hint> Specify hint for the --lock password." << endl |
|||
<< endl |
|||
<< "Decryption configuration:" << endl |
|||
<< " --unlock <password> Specify password for a (the) key." << endl |
|||
<< "Key generation configuration:" << endl |
|||
<< " --no-icap Don't bother to make a direct-ICAP capable key." << endl |
|||
; |
|||
} |
|||
|
|||
static bool isTrue(std::string const& _m) |
|||
{ |
|||
return _m == "on" || _m == "yes" || _m == "true" || _m == "1"; |
|||
} |
|||
|
|||
static bool isFalse(std::string const& _m) |
|||
{ |
|||
return _m == "off" || _m == "no" || _m == "false" || _m == "0"; |
|||
} |
|||
|
|||
private: |
|||
KDF kdf() const { return m_kdf == "pbkdf2" ? KDF::PBKDF2_SHA256 : KDF::Scrypt; } |
|||
|
|||
/// Operating mode.
|
|||
OperationMode m_mode; |
|||
|
|||
/// Wallet stuff
|
|||
string m_secretsPath = SecretStore::defaultPath(); |
|||
string m_walletPath = KeyManager::defaultPath(); |
|||
|
|||
/// Wallet password stuff
|
|||
string m_masterPassword; |
|||
strings m_unlocks; |
|||
string m_lock; |
|||
string m_lockHint; |
|||
bool m_icap = true; |
|||
|
|||
/// Creating
|
|||
string m_name; |
|||
|
|||
/// Importing
|
|||
strings m_inputs; |
|||
|
|||
string m_kdf = "scrypt"; |
|||
map<string, string> m_kdfParams; |
|||
// string m_cipher;
|
|||
// map<string, string> m_cipherParams;
|
|||
}; |
@ -0,0 +1,84 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file main.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
* Ethereum client. |
|||
*/ |
|||
|
|||
#include <thread> |
|||
#include <chrono> |
|||
#include <fstream> |
|||
#include <iostream> |
|||
#include <libdevcore/FileSystem.h> |
|||
#include <libdevcore/Log.h> |
|||
#include <libethcore/KeyManager.h> |
|||
#include "BuildInfo.h" |
|||
#include "KeyAux.h" |
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::eth; |
|||
|
|||
void help() |
|||
{ |
|||
cout |
|||
<< "Usage ethkey [OPTIONS]" << endl |
|||
<< "Options:" << endl << endl; |
|||
KeyCLI::streamHelp(cout); |
|||
cout |
|||
<< "General Options:" << endl |
|||
<< " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl |
|||
<< " -V,--version Show the version and exit." << endl |
|||
<< " -h,--help Show this help message and exit." << endl |
|||
; |
|||
exit(0); |
|||
} |
|||
|
|||
void version() |
|||
{ |
|||
cout << "ethkey version " << dev::Version << endl; |
|||
cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl; |
|||
exit(0); |
|||
} |
|||
|
|||
int main(int argc, char** argv) |
|||
{ |
|||
KeyCLI m(KeyCLI::OperationMode::ListBare); |
|||
g_logVerbosity = 0; |
|||
|
|||
for (int i = 1; i < argc; ++i) |
|||
{ |
|||
string arg = argv[i]; |
|||
if (m.interpretOption(i, argc, argv)) {} |
|||
else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc) |
|||
g_logVerbosity = atoi(argv[++i]); |
|||
else if (arg == "-h" || arg == "--help") |
|||
help(); |
|||
else if (arg == "-V" || arg == "--version") |
|||
version(); |
|||
else |
|||
{ |
|||
cerr << "Invalid argument: " << arg << endl; |
|||
exit(-1); |
|||
} |
|||
} |
|||
|
|||
m.execute(); |
|||
|
|||
return 0; |
|||
} |
|||
|
@ -0,0 +1,520 @@ |
|||
|
|||
// This is a copy of boost/multiprecision/detail/number_compare.hpp from boost 1.59 to replace buggy version from 1.58.
|
|||
|
|||
#ifdef BOOST_MP_COMPARE_HPP |
|||
#error This bug workaround header must be included before original boost/multiprecision/detail/number_compare.hpp |
|||
#endif |
|||
|
|||
///////////////////////////////////////////////////////////////////////////////
|
|||
// Copyright 2012 John Maddock. Distributed under the Boost
|
|||
// Software License, Version 1.0. (See accompanying file
|
|||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|||
|
|||
#ifndef BOOST_MP_COMPARE_HPP |
|||
#define BOOST_MP_COMPARE_HPP |
|||
|
|||
// A copy of boost/multiprecision/traits/is_backend.hpp
|
|||
#ifndef BOOST_MP_IS_BACKEND_HPP |
|||
#define BOOST_MP_IS_BACKEND_HPP |
|||
|
|||
#include <boost/mpl/has_xxx.hpp> |
|||
#include <boost/type_traits/conditional.hpp> |
|||
#include <boost/type_traits/is_convertible.hpp> |
|||
#include <boost/multiprecision/detail/number_base.hpp> |
|||
#include <boost/multiprecision/detail/generic_interconvert.hpp> |
|||
|
|||
namespace boost{ namespace multiprecision{ namespace detail{ |
|||
|
|||
BOOST_MPL_HAS_XXX_TRAIT_DEF(signed_types) |
|||
BOOST_MPL_HAS_XXX_TRAIT_DEF(unsigned_types) |
|||
BOOST_MPL_HAS_XXX_TRAIT_DEF(float_types) |
|||
|
|||
template <class T> |
|||
struct is_backend |
|||
{ |
|||
static const bool value = has_signed_types<T>::value && has_unsigned_types<T>::value && has_float_types<T>::value; |
|||
}; |
|||
|
|||
template <class Backend> |
|||
struct other_backend |
|||
{ |
|||
typedef typename boost::conditional< |
|||
boost::is_same<number<Backend>, number<Backend, et_on> >::value, |
|||
number<Backend, et_off>, number<Backend, et_on> >::type type; |
|||
}; |
|||
|
|||
template <class B, class V> |
|||
struct number_from_backend |
|||
{ |
|||
typedef typename boost::conditional < |
|||
boost::is_convertible<V, number<B> >::value, |
|||
number<B>, |
|||
typename other_backend<B>::type > ::type type; |
|||
}; |
|||
|
|||
template <bool b, class T, class U> |
|||
struct is_first_backend_imp{ static const bool value = false; }; |
|||
template <class T, class U> |
|||
struct is_first_backend_imp<true, T, U>{ static const bool value = is_convertible<U, number<T, et_on> >::value || is_convertible<U, number<T, et_off> >::value; }; |
|||
|
|||
template <class T, class U> |
|||
struct is_first_backend : is_first_backend_imp<is_backend<T>::value, T, U> {}; |
|||
|
|||
template <bool b, class T, class U> |
|||
struct is_second_backend_imp{ static const bool value = false; }; |
|||
template <class T, class U> |
|||
struct is_second_backend_imp<true, T, U>{ static const bool value = is_convertible<T, number<U> >::value || is_convertible<T, number<U, et_off> >::value; }; |
|||
|
|||
template <class T, class U> |
|||
struct is_second_backend : is_second_backend_imp<is_backend<U>::value, T, U> {}; |
|||
|
|||
} |
|||
} |
|||
} |
|||
|
|||
#endif // BOOST_MP_IS_BACKEND_HPP
|
|||
|
|||
//
|
|||
// Comparison operators for number.
|
|||
//
|
|||
|
|||
namespace boost{ namespace multiprecision{ |
|||
|
|||
namespace default_ops{ |
|||
|
|||
template <class B> |
|||
inline bool eval_eq(const B& a, const B& b) |
|||
{ |
|||
return a.compare(b) == 0; |
|||
} |
|||
template <class T, class U> |
|||
inline typename enable_if_c<boost::multiprecision::detail::is_first_backend<T, U>::value, bool>::type eval_eq(const T& a, const U& b) |
|||
{ |
|||
typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b); |
|||
return eval_eq(a, t.backend()); |
|||
} |
|||
template <class T, class U> |
|||
inline typename enable_if_c<boost::multiprecision::detail::is_second_backend<T, U>::value, bool>::type eval_eq(const T& a, const U& b) |
|||
{ |
|||
typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a); |
|||
return eval_eq(t.backend(), b); |
|||
} |
|||
|
|||
template <class B> |
|||
inline bool eval_lt(const B& a, const B& b) |
|||
{ |
|||
return a.compare(b) < 0; |
|||
} |
|||
template <class T, class U> |
|||
inline typename enable_if_c<boost::multiprecision::detail::is_first_backend<T, U>::value, bool>::type eval_lt(const T& a, const U& b) |
|||
{ |
|||
typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b); |
|||
return eval_lt(a, t.backend()); |
|||
} |
|||
template <class T, class U> |
|||
inline typename enable_if_c<boost::multiprecision::detail::is_second_backend<T, U>::value, bool>::type eval_lt(const T& a, const U& b) |
|||
{ |
|||
typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a); |
|||
return eval_lt(t.backend(), b); |
|||
} |
|||
|
|||
template <class B> |
|||
inline bool eval_gt(const B& a, const B& b) |
|||
{ |
|||
return a.compare(b) > 0; |
|||
} |
|||
template <class T, class U> |
|||
inline typename enable_if_c<boost::multiprecision::detail::is_first_backend<T, U>::value, bool>::type eval_gt(const T& a, const U& b) |
|||
{ |
|||
typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b); |
|||
return eval_gt(a, t.backend()); |
|||
} |
|||
template <class T, class U> |
|||
inline typename enable_if_c<boost::multiprecision::detail::is_second_backend<T, U>::value, bool>::type eval_gt(const T& a, const U& b) |
|||
{ |
|||
typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a); |
|||
return eval_gt(t.backend(), b); |
|||
} |
|||
|
|||
} // namespace default_ops
|
|||
|
|||
namespace detail{ |
|||
|
|||
template <class Num, class Val> |
|||
struct is_valid_mixed_compare : public mpl::false_ {}; |
|||
|
|||
template <class B, expression_template_option ET, class Val> |
|||
struct is_valid_mixed_compare<number<B, ET>, Val> : public is_convertible<Val, number<B, ET> > {}; |
|||
|
|||
template <class B, expression_template_option ET> |
|||
struct is_valid_mixed_compare<number<B, ET>, number<B, ET> > : public mpl::false_ {}; |
|||
|
|||
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4> |
|||
struct is_valid_mixed_compare<number<B, ET>, expression<tag, Arg1, Arg2, Arg3, Arg4> > |
|||
: public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {}; |
|||
|
|||
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET> |
|||
struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> > |
|||
: public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {}; |
|||
|
|||
template <class Backend, expression_template_option ExpressionTemplates> |
|||
inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value != number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>&) |
|||
{ |
|||
return false; |
|||
} |
|||
template <class Backend, expression_template_option ExpressionTemplates> |
|||
inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value == number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>& a) |
|||
{ |
|||
using default_ops::eval_fpclassify; |
|||
return eval_fpclassify(a.backend()) == FP_NAN; |
|||
} |
|||
|
|||
template <class Arithmetic> |
|||
inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Arithmetic>::value != number_kind_floating_point, bool>::type is_unordered_value(const Arithmetic&) |
|||
{ |
|||
return false; |
|||
} |
|||
template <class Arithmetic> |
|||
inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Arithmetic>::value == number_kind_floating_point, bool>::type is_unordered_value(const Arithmetic& a) |
|||
{ |
|||
return (boost::math::isnan)(a); |
|||
} |
|||
|
|||
template <class T, class U> |
|||
inline BOOST_CONSTEXPR bool is_unordered_comparison(const T& a, const U& b) |
|||
{ |
|||
return is_unordered_value(a) || is_unordered_value(b); |
|||
} |
|||
|
|||
} |
|||
|
|||
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2> |
|||
inline bool operator == (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) |
|||
{ |
|||
using default_ops::eval_eq; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return eval_eq(a.backend(), b.backend()); |
|||
} |
|||
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type |
|||
operator == (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) |
|||
{ |
|||
using default_ops::eval_eq; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return eval_eq(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); |
|||
} |
|||
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type |
|||
operator == (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) |
|||
{ |
|||
using default_ops::eval_eq; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return eval_eq(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); |
|||
} |
|||
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type |
|||
operator == (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) |
|||
{ |
|||
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; |
|||
using default_ops::eval_eq; |
|||
result_type t(b); |
|||
if(detail::is_unordered_comparison(a, t)) return false; |
|||
return eval_eq(t.backend(), result_type::canonical_value(a)); |
|||
} |
|||
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type |
|||
operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) |
|||
{ |
|||
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; |
|||
using default_ops::eval_eq; |
|||
result_type t(a); |
|||
if(detail::is_unordered_comparison(t, b)) return false; |
|||
return eval_eq(t.backend(), result_type::canonical_value(b)); |
|||
} |
|||
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> |
|||
inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type |
|||
operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) |
|||
{ |
|||
using default_ops::eval_eq; |
|||
typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a); |
|||
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b); |
|||
if(detail::is_unordered_comparison(t, t2)) return false; |
|||
return eval_eq(t.backend(), t2.backend()); |
|||
} |
|||
|
|||
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2> |
|||
inline bool operator != (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) |
|||
{ |
|||
using default_ops::eval_eq; |
|||
if(detail::is_unordered_comparison(a, b)) return true; |
|||
return !eval_eq(a.backend(), b.backend()); |
|||
} |
|||
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type |
|||
operator != (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) |
|||
{ |
|||
using default_ops::eval_eq; |
|||
if(detail::is_unordered_comparison(a, b)) return true; |
|||
return !eval_eq(a.backend(), number<Backend, et_on>::canonical_value(b)); |
|||
} |
|||
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type |
|||
operator != (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) |
|||
{ |
|||
using default_ops::eval_eq; |
|||
if(detail::is_unordered_comparison(a, b)) return true; |
|||
return !eval_eq(b.backend(), number<Backend, et_on>::canonical_value(a)); |
|||
} |
|||
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type |
|||
operator != (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) |
|||
{ |
|||
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; |
|||
using default_ops::eval_eq; |
|||
result_type t(b); |
|||
if(detail::is_unordered_comparison(a, t)) return true; |
|||
return !eval_eq(t.backend(), result_type::canonical_value(a)); |
|||
} |
|||
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type |
|||
operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) |
|||
{ |
|||
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; |
|||
using default_ops::eval_eq; |
|||
result_type t(a); |
|||
if(detail::is_unordered_comparison(t, b)) return true; |
|||
return !eval_eq(t.backend(), result_type::canonical_value(b)); |
|||
} |
|||
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> |
|||
inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type |
|||
operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) |
|||
{ |
|||
using default_ops::eval_eq; |
|||
typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a); |
|||
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b); |
|||
if(detail::is_unordered_comparison(t, t2)) return true; |
|||
return !eval_eq(t.backend(), t2.backend()); |
|||
} |
|||
|
|||
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2> |
|||
inline bool operator < (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) |
|||
{ |
|||
using default_ops::eval_lt; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return eval_lt(a.backend(), b.backend()); |
|||
} |
|||
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type |
|||
operator < (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) |
|||
{ |
|||
using default_ops::eval_lt; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); |
|||
} |
|||
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type |
|||
operator < (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) |
|||
{ |
|||
using default_ops::eval_gt; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); |
|||
} |
|||
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type |
|||
operator < (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) |
|||
{ |
|||
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; |
|||
using default_ops::eval_gt; |
|||
result_type t(b); |
|||
if(detail::is_unordered_comparison(a, t)) return false; |
|||
return eval_gt(t.backend(), result_type::canonical_value(a)); |
|||
} |
|||
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type |
|||
operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) |
|||
{ |
|||
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; |
|||
using default_ops::eval_lt; |
|||
result_type t(a); |
|||
if(detail::is_unordered_comparison(t, b)) return false; |
|||
return eval_lt(t.backend(), result_type::canonical_value(b)); |
|||
} |
|||
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> |
|||
inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type |
|||
operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) |
|||
{ |
|||
using default_ops::eval_lt; |
|||
typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a); |
|||
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b); |
|||
if(detail::is_unordered_comparison(t, t2)) return false; |
|||
return eval_lt(t.backend(), t2.backend()); |
|||
} |
|||
|
|||
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2> |
|||
inline bool operator > (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) |
|||
{ |
|||
using default_ops::eval_gt; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return eval_gt(a.backend(), b.backend()); |
|||
} |
|||
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type |
|||
operator > (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) |
|||
{ |
|||
using default_ops::eval_gt; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); |
|||
} |
|||
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type |
|||
operator > (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) |
|||
{ |
|||
using default_ops::eval_lt; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); |
|||
} |
|||
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type |
|||
operator > (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) |
|||
{ |
|||
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; |
|||
using default_ops::eval_lt; |
|||
result_type t(b); |
|||
if(detail::is_unordered_comparison(a, t)) return false; |
|||
return a > t; |
|||
} |
|||
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type |
|||
operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) |
|||
{ |
|||
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; |
|||
using default_ops::eval_gt; |
|||
result_type t(a); |
|||
if(detail::is_unordered_comparison(t, b)) return false; |
|||
return t > b; |
|||
} |
|||
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> |
|||
inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type |
|||
operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) |
|||
{ |
|||
using default_ops::eval_gt; |
|||
typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a); |
|||
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b); |
|||
if(detail::is_unordered_comparison(t, t2)) return false; |
|||
return t > t2; |
|||
} |
|||
|
|||
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2> |
|||
inline bool operator <= (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) |
|||
{ |
|||
using default_ops::eval_gt; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return !eval_gt(a.backend(), b.backend()); |
|||
} |
|||
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type |
|||
operator <= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) |
|||
{ |
|||
using default_ops::eval_gt; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return !eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); |
|||
} |
|||
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type |
|||
operator <= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) |
|||
{ |
|||
using default_ops::eval_lt; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return !eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); |
|||
} |
|||
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type |
|||
operator <= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) |
|||
{ |
|||
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; |
|||
using default_ops::eval_lt; |
|||
if(detail::is_unordered_value(a) || detail::is_unordered_value(b)) |
|||
return false; |
|||
result_type t(b); |
|||
if(detail::is_unordered_comparison(a, t)) return false; |
|||
return !eval_lt(t.backend(), result_type::canonical_value(a)); |
|||
} |
|||
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type |
|||
operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) |
|||
{ |
|||
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; |
|||
using default_ops::eval_gt; |
|||
result_type t(a); |
|||
if(detail::is_unordered_comparison(t, b)) return false; |
|||
return !eval_gt(t.backend(), result_type::canonical_value(b)); |
|||
} |
|||
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> |
|||
inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type |
|||
operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) |
|||
{ |
|||
using default_ops::eval_gt; |
|||
typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a); |
|||
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b); |
|||
if(detail::is_unordered_comparison(t, t2)) return false; |
|||
return !eval_gt(t.backend(), t2.backend()); |
|||
} |
|||
|
|||
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2> |
|||
inline bool operator >= (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) |
|||
{ |
|||
using default_ops::eval_lt; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return !eval_lt(a.backend(), b.backend()); |
|||
} |
|||
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type |
|||
operator >= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) |
|||
{ |
|||
using default_ops::eval_lt; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return !eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); |
|||
} |
|||
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type |
|||
operator >= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) |
|||
{ |
|||
using default_ops::eval_gt; |
|||
if(detail::is_unordered_comparison(a, b)) return false; |
|||
return !eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); |
|||
} |
|||
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type |
|||
operator >= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) |
|||
{ |
|||
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; |
|||
using default_ops::eval_gt; |
|||
result_type t(b); |
|||
if(detail::is_unordered_comparison(a, t)) return false; |
|||
return !eval_gt(t.backend(), result_type::canonical_value(a)); |
|||
} |
|||
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> |
|||
inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type |
|||
operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) |
|||
{ |
|||
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; |
|||
using default_ops::eval_lt; |
|||
result_type t(a); |
|||
if(detail::is_unordered_comparison(t, b)) return false; |
|||
return !eval_lt(t.backend(), result_type::canonical_value(b)); |
|||
} |
|||
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> |
|||
inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type |
|||
operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) |
|||
{ |
|||
using default_ops::eval_lt; |
|||
typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a); |
|||
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b); |
|||
if(detail::is_unordered_comparison(t, t2)) return false; |
|||
return !eval_lt(t.backend(), t2.backend()); |
|||
} |
|||
|
|||
|
|||
}} // namespaces
|
|||
|
|||
#endif // BOOST_MP_COMPARE_HPP
|
@ -0,0 +1,128 @@ |
|||
/*
|
|||
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 PathGasMeter.cpp
|
|||
* @author Christian <c@ethdev.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
#include "PathGasMeter.h" |
|||
#include <libevmasm/KnownState.h> |
|||
#include <libevmasm/SemanticInformation.h> |
|||
|
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::eth; |
|||
|
|||
PathGasMeter::PathGasMeter(AssemblyItems const& _items): |
|||
m_items(_items) |
|||
{ |
|||
for (size_t i = 0; i < m_items.size(); ++i) |
|||
if (m_items[i].type() == Tag) |
|||
m_tagPositions[m_items[i].data()] = i; |
|||
} |
|||
|
|||
GasMeter::GasConsumption PathGasMeter::estimateMax( |
|||
size_t _startIndex, |
|||
shared_ptr<KnownState> const& _state |
|||
) |
|||
{ |
|||
auto path = unique_ptr<GasPath>(new GasPath()); |
|||
path->index = _startIndex; |
|||
path->state = _state->copy(); |
|||
m_queue.push_back(move(path)); |
|||
|
|||
GasMeter::GasConsumption gas; |
|||
while (!m_queue.empty() && !gas.isInfinite) |
|||
gas = max(gas, handleQueueItem()); |
|||
return gas; |
|||
} |
|||
|
|||
GasMeter::GasConsumption PathGasMeter::handleQueueItem() |
|||
{ |
|||
assertThrow(!m_queue.empty(), OptimizerException, ""); |
|||
|
|||
unique_ptr<GasPath> path = move(m_queue.back()); |
|||
m_queue.pop_back(); |
|||
|
|||
shared_ptr<KnownState> state = path->state; |
|||
GasMeter meter(state, path->largestMemoryAccess); |
|||
ExpressionClasses& classes = state->expressionClasses(); |
|||
GasMeter::GasConsumption gas = path->gas; |
|||
size_t index = path->index; |
|||
|
|||
if (index >= m_items.size() || (index > 0 && m_items.at(index).type() != Tag)) |
|||
// Invalid jump usually provokes an out-of-gas exception, but we want to give an upper
|
|||
// bound on the gas that is needed without changing the behaviour, so it is fine to
|
|||
// return the current gas value.
|
|||
return gas; |
|||
|
|||
set<u256> jumpTags; |
|||
for (; index < m_items.size() && !gas.isInfinite; ++index) |
|||
{ |
|||
bool branchStops = false; |
|||
jumpTags.clear(); |
|||
AssemblyItem const& item = m_items.at(index); |
|||
if (item.type() == Tag || item == AssemblyItem(eth::Instruction::JUMPDEST)) |
|||
{ |
|||
// Do not allow any backwards jump. This is quite restrictive but should work for
|
|||
// the simplest things.
|
|||
if (path->visitedJumpdests.count(index)) |
|||
return GasMeter::GasConsumption::infinite(); |
|||
path->visitedJumpdests.insert(index); |
|||
} |
|||
else if (item == AssemblyItem(eth::Instruction::JUMP)) |
|||
{ |
|||
branchStops = true; |
|||
jumpTags = state->tagsInExpression(state->relativeStackElement(0)); |
|||
if (jumpTags.empty()) // unknown jump destination
|
|||
return GasMeter::GasConsumption::infinite(); |
|||
} |
|||
else if (item == AssemblyItem(eth::Instruction::JUMPI)) |
|||
{ |
|||
ExpressionClasses::Id condition = state->relativeStackElement(-1); |
|||
if (classes.knownNonZero(condition) || !classes.knownZero(condition)) |
|||
{ |
|||
jumpTags = state->tagsInExpression(state->relativeStackElement(0)); |
|||
if (jumpTags.empty()) // unknown jump destination
|
|||
return GasMeter::GasConsumption::infinite(); |
|||
} |
|||
branchStops = classes.knownNonZero(condition); |
|||
} |
|||
else if (SemanticInformation::altersControlFlow(item)) |
|||
branchStops = true; |
|||
|
|||
gas += meter.estimateMax(item); |
|||
|
|||
for (u256 const& tag: jumpTags) |
|||
{ |
|||
auto newPath = unique_ptr<GasPath>(new GasPath()); |
|||
newPath->index = m_items.size(); |
|||
if (m_tagPositions.count(tag)) |
|||
newPath->index = m_tagPositions.at(tag); |
|||
newPath->gas = gas; |
|||
newPath->largestMemoryAccess = meter.largestMemoryAccess(); |
|||
newPath->state = state->copy(); |
|||
newPath->visitedJumpdests = path->visitedJumpdests; |
|||
m_queue.push_back(move(newPath)); |
|||
} |
|||
|
|||
if (branchStops) |
|||
break; |
|||
} |
|||
|
|||
return gas; |
|||
} |
@ -0,0 +1,66 @@ |
|||
/*
|
|||
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 PathGasMeter.cpp
|
|||
* @author Christian <c@ethdev.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <set> |
|||
#include <vector> |
|||
#include <memory> |
|||
#include <libevmasm/GasMeter.h> |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace eth |
|||
{ |
|||
|
|||
class KnownState; |
|||
|
|||
struct GasPath |
|||
{ |
|||
size_t index = 0; |
|||
std::shared_ptr<KnownState> state; |
|||
u256 largestMemoryAccess; |
|||
GasMeter::GasConsumption gas; |
|||
std::set<size_t> visitedJumpdests; |
|||
}; |
|||
|
|||
/**
|
|||
* Computes an upper bound on the gas usage of a computation starting at a certain position in |
|||
* a list of AssemblyItems in a given state until the computation stops. |
|||
* Can be used to estimate the gas usage of functions on any given input. |
|||
*/ |
|||
class PathGasMeter |
|||
{ |
|||
public: |
|||
PathGasMeter(AssemblyItems const& _items); |
|||
|
|||
GasMeter::GasConsumption estimateMax(size_t _startIndex, std::shared_ptr<KnownState> const& _state); |
|||
|
|||
private: |
|||
GasMeter::GasConsumption handleQueueItem(); |
|||
|
|||
std::vector<std::unique_ptr<GasPath>> m_queue; |
|||
std::map<u256, size_t> m_tagPositions; |
|||
AssemblyItems const& m_items; |
|||
}; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,24 @@ |
|||
cmake_policy(SET CMP0015 NEW) |
|||
# this policy was introduced in cmake 3.0 |
|||
# remove if, once 3.0 will be used on unix |
|||
if (${CMAKE_MAJOR_VERSION} GREATER 2) |
|||
# old policy do not use MACOSX_RPATH |
|||
cmake_policy(SET CMP0042 OLD) |
|||
endif() |
|||
set(CMAKE_AUTOMOC OFF) |
|||
|
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") |
|||
|
|||
aux_source_directory(. SRC_LIST) |
|||
|
|||
include_directories(BEFORE ..) |
|||
|
|||
set(EXECUTABLE scrypt) |
|||
|
|||
file(GLOB HEADERS "*.h") |
|||
|
|||
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) |
|||
|
|||
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) |
|||
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) |
|||
|
@ -0,0 +1,9 @@ |
|||
Copyright (c) 2013, Joshua Small |
|||
All rights reserved. |
|||
|
|||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
|||
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
|||
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue