From 51f887aac5e7906f18dfe1aa74cd08be00ddd4a2 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 20 Jul 2015 19:38:40 +0200 Subject: [PATCH] Make sure all directories are not readable by baddies (dejavu wk1#0). Closes #2509. Remove neth :(. Who knows, perhaps not forever... --- CMakeLists.txt | 17 +- alethzero/NatspecHandler.cpp | 5 +- libdevcore/TransientDirectory.cpp | 8 +- libdevcrypto/SecretStore.cpp | 2 + libethereum/BlockChain.cpp | 5 +- libethereum/State.cpp | 1 + libethereum/Utility.cpp | 6 +- libweb3jsonrpc/WebThreeStubServer.cpp | 4 +- libwhisper/WhisperDB.cpp | 5 +- neth/CMakeLists.txt | 26 - neth/main.cpp | 1497 ------------------------- 11 files changed, 25 insertions(+), 1551 deletions(-) delete mode 100644 neth/CMakeLists.txt delete mode 100644 neth/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3330977aa..7fb6b3b94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,7 +38,6 @@ option(ETHKEY "Build the CLI key manager component" ON) option(SOLIDITY "Build the Solidity language components" ON) option(SERPENT "Build the Serpent language components" ON) option(TOOLS "Build the tools components" ON) -option(NCURSES "Build the NCurses components" OFF) option(GUI "Build GUI components (AlethZero, Mix)" ON) option(TESTS "Build the tests." ON) option(NOBOOST "No use of boost macros in test functions" OFF) @@ -209,7 +208,6 @@ eth_format_option(ETHKEY) eth_format_option(ETHASHCL) eth_format_option(JSCONSOLE) eth_format_option_on_decent_platform(SERPENT) -eth_format_option_on_decent_platform(NCURSES) if (JSCONSOLE) set(JSONRPC ON) @@ -227,7 +225,6 @@ if (BUNDLE STREQUAL "minimal") set(SOLIDITY OFF) set(USENPM OFF) set(GUI OFF) - set(NCURSES OFF) set(TOOLS ON) set(TESTS OFF) elseif (BUNDLE STREQUAL "full") @@ -235,7 +232,6 @@ elseif (BUNDLE STREQUAL "full") set(SOLIDITY ON) set(USENPM ON) set(GUI ON) -# set(NCURSES ${DECENT_PLATFORM}) set(TOOLS ON) set(TESTS ON) set(FATDB ON) @@ -244,7 +240,6 @@ elseif (BUNDLE STREQUAL "cli") set(SOLIDITY ON) set(USENPM ON) set(GUI OFF) -# set(NCURSES ${DECENT_PLATFORM}) set(TOOLS ON) set(TESTS ON) set(FATDB ON) @@ -253,7 +248,6 @@ elseif (BUNDLE STREQUAL "core") set(SOLIDITY ON) set(USENPM OFF) set(GUI ON) - set(NCURSES OFF) set(TOOLS ON) set(TESTS OFF) set(FATDB ON) @@ -262,7 +256,6 @@ elseif (BUNDLE STREQUAL "tests") set(SOLIDITY ON) set(USENPM OFF) set(GUI OFF) - set(NCURSES OFF) set(TOOLS OFF) set(TESTS ON) set(FATDB ON) @@ -271,7 +264,6 @@ elseif (BUNDLE STREQUAL "user") set(SOLIDITY OFF) set(USENPM OFF) set(GUI ON) -# set(NCURSES ${DECENT_PLATFORM}) set(TOOLS ON) set(TESTS OFF) elseif (BUNDLE STREQUAL "wallet") @@ -279,7 +271,6 @@ elseif (BUNDLE STREQUAL "wallet") set(SOLIDITY OFF) set(USENPM OFF) set(GUI OFF) - set(NCURSES OFF) set(TOOLS OFF) set(TESTS OFF) set(ETHKEY ON) @@ -290,7 +281,6 @@ elseif (BUNDLE STREQUAL "miner") set(SOLIDITY OFF) set(USENPM OFF) set(GUI OFF) - set(NCURSES OFF) set(TOOLS OFF) set(TESTS OFF) set(ETHKEY OFF) @@ -338,7 +328,6 @@ message("-- TOOLS Build basic tools ${TOOLS}") message("-- SOLIDITY Build Solidity language components ${SOLIDITY}") message("-- SERPENT Build Serpent language components ${SERPENT}") message("-- GUI Build GUI components ${GUI}") -message("-- NCURSES Build NCurses components ${NCURSES}") message("-- TESTS Build tests ${TESTS}") message("-- ETHASHCL Build OpenCL components (experimental!) ${ETHASHCL}") message("-- JSCONSOLE Build with javascript console ${JSCONSOLE}") @@ -373,7 +362,7 @@ if (EVMJIT) add_subdirectory(evmjit) endif() -if (TOOLS OR GUI OR SOLIDITY OR NCURSES OR TESTS) +if (TOOLS OR GUI OR SOLIDITY OR TESTS) set(GENERAL 1) else () set(GENERAL 0) @@ -469,10 +458,6 @@ if (TOOLS) endif() -#if (NCURSES) -# add_subdirectory(neth) -#endif () - if (GUI) add_subdirectory(libnatspec) diff --git a/alethzero/NatspecHandler.cpp b/alethzero/NatspecHandler.cpp index d00abc44f..6ed9f2b10 100644 --- a/alethzero/NatspecHandler.cpp +++ b/alethzero/NatspecHandler.cpp @@ -29,15 +29,16 @@ #include #include #include - using namespace dev; using namespace dev::eth; using namespace std; +namespace fs = boost::filesystem; NatspecHandler::NatspecHandler() { string path = Defaults::dbPath(); - boost::filesystem::create_directories(path); + fs::create_directories(path); + fs::permissions(path, fs::owner_all); ldb::Options o; o.create_if_missing = true; ldb::DB::Open(o, path + "/natspec", &m_db); diff --git a/libdevcore/TransientDirectory.cpp b/libdevcore/TransientDirectory.cpp index 8b7aa4467..31a826c24 100644 --- a/libdevcore/TransientDirectory.cpp +++ b/libdevcore/TransientDirectory.cpp @@ -27,6 +27,7 @@ #include "Log.h" using namespace std; using namespace dev; +namespace fs = boost::filesystem; TransientDirectory::TransientDirectory(): TransientDirectory((boost::filesystem::temp_directory_path() / "eth_transient" / toString(FixedHash<4>::random())).string()) @@ -39,13 +40,14 @@ TransientDirectory::TransientDirectory(std::string const& _path): if (boost::filesystem::exists(m_path)) BOOST_THROW_EXCEPTION(FileError()); - boost::filesystem::create_directories(m_path); + fs::create_directories(m_path); + fs::permissions(m_path, fs::owner_all); } TransientDirectory::~TransientDirectory() { boost::system::error_code ec; - boost::filesystem::remove_all(m_path, ec); + fs::remove_all(m_path, ec); if (!ec) return; @@ -56,7 +58,7 @@ TransientDirectory::~TransientDirectory() this_thread::sleep_for(chrono::milliseconds(10)); ec.clear(); - boost::filesystem::remove_all(m_path, ec); + fs::remove_all(m_path, ec); if (!ec) cwarn << "Failed to delete directory '" << m_path << "': " << ec.message(); } diff --git a/libdevcrypto/SecretStore.cpp b/libdevcrypto/SecretStore.cpp index a7a16a1b8..55c944e8e 100644 --- a/libdevcrypto/SecretStore.cpp +++ b/libdevcrypto/SecretStore.cpp @@ -137,6 +137,7 @@ void SecretStore::save(string const& _keysPath) { fs::path p(_keysPath); fs::create_directories(p); + fs::permissions(p, fs::owner_all); for (auto& k: m_keys) { string uuid = toUUID(k.first); @@ -158,6 +159,7 @@ void SecretStore::load(string const& _keysPath) { fs::path p(_keysPath); fs::create_directories(p); + fs::permissions(p, fs::owner_all); for (fs::directory_iterator it(p); it != fs::directory_iterator(); ++it) if (fs::is_regular_file(it->path())) readKey(it->path().string(), true); diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 61c3ecf0c..a992c5851 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -42,11 +42,11 @@ #include "State.h" #include "Utility.h" #include "Defaults.h" - using namespace std; using namespace dev; using namespace dev::eth; namespace js = json_spirit; +namespace fs = boost::filesystem; #define ETH_CATCH 1 #define ETH_TIMED_IMPORTS 1 @@ -156,7 +156,8 @@ unsigned BlockChain::open(std::string const& _path, WithExisting _we) string chainPath = path + "/" + toHex(m_genesisHash.ref().cropped(0, 4)); string extrasPath = chainPath + "/" + toString(c_databaseVersion); - boost::filesystem::create_directories(extrasPath); + fs::create_directories(extrasPath); + fs::permissions(extrasPath, fs::owner_all); bytes status = contents(extrasPath + "/minor"); unsigned lastMinor = c_minorProtocolVersion; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 64daaf5f8..95bb0febb 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -67,6 +67,7 @@ OverlayDB State::openDB(std::string const& _basePath, h256 const& _genesisHash, path += "/" + toHex(_genesisHash.ref().cropped(0, 4)) + "/" + toString(c_databaseVersion); boost::filesystem::create_directories(path); + fs::permissions(path, fs::owner_all); ldb::Options o; o.max_open_files = 256; diff --git a/libethereum/Utility.cpp b/libethereum/Utility.cpp index 1b97f82e7..f34f66463 100644 --- a/libethereum/Utility.cpp +++ b/libethereum/Utility.cpp @@ -113,12 +113,14 @@ void dev::eth::upgradeDatabase(std::string const& _basePath, h256 const& _genesi // write status if (!fs::exists(chainPath + "/blocks")) { - boost::filesystem::create_directories(chainPath); + fs::create_directories(chainPath); + fs::permissions(chainPath, fs::owner_all); fs::rename(path + "/blocks", chainPath + "/blocks"); if (!fs::exists(extrasPath + "/extras")) { - boost::filesystem::create_directories(extrasPath); + fs::create_directories(extrasPath); + fs::permissions(extrasPath, fs::owner_all); fs::rename(path + "/details", extrasPath + "/extras"); fs::rename(path + "/state", extrasPath + "/state"); writeFile(extrasPath + "/minor", rlp(minorProtocolVersion)); diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index bf49d3322..0a7277e06 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -34,6 +34,7 @@ using namespace std; using namespace dev; using namespace dev::eth; +namespace fs = boost::filesystem; bool isHex(std::string const& _s) { @@ -56,7 +57,8 @@ WebThreeStubServer::WebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, m_gp(_gp) { auto path = getDataDir() + "/.web3"; - boost::filesystem::create_directories(path); + fs::create_directories(path); + fs::permissions(path, fs::owner_all); ldb::Options o; o.create_if_missing = true; ldb::DB::Open(o, path, &m_db); diff --git a/libwhisper/WhisperDB.cpp b/libwhisper/WhisperDB.cpp index 7104723d7..9f7cebbeb 100644 --- a/libwhisper/WhisperDB.cpp +++ b/libwhisper/WhisperDB.cpp @@ -22,16 +22,17 @@ #include "WhisperDB.h" #include #include - using namespace std; using namespace dev; using namespace dev::shh; +namespace fs = boost::filesystem; WhisperDB::WhisperDB() { m_readOptions.verify_checksums = true; string path = dev::getDataDir("shh"); - boost::filesystem::create_directories(path); + fs::create_directories(path); + fs::permissions(path, fs::owner_all); leveldb::Options op; op.create_if_missing = true; op.max_open_files = 256; diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt deleted file mode 100644 index 68de36368..000000000 --- a/neth/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -cmake_policy(SET CMP0015 NEW) - -aux_source_directory(. SRC_LIST) - -include_directories(BEFORE ..) -include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) -include_directories(${DB_INCLUDE_DIRS}) -include_directories(${Boost_INCLUDE_DIRS}) - -set(EXECUTABLE neth) - -add_executable(${EXECUTABLE} ${SRC_LIST}) - -add_dependencies(${EXECUTABLE} BuildInfo.h) - -if (JSONRPC) - target_link_libraries(${EXECUTABLE} web3jsonrpc) -endif() - -target_link_libraries(${EXECUTABLE} webthree) -target_link_libraries(${EXECUTABLE} ethereum) -target_link_libraries(${EXECUTABLE} ncurses) -target_link_libraries(${EXECUTABLE} form) - -install( TARGETS ${EXECUTABLE} DESTINATION bin ) - diff --git a/neth/main.cpp b/neth/main.cpp deleted file mode 100644 index c3dc65715..000000000 --- a/neth/main.cpp +++ /dev/null @@ -1,1497 +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 . -*/ -/** @file main.cpp - * @author Gav Wood - * @date 2014 - * Ethereum client. - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#if ETH_JSONRPC || !ETH_TRUE -#include -#include -#include -#endif -#include "BuildInfo.h" - -#undef KEY_EVENT // from windows.h -#include -#undef OK -#include -#undef OK - -using namespace std; -using namespace dev; -using namespace dev::eth; -using namespace p2p; -using namespace boost::algorithm; -using dev::eth::Instruction; - -bool isTrue(std::string const& _m) -{ - return _m == "on" || _m == "yes" || _m == "true" || _m == "1"; -} - -bool isFalse(std::string const& _m) -{ - return _m == "off" || _m == "no" || _m == "false" || _m == "0"; -} - -void help() -{ - cout - << "Usage neth [OPTIONS]" << endl - << "Options:" << endl - << " -a,--address Set the coinbase (mining payout) address to addr (default: auto)." << endl - << " -b,--bootstrap Connect to the default Ethereum peerserver." << endl - << " -B,--block-fees Set the block fee profit in the reference unit e.g. ¢ (Default: 15)." << endl - << " -c,--client-name Add a name to your client's version string (default: blank)." << endl - << " -d,--db-path Load database from path (default: ~/.ethereum " << endl - << " /Etherum or Library/Application Support/Ethereum)." << endl - << " -D,--initdag Initialize DAG for mining and exit." << endl - << " -e,--ether-price Set the ether price in the reference unit e.g. ¢ (Default: 30.679)." << endl - << " -f,--force-mining Mine even when there are no transaction to mine (Default: off)" << endl - << " -h,--help Show this help message and exit." << endl -#if ETH_JSONRPC - << " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl - << " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: 8080)." << endl -#endif - << " -K,--kill-blockchain First kill the blockchain." << endl - << " --listen-ip Listen on the given IP for incoming connections (default: 0.0.0.0)." << endl - << " -l,--listen Listen on the given port for incoming connections (default: 30303)." << endl - << " -u,--public-ip Force public ip to given (default; auto)." << endl - << " -m,--mining Enable mining (default: off)" << endl - << " -n,--upnp Use upnp for NAT (default: on)." << endl - << " -o,--mode Start a full node or a peer node (Default: full)." << endl - << " -p,--port Connect to remote port (default: 30303)." << endl - << " -P,--priority <0 - 100> Default % priority of a transaction (default: 50)." << endl - << " -r,--remote Connect to remote host (default: none)." << endl - << " -s,--secret Set the secret key for use with send command (default: auto)." << endl - << " -t,--miners Number of mining threads to start (Default: " << thread::hardware_concurrency() << ")" << endl - << " -v,--verbosity <0..9> Set the log verbosity from 0 to 9 (tmp forced to 1)." << endl - << " -x,--peers Attempt to connect to given number of peers (default: 5)." << endl - << " -V,--version Show the version and exit." << endl -#if ETH_EVMJIT - << " --vm Select VM. Options are: interpreter, jit, smart. (default: interpreter)" << endl -#endif - ; - exit(0); -} - -void interactiveHelp() -{ - cout - << "Commands:" << endl - << " netstart Starts the network sybsystem on a specific port." << endl - << " netstop Stops the network subsystem." << endl -#if ETH_JSONRPC - << " jsonstart Starts the JSON-RPC server." << endl - << " jsonstop Stops the JSON-RPC server." << endl -#endif - << " connect Connects to a specific peer." << endl - << " minestart Starts mining." << endl - << " minestop Stops mining." << endl - << " address Gives the current address." << endl - << " secret Gives the current secret" << endl - << " block Gives the current block height." << endl - << " balance Gives the current balance." << endl - << " peers List the peers that are connected" << endl - << " transact Execute a given transaction." << endl - << " send Execute a given transaction with current secret." << endl - << " contract Create a new contract with current secret." << endl - << " inspect Dumps a contract to /.evm." << endl - << " verbosity () Gets or sets verbosity level." << endl - << " setblockfees Set the block fee profit in the reference unit e.g. ¢ (Default: 15)" << endl - << " setetherprice

Resets the ether price." << endl - << " setpriority

Resets the transaction priority." << endl - << " reset Resets ncurses windows" << endl - << " exit Exits the application." << endl; -} - -string credits() -{ - std::ostringstream ccout; - ccout - << "NEthereum (++) " << dev::Version << endl - << " Code by Gav Wood & caktux, (c) 2013, 2014, 2015." << endl - << " Based on a design by Vitalik Buterin." << endl << endl; - - ccout << "Type 'netstart 30303' to start networking" << endl; - ccout << "Type 'connect " << Host::pocHost() << " 30303' to connect" << endl; - ccout << "Type 'exit' to quit" << endl << endl; - return ccout.str(); -} - -void version() -{ - cout << "neth version " << dev::Version << endl; - cout << "eth network protocol version: " << dev::eth::c_protocolVersion << endl; - cout << "Client database version: " << dev::eth::c_databaseVersion << endl; - cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl; - exit(0); -} - -Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); -string pretty(h160 _a, dev::eth::State _st) -{ - string ns; - h256 n; - if (h160 nameReg = (u160)_st.storage(c_config, 0)) - n = _st.storage(nameReg, (u160)(_a)); - if (n) - { - std::string s((char const*)n.data(), 32); - if (s.find_first_of('\0') != string::npos) - s.resize(s.find_first_of('\0')); - ns = " " + s; - } - return ns; -} - -bool g_exit = false; - -void sighandler(int) -{ - g_exit = true; -} - -namespace nc -{ - -class nc_window_streambuf: public std::streambuf -{ -public: - nc_window_streambuf(WINDOW* p, std::ostream& os, unsigned long cursesAttr = 0); - nc_window_streambuf(WINDOW* p, unsigned long _cursesAttr = 0); - nc_window_streambuf(nc_window_streambuf const& _rhs); - virtual ~nc_window_streambuf(); - - nc_window_streambuf& operator=(nc_window_streambuf const& _rhs); - - virtual int overflow(int c); - virtual int sync(); - -private: - void copy(nc_window_streambuf const& _rhs); - - WINDOW* m_pnl; - unsigned long m_flags; - std::ostream* m_os; - std::streambuf* m_old; -}; - -nc_window_streambuf::nc_window_streambuf(WINDOW * p, unsigned long _cursesAttr): - m_pnl(p), - m_flags(_cursesAttr), - m_os(0), - m_old(0) -{ - // Tell parent class that we want to call overflow() for each - // input char: - setp(0, 0); - setg(0, 0, 0); - scrollok(p, true); - mvwinch(p, 0, 0); -} - -nc_window_streambuf::nc_window_streambuf(WINDOW* _p, std::ostream& _os, unsigned long _cursesAttr): - m_pnl(_p), - m_flags(_cursesAttr), - m_os(&_os), - m_old(_os.rdbuf()) -{ - setp(0, 0); - setg(0, 0, 0); - _os.rdbuf(this); - scrollok(_p, true); - mvwinch(_p, 0, 0); -} - -void nc_window_streambuf::copy(nc_window_streambuf const& _rhs) -{ - if (this != &_rhs) - { - m_pnl = _rhs.m_pnl; - m_flags = _rhs.m_flags; - m_os = _rhs.m_os; - m_old = _rhs.m_old; - } -} - -nc_window_streambuf::nc_window_streambuf(nc_window_streambuf const& _rhs): - std::streambuf() -{ - copy(_rhs); -} - -nc_window_streambuf& nc_window_streambuf::operator=(nc_window_streambuf const& _rhs) -{ - copy(_rhs); - return *this; -} - -nc_window_streambuf::~nc_window_streambuf() -{ - if (m_os) - m_os->rdbuf(m_old); -} - -int nc_window_streambuf::overflow(int c) -{ - int ret = c; - if (c != EOF) - { - int x = 0; - int y = 0; - int mx = 0; - int my = 0; - getyx(m_pnl, y, x); - getmaxyx(m_pnl, my, mx); - if (y < 1) - y = 1; - if (x < 2) - x = 2; - if (x > mx - 4) - { - if (y + 1 >= my) - scroll(m_pnl); - else - y++; - x = 2; - } - if (m_flags) - { - wattron(m_pnl, m_flags); - if (mvwaddch(m_pnl, y, x++, (chtype)c) == ERR) - ret = EOF; - wattroff(m_pnl, m_flags); - } - else if (mvwaddch(m_pnl, y, x++, (chtype)c) == ERR) - ret = EOF; - } - if (c == EOF) // || std::isspace(c) - if (sync() == EOF) - ret = EOF; - return ret; -} - -int nc_window_streambuf::sync() -{ - if (stdscr && m_pnl) - return (wrefresh(m_pnl) == ERR) ? EOF : 0; - return EOF; -} - -} - -vector form_dialog(vector _sfields, vector _lfields, vector _bfields, int _cols, int _rows, string _post_form); - -enum class NodeMode -{ - PeerServer, - Full -}; - -int main(int argc, char** argv) -{ - string listenIP; - unsigned short listenPort = 30303; - string publicIP; - string remoteHost; - unsigned short remotePort = 30303; - string dbPath; - unsigned mining = ~(unsigned)0; - NodeMode mode = NodeMode::Full; - unsigned peers = 5; -#if ETH_JSONRPC - int jsonrpc = 8080; -#endif - bool bootstrap = false; - bool upnp = true; - bool forceMining = false; - bool killChain = false; - bool structuredLogging = false; - string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S"; - string clientName; - TransactionPriority priority = TransactionPriority::Medium; - double etherPrice = 30.679; - double blockFees = 15.0; - - // Init defaults - Defaults::get(); - - // Our address. - KeyPair us = KeyPair::create(); - Address coinbase = us.address(); - - string configFile = getDataDir() + "/config.rlp"; - bytes b = contents(configFile); - if (b.size()) - { - RLP config(b); - us = KeyPair(config[0].toHash()); - coinbase = config[1].toHash

(); - } - else - writeFile(configFile, rlpList(us.secret(), coinbase)); - - for (int i = 1; i < argc; ++i) - { - string arg = argv[i]; - if (arg == "--listen-ip" && i + 1 < argc) - listenIP = argv[++i]; - else if ((arg == "-l" || arg == "--listen" || arg == "--listen-port") && i + 1 < argc) - listenPort = (short)atoi(argv[++i]); - else if ((arg == "-u" || arg == "--public-ip" || arg == "--public") && i + 1 < argc) - publicIP = argv[++i]; - else if ((arg == "-r" || arg == "--remote") && i + 1 < argc) - remoteHost = argv[++i]; - else if ((arg == "-p" || arg == "--port") && i + 1 < argc) - remotePort = (short)atoi(argv[++i]); - else if ((arg == "-n" || arg == "--upnp") && i + 1 < argc) - { - string m = argv[++i]; - if (isTrue(m)) - upnp = true; - else if (isFalse(m)) - upnp = false; - else - { - cerr << "Invalid UPnP option: " << m << endl; - return -1; - } - } - else if (arg == "-K" || arg == "--kill-blockchain") - killChain = true; - else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc) - clientName = argv[++i]; - else if ((arg == "-a" || arg == "--address" || arg == "--coinbase-address") && i + 1 < argc) - { - try - { - coinbase = h160(fromHex(argv[++i], WhenError::Throw)); - } - catch (BadHexCharacter& _e) - { - cwarn << "invalid hex character, coinbase rejected"; - cwarn << boost::diagnostic_information(_e); - break; - } - catch (...) - { - cwarn << "coinbase rejected"; - break; - } - } - else if ((arg == "-s" || arg == "--secret") && i + 1 < argc) - us = KeyPair(h256(fromHex(argv[++i]))); - else if (arg == "--structured-logging-format" && i + 1 < argc) - structuredLoggingFormat = string(argv[++i]); - else if (arg == "--structured-logging") - structuredLogging = true; - else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc) - dbPath = argv[++i]; - else if ((arg == "-B" || arg == "--block-fees") && i + 1 < argc) - { - try - { - blockFees = stof(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[++i] << endl; - return -1; - } - } - else if ((arg == "-e" || arg == "--ether-price") && i + 1 < argc) - { - try - { - etherPrice = stof(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[++i] << endl; - return -1; - } - } - else if ((arg == "-P" || arg == "--priority") && i + 1 < argc) - { - string m = boost::to_lower_copy(string(argv[++i])); - if (m == "lowest") - priority = TransactionPriority::Lowest; - else if (m == "low") - priority = TransactionPriority::Low; - else if (m == "medium" || m == "mid" || m == "default" || m == "normal") - priority = TransactionPriority::Medium; - else if (m == "high") - priority = TransactionPriority::High; - else if (m == "highest") - priority = TransactionPriority::Highest; - else - try { - priority = (TransactionPriority)(max(0, min(100, stoi(m))) * 8 / 100); - } - catch (...) { - cerr << "Unknown " << arg << " option: " << m << endl; - return -1; - } - } - else if ((arg == "-m" || arg == "--mining") && i + 1 < argc) - { - string m = argv[++i]; - if (isTrue(m)) - mining = ~(unsigned)0; - else if (isFalse(m)) - mining = 0; - else - try { - mining = stoi(m); - } - catch (...) { - cerr << "Unknown -m/--mining option: " << m << endl; - return -1; - } - } - else if (arg == "-b" || arg == "--bootstrap") - bootstrap = true; - else if (arg == "-f" || arg == "--force-mining") - forceMining = true; -#if ETH_JSONRPC - else if ((arg == "-j" || arg == "--json-rpc")) - jsonrpc = jsonrpc ? jsonrpc : 8080; - else if (arg == "--json-rpc-port" && i + 1 < argc) - jsonrpc = atoi(argv[++i]); -#endif - else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc) - g_logVerbosity = atoi(argv[++i]); - else if ((arg == "-x" || arg == "--peers") && i + 1 < argc) - peers = atoi(argv[++i]); - else if ((arg == "-o" || arg == "--mode") && i + 1 < argc) - { - string m = argv[++i]; - if (m == "full") - mode = NodeMode::Full; - else if (m == "peer") - mode = NodeMode::PeerServer; - else - { - cerr << "Unknown mode: " << m << endl; - return -1; - } - } -#if ETH_EVMJIT - else if (arg == "--vm" && i + 1 < argc) - { - string vmKind = argv[++i]; - if (vmKind == "interpreter") - VMFactory::setKind(VMKind::Interpreter); - else if (vmKind == "jit") - VMFactory::setKind(VMKind::JIT); - else if (vmKind == "smart") - VMFactory::setKind(VMKind::Smart); - else - { - cerr << "Unknown VM kind: " << vmKind << endl; - return -1; - } - } -#endif - else if (arg == "-h" || arg == "--help") - help(); - else if (arg == "-V" || arg == "--version") - version(); - else - { - cerr << "Invalid argument: " << arg << endl; - exit(-1); - } - } - - if (!clientName.empty()) - clientName += "/"; - - cout << credits(); - - StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat); - auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp); - auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp"); - std::string clientImplString = "N++eth/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM)); - dev::WebThreeDirect web3( - clientImplString, - dbPath, - killChain ? WithExisting::Kill : WithExisting::Trust, - mode == NodeMode::Full ? set{"eth", "shh"} : set(), - netPrefs, - &nodesState); - - web3.setIdealPeerCount(peers); - std::shared_ptr gasPricer = make_shared(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000)); - eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; - StructuredLogger::starting(clientImplString, dev::Version); - if (c) - { - c->setGasPricer(gasPricer); - c->setForceMining(forceMining); - c->setAddress(coinbase); - } - - cout << "Transaction Signer: " << us.address() << endl; - cout << "Mining Benefactor: " << coinbase << endl; - web3.startNetwork(); - - if (bootstrap) - web3.addNode(p2p::NodeId(), Host::pocHost()); - if (remoteHost.size()) - web3.addNode(p2p::NodeId(), remoteHost + ":" + toString(remotePort)); - if (c && mining) - c->startMining(); - -#if ETH_JSONRPC || !ETH_TRUE - shared_ptr jsonrpcServer; - unique_ptr jsonrpcConnector; - KeyManager km; - if (jsonrpc > -1) - { - jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads)); - jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){ return web3.ethereum(); }, vector({us})), vector({us})), km); - jsonrpcServer->setIdentities({us}); - jsonrpcServer->StartListening(); - } -#endif - - signal(SIGABRT, &sighandler); - signal(SIGTERM, &sighandler); - signal(SIGINT, &sighandler); - - std::ostringstream ccout; - - // Initialize ncurses - char* str = new char[255]; - int width; - int height; - int y = 0; - int x = 2; - string cmd; - WINDOW * mainwin, * consolewin, * logwin, * blockswin, * pendingwin, *addswin, * contractswin, * peerswin; - - if (!(mainwin = initscr())) - { - cerr << "Error initialising ncurses."; - delete [] str; - return -1; - } - - getmaxyx(mainwin, height, width); - int qheight = height * 3 / 5; - int qwidth = width / 4 - 4; - - nonl(); - cbreak(); - timeout(30000); - echo(); - keypad(mainwin, true); - - // Initialize color pairs - start_color(); - init_pair(1, COLOR_WHITE, COLOR_BLACK); - init_pair(2, COLOR_RED, COLOR_BLACK); - init_pair(3, 7, COLOR_BLACK); - use_default_colors(); - - logwin = newwin(height * 2 / 5 - 2, width * 2 / 3, qheight, 0); - nc::nc_window_streambuf outbuf(logwin, std::cout); - nc::nc_window_streambuf eoutbuf(logwin, std::cerr); - - consolewin = newwin(qheight, width / 4, 0, 0); - nc::nc_window_streambuf coutbuf(consolewin, ccout); - blockswin = newwin(qheight, width / 4, 0, width / 4); - pendingwin = newwin(height * 1 / 5, width / 4, 0, width * 2 / 4); - peerswin = newwin(height * 2 / 5, width / 4, height * 1 / 5, width * 2 / 4); - addswin = newwin(height * 2 / 5 - 2, width / 3, qheight, width * 2 / 3); - contractswin = newwin(qheight, width / 4, 0, width * 3 / 4); - - int vl = qheight - 4; - wsetscrreg(consolewin, 1, vl); - wsetscrreg(blockswin, 1, vl); - wsetscrreg(pendingwin, 1, vl); - wsetscrreg(peerswin, 1, vl); - wsetscrreg(addswin, 1, vl); - wsetscrreg(contractswin, 1, vl); - - mvwprintw(mainwin, 1, 1, " > "); - wresize(mainwin, 3, width); - mvwin(mainwin, height - 3, 0); - - wmove(mainwin, 1, 4); - - while (true) - { - wclrtobot(consolewin); - wclrtobot(pendingwin); - wclrtobot(peerswin); - wclrtobot(addswin); - wclrtobot(contractswin); - - ccout << credits(); - - // Prompt - wmove(mainwin, 1, 4); - getstr(str); - - string s(str); - istringstream iss(s); - iss >> cmd; - - // Address - ccout << "Address:" << endl; - ccout << toHex(us.address().asArray()) << endl << endl; - - mvwprintw(mainwin, 1, 1, " > "); - clrtoeol(); - - if (s.length() > 1) - { - ccout << "> "; - ccout << str << endl; - } - - if (cmd == "netstart") - { - unsigned port; - iss >> port; - if (port) - netPrefs.listenPort = port; - web3.setNetworkPreferences(netPrefs); - web3.startNetwork(); - } - else if (cmd == "connect") - { - string addr; - unsigned port; - iss >> addr >> port; - web3.addNode(p2p::NodeId(), addr + ":" + toString(port ? port : p2p::c_defaultIPPort)); - } - else if (cmd == "netstop") - { - web3.stopNetwork(); - } - else if (c && cmd == "minestart") - { - c->startMining(); - } - else if (c && cmd == "minestop") - { - c->stopMining(); - } - else if (c && cmd == "mineforce") - { - string enable; - iss >> enable; - c->setForceMining(isTrue(enable)); - } - else if (c && cmd == "setblockfees") - { - iss >> blockFees; - try - { - gasPricer->setRefBlockFees(u256(blockFees * 1000)); - } - catch (Overflow const& _e) - { - cout << boost::diagnostic_information(_e); - } - - cout << "Block fees: " << blockFees << endl; - } - else if (c && cmd == "setetherprice") - { - iss >> etherPrice; - if (etherPrice == 0) - cout << "ether price cannot be set to zero" << endl; - else - { - try - { - gasPricer->setRefPrice(u256(double(ether / 1000) / etherPrice)); - } - catch (Overflow const& _e) - { - cout << boost::diagnostic_information(_e); - } - } - cout << "ether Price: " << etherPrice << endl; - } - else if (c && cmd == "setpriority") - { - string m; - iss >> m; - boost::to_lower(m); - if (m == "lowest") - priority = TransactionPriority::Lowest; - else if (m == "low") - priority = TransactionPriority::Low; - else if (m == "medium" || m == "mid" || m == "default" || m == "normal") - priority = TransactionPriority::Medium; - else if (m == "high") - priority = TransactionPriority::High; - else if (m == "highest") - priority = TransactionPriority::Highest; - else - try { - priority = (TransactionPriority)(max(0, min(100, stoi(m))) * 8 / 100); - } - catch (...) { - cerr << "Unknown priority: " << m << endl; - } - cout << "Priority: " << (int)priority << "/8" << endl; - } - else if (cmd == "verbosity") - { - if (iss.peek() != -1) - iss >> g_logVerbosity; - cout << "Verbosity: " << g_logVerbosity << endl; - } -#if ETH_JSONRPC - else if (cmd == "jsonport") - { - if (iss.peek() != -1) - iss >> jsonrpc; - cout << "JSONRPC Port: " << jsonrpc << endl; - } - else if (cmd == "jsonstart") - { - if (jsonrpc < 0) - jsonrpc = 8080; -#if ETH_DEBUG - jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", 1)); -#else - jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", 4)); -#endif - jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){ return web3.ethereum(); }, vector({us})), vector({us}))); - jsonrpcServer->setIdentities({us}); - jsonrpcServer->StartListening(); - } - else if (cmd == "jsonstop") - { - if (jsonrpcServer.get()) - jsonrpcServer->StopListening(); - jsonrpcServer.reset(); - } -#endif - else if (cmd == "address") - { - ccout << "Current address:" << endl; - ccout << toHex(us.address().asArray()) << endl; - } - else if (cmd == "secret") - { - ccout << "Current secret:" << endl; - ccout << toHex(us.secret().asArray()) << endl; - } - else if (c && cmd == "block") - { - unsigned n = c->blockChain().details().number; - ccout << "Current block # "; - ccout << toString(n) << endl; - } - else if (cmd == "peers") - { - for (auto it: web3.peers()) - cout << it.host << ":" << it.port << ", " << it.clientVersion << ", " - << std::chrono::duration_cast(it.lastPing).count() << "ms" - << endl; - } - else if (c && cmd == "balance") - { - u256 balance = c->balanceAt(us.address()); - ccout << "Current balance:" << endl; - ccout << toString(balance) << endl; - } - else if (c && cmd == "transact") - { - auto const& bc = c->blockChain(); - auto h = bc.currentHash(); - auto blockData = bc.block(h); - BlockInfo info(blockData); - vector s; - s.push_back("Address"); - vector l; - l.push_back("Amount"); - stringstream label; - label << "Gas price"; - l.push_back(label.str()); - l.push_back("Gas"); - vector b; - b.push_back("Secret"); - b.push_back("Data"); - vector fields = form_dialog(s, l, b, height, width, cmd); - int fs = fields.size(); - if (fs < 6) - { - if (fs > 0) - cwarn << "Missing parameter"; - } - else - { - fields[0].erase(std::remove(fields[0].begin(), fields[0].end(), ' '), fields[0].end()); - fields[4].erase(std::remove(fields[4].begin(), fields[4].end(), ' '), fields[4].end()); - fields[5].erase(std::find_if(fields[5].rbegin(), fields[5].rend(), std::bind1st(std::not_equal_to(), ' ')).base(), fields[5].end()); - int size = fields[0].length(); - u256 amount; - u256 gasPrice; - u256 gas; - stringstream ssa; - ssa << fields[1]; - ssa >> amount; - stringstream ssg; - ssg << fields[3]; - ssg >> gas; - stringstream ssp; - ssp << fields[2]; - ssp >> gasPrice; - if (!gasPrice) - gasPrice = gasPricer->bid(priority); - string sechex = fields[4]; - string sdata = fields[5]; - cnote << "Data:"; - cnote << sdata; - bytes data = dev::eth::parseData(sdata); - cnote << "Bytes:"; - string sbd = asString(data); - bytes bbd = asBytes(sbd); - stringstream ssbd; - ssbd << bbd; - cnote << ssbd.str(); - int ssize = fields[4].length(); - u256 minGas = (u256)Transaction::gasRequired(data, 0); - if (size < 40) - { - if (size > 0) - cwarn << "Invalid address length:" << size; - } - else if (gas < minGas) - cwarn << "Minimum gas amount is" << minGas; - else if (ssize < 40) - { - if (ssize > 0) - cwarn << "Invalid secret length:" << ssize; - } - else - { - try - { - Secret secret = h256(fromHex(sechex, WhenError::Throw)); - Address dest = h160(fromHex(fields[0], WhenError::Throw)); - c->submitTransaction(secret, amount, dest, data, gas, gasPrice); - } - catch (BadHexCharacter& _e) - { - cwarn << "invalid hex character, transaction rejected"; - cwarn << boost::diagnostic_information(_e); - } - catch (...) - { - cwarn << "transaction rejected"; - } - } - } - } - else if (c && cmd == "send") - { - vector s; - s.push_back("Address"); - vector l; - l.push_back("Amount"); - vector b; - vector fields = form_dialog(s, l, b, height, width, cmd); - int fs = fields.size(); - if (fs < 2) - { - if (fs > 0) - cwarn << "Missing parameter"; - } - else - { - fields[0].erase(std::remove(fields[0].begin(), fields[0].end(), ' '), fields[0].end()); - int size = fields[0].length(); - u256 amount; - stringstream sss; - sss << fields[1]; - sss >> amount; - if (size < 40) - { - if (size > 0) - cwarn << "Invalid address length:" << size; - } - else - { - auto const& bc = c->blockChain(); - auto h = bc.currentHash(); - auto blockData = bc.block(h); - BlockInfo info(blockData); - u256 minGas = (u256)Transaction::gasRequired(bytes(), 0); - try - { - Address dest = h160(fromHex(fields[0], WhenError::Throw)); - c->submitTransaction(us.secret(), amount, dest, bytes(), minGas); - } - catch (BadHexCharacter& _e) - { - cwarn << "invalid hex character, transaction rejected"; - cwarn << boost::diagnostic_information(_e); - } - catch (...) - { - cwarn << "transaction rejected"; - } - } - } - } - else if (c && cmd == "contract") - { - auto const& bc = c->blockChain(); - auto h = bc.currentHash(); - auto blockData = bc.block(h); - BlockInfo info(blockData); - vector s; - vector l; - l.push_back("Endowment"); - stringstream label; - label << "Gas price"; - l.push_back(label.str()); - l.push_back("Gas"); - vector b; - b.push_back("Code (hex)"); - vector fields = form_dialog(s, l, b, height, width, cmd); - int fs = fields.size(); - if (fs < 4) - { - if (fs > 0) - cwarn << "Missing parameter"; - } - else - { - u256 endowment; - u256 gas; - u256 gasPrice; - stringstream sse; - sse << fields[0]; - sse >> endowment; - stringstream ssg; - ssg << fields[2]; - ssg >> gas; - stringstream ssp; - ssp << fields[1]; - ssp >> gasPrice; - string sinit = fields[3]; - trim_all(sinit); - int size = sinit.length(); - bytes init; - cnote << "Init:"; - cnote << sinit; - cnote << "Code size:" << size; - if (size < 1) - cwarn << "No code submitted"; - else - { - cnote << "Assembled:"; - stringstream ssc; - try - { - init = fromHex(sinit, WhenError::Throw); - } - catch (BadHexCharacter& _e) - { - cwarn << "invalid hex character, code rejected"; - cwarn << boost::diagnostic_information(_e); - init = bytes(); - } - catch (...) - { - cwarn << "code rejected"; - init = bytes(); - } - - ssc.str(string()); - ssc << disassemble(init); - cnote << "Init:"; - cnote << ssc.str(); - } - u256 minGas = (u256)Transaction::gasRequired(init, 0); - if (!init.size()) - cwarn << "Contract creation aborted, no init code."; - else if (endowment < 0) - cwarn << "Invalid endowment"; - else if (gas < minGas) - cwarn << "Minimum gas amount is" << minGas; - else - c->submitTransaction(us.secret(), endowment, init, gas); - } - } - else if (c && cmd == "inspect") - { - string rechex; - iss >> rechex; - - if (rechex.length() != 40) - cwarn << "Invalid address length"; - else - { - auto address = h160(fromHex(rechex)); - stringstream s; - - try - { - auto storage = c->storageAt(address); - for (auto const& i: storage) - s << "@" << showbase << hex << i.first << " " << showbase << hex << i.second << endl; - s << endl << disassemble(c->codeAt(address)) << endl; - - string outFile = getDataDir() + "/" + rechex + ".evm"; - ofstream ofs; - ofs.open(outFile, ofstream::binary); - ofs.write(s.str().c_str(), s.str().length()); - ofs.close(); - - cnote << "Saved" << rechex << "to" << outFile; - } - catch (dev::InvalidTrie const& _e) - { - cwarn << "Corrupted trie.\n" << diagnostic_information(_e); - } - } - } - else if (cmd == "reset") - { - vector ws { consolewin, blockswin, pendingwin, peerswin, contractswin, addswin, mainwin }; - for (auto &w: ws) - { - wclear(w); - wrefresh(w); - } - } - else if (cmd == "help") - interactiveHelp(); - else if (cmd == "exit") - break; - else if (cmd != "") - cwarn << "Unrecognised command. Type 'help' for a list of available commands."; - - // Clear cmd at each pass - cmd = ""; - - - // Contracts and addresses count / offset - int cc = 1; - int ca = 0; - - if (c) { - // Lock to prevent corrupt block-chain errors - auto const& bc = c->blockChain(); - ccout << "Genesis hash: " << bc.genesisHash() << endl; - - // Blocks - y = 1; - for (auto h = bc.currentHash(); h != bc.genesisHash(); h = bc.details(h).parent) - { - auto d = bc.details(h); - string s = "# " + std::to_string(d.number) + ' ' + toString(h); // .abridged(); - mvwaddnstr(blockswin, y++, x, s.c_str(), qwidth); - - auto b = bc.block(h); - for (auto const& i: RLP(b)[1]) - { - Transaction t(i.data(), CheckTransaction::Everything); - auto s = t.receiveAddress() ? - boost::format(" %1% %2%> %3%: %4% [%5%]") % - toString(t.safeSender()) % - (c->codeAt(t.receiveAddress(), PendingBlock).size() ? '*' : '-') % - toString(t.receiveAddress()) % - toString(formatBalance(t.value())) % - toString((unsigned)t.nonce()) : - boost::format(" %1% +> %2%: %3% [%4%]") % - toString(t.safeSender()) % - toString(right160(sha3(rlpList(t.safeSender(), t.nonce())))) % - toString(formatBalance(t.value())) % - toString((unsigned)t.nonce()); - mvwaddnstr(blockswin, y++, x, s.str().c_str(), qwidth - 2); - if (y > qheight - 2) - break; - } - if (y > qheight - 2) - break; - } - - - // Pending - y = 1; - for (Transaction const& t: c->pending()) - { - auto s = t.receiveAddress() ? - boost::format("%1% %2%> %3%: %4% [%5%]") % - toString(t.safeSender()) % - (c->codeAt(t.receiveAddress(), PendingBlock).size() ? '*' : '-') % - toString(t.receiveAddress()) % - toString(formatBalance(t.value())) % - toString((unsigned)t.nonce()) : - boost::format("%1% +> %2%: %3% [%4%]") % - toString(t.safeSender()) % - toString(right160(sha3(rlpList(t.safeSender(), t.nonce())))) % - toString(formatBalance(t.value())) % - toString((unsigned)t.nonce()); - mvwaddnstr(pendingwin, y++, x, s.str().c_str(), qwidth); - if (y > height * 1 / 5 - 2) - break; - } - -#if ETH_FATDB - // Contracts and addresses - y = 1; - auto acs = c->addresses(); - ca = acs.size(); - for (auto const& i: acs) - if (c->codeAt(i, PendingBlock).size()) - { - auto s = boost::format("%1%%2% : %3% [%4%]") % - toString(i) % - pretty(i, c->postState()) % - toString(formatBalance(c->balanceAt(i))) % - toString((unsigned)c->countAt(i, PendingBlock)); - mvwaddnstr(contractswin, cc++, x, s.str().c_str(), qwidth); - if (cc > qheight - 2) - break; - } - for (auto const& i: acs) - if (c->codeAt(i, PendingBlock).empty()) - { - auto s = boost::format("%1%%2% : %3% [%4%]") % - toString(i) % - pretty(i, c->postState()) % - toString(formatBalance(c->balanceAt(i))) % - toString((unsigned)c->countAt(i, PendingBlock)); - mvwaddnstr(addswin, y++, x, s.str().c_str(), width / 2 - 4); - if (y > height * 3 / 5 - 4) - break; - } -#else - mvwaddnstr(contractswin, 1, x, "build with ETH_FATDB to list contracts", qwidth); - mvwaddnstr(addswin, 1, x, "build with ETH_FATDB to list addresses", width / 2 - 4); -#endif - - // Peers - y = 1; - for (PeerSessionInfo const& i: web3.peers()) - { - auto s = boost::format("%1% ms - %2%:%3% - %4%") % - toString(chrono::duration_cast(i.lastPing).count()) % - i.host % - toString(i.port) % - i.clientVersion; - mvwaddnstr(peerswin, y++, x, s.str().c_str(), qwidth); - if (y > height * 2 / 5 - 4) - break; - } - } - - box(consolewin, 0, 0); - box(blockswin, 0, 0); - box(pendingwin, 0, 0); - box(peerswin, 0, 0); - box(addswin, 0, 0); - box(contractswin, 0, 0); - box(mainwin, 0, 0); - - // Balance - stringstream ssb; - u256 balance; - if (c) - balance = c->balanceAt(us.address()); - ssb << "Balance: "; - if (c) - ssb << formatBalance(balance); - mvwprintw(consolewin, 0, x, ssb.str().c_str()); - - // Block - mvwprintw(blockswin, 0, x, "Block # "); - if (c) { - unsigned n = c->blockChain().details().number; - mvwprintw(blockswin, 0, 10, toString(n).c_str()); - } - - // Pending - stringstream pc; - pc << "Pending: "; - if (c) - pc << toString(c->pending().size()); - else - pc << 0; - mvwprintw(pendingwin, 0, x, pc.str().c_str()); - - // Contracts - stringstream sc; - sc << "Contracts: " << cc - 1; - mvwprintw(contractswin, 0, x, sc.str().c_str()); - - // Peers - mvwprintw(peerswin, 0, x, "Peers: "); - mvwprintw(peerswin, 0, 9, toString(web3.peers().size()).c_str()); - - // Mining flag - if (c && c->isMining()) - { - mvwprintw(consolewin, qheight - 1, width / 4 - 11, "Mining ON"); - dev::eth::MiningProgress p = c->miningProgress(); - auto speed = boost::format("%2% kH/s @ %1%s") % (p.ms / 1000) % (p.ms ? p.hashes / p.ms : 0); - mvwprintw(consolewin, qheight - 2, width / 4 - speed.str().length() - 2, speed.str().c_str()); - } - else - mvwprintw(consolewin, qheight - 1, width / 4 - 12, "Mining OFF"); - - wmove(consolewin, 1, x); - - // Addresses - stringstream ac; - ac << "Addresses: " << ca; - mvwprintw(addswin, 0, x, ac.str().c_str()); - - - wrefresh(consolewin); - wrefresh(blockswin); - wrefresh(pendingwin); - wrefresh(peerswin); - wrefresh(addswin); - wrefresh(contractswin); - wrefresh(mainwin); - } - - delwin(addswin); - delwin(contractswin); - delwin(peerswin); - delwin(pendingwin); - delwin(blockswin); - delwin(consolewin); - delwin(logwin); - delwin(mainwin); - endwin(); - refresh(); - -#if ETH_JSONRPC - if (jsonrpcServer.get()) - jsonrpcServer->StopListening(); -#endif - - return 0; -} - -void print_in_middle(WINDOW *win, int starty, int startx, int width, string str, chtype color) -{ - int length; - int x = 0; - int y = 0; - float temp; - - if (startx != 0) - x = startx; - if (starty != 0) - y = starty; - if (width == 0) - width = 80; - - length = str.length(); - temp = (width - length) / 2; - x = x + (int)temp; - wattron(win, color); - mvwprintw(win, y, x, "%s", str.c_str()); - wattroff(win, color); - refresh(); -} - -vector form_dialog(vector _sv, vector _lv, vector _bv, int _cols, int _rows, string _post_form) -{ - vector vs; - WINDOW *form_win; - int _sfields = _sv.size(); - int _lfields = _lv.size(); - int _bfields = _bv.size(); - int maxfields = _sfields + _lfields + _bfields; - vector field(maxfields + 1); - - int ch; - int starty = 6; - int height = _cols; - int width = _rows; - - // Initialize the fields - int si; - int li; - int bi = 0; - vector labels; - for (si = 0; si < _sfields; ++si) - { - starty++; // Leave room for our labels, no window yet so that or fake fields... - field[si] = new_field(1, 40, starty++, 1, 0, 0); - labels.push_back(starty); - set_field_back(field[si], A_UNDERLINE); - set_field_type(field[si], TYPE_ALNUM, 40); - } - for (li = _sfields; li < _sfields + _lfields; ++li) - { - starty++; - field[li] = new_field(1, 64, starty++, 1, 3, 0); - labels.push_back(starty); - set_field_back(field[li], A_UNDERLINE); - } - for (bi = _sfields + _lfields; bi < maxfields; ++bi) - { - starty++; - field[bi] = new_field(5, 72, starty++, 1, 0, 0); - labels.push_back(starty); - field_opts_off(field[bi], O_STATIC); - set_field_back(field[bi], A_UNDERLINE); - starty += 4; - } - - // The FORM expects a NULL terminated list of fields - field[maxfields] = NULL; - - // Create the form and post it - FORM *form = new_form(field.data()); - - // Calculate the area required for the form - scale_form(form, &_rows, &_cols); - - // Create the window to be associated with the form - form_win = newwin(_rows + 4, _cols + 8, (height / 2 - _rows / 2 - 2), (width / 2 - _cols / 2 - 2)); - - // Set main window and sub window - set_form_win(form, form_win); - set_form_sub(form, derwin(form_win, _rows, _cols, 2, 2)); - - nodelay(form_win, true); - keypad(form_win, true); - noecho(); - timeout(0); - - box(form_win, 0, 0); - print_in_middle(form_win, 1, 0, _cols, _post_form, COLOR_PAIR(2)); - - post_form(form); - - // Set labels - int ca = 0; - int cf; - for (cf = 0; cf < _sfields; ++cf) - { - wattron(form_win, COLOR_PAIR(3)); - mvwprintw(form_win, labels[ca], 3, _sv[cf].c_str()); - wattroff(form_win, COLOR_PAIR(3)); - ca++; - } - for (cf = 0; cf < _lfields; ++cf) - { - wattron(form_win, COLOR_PAIR(3)); - mvwprintw(form_win, labels[ca], 3, _lv[cf].c_str()); - mvwprintw(form_win, labels[ca] + 1, _cols - 1, "wei"); - wattroff(form_win, COLOR_PAIR(3)); - ca++; - } - for (cf = 0; cf < _bfields; ++cf) - { - wattron(form_win, COLOR_PAIR(3)); - mvwprintw(form_win, labels[ca], 3, _bv[cf].c_str()); - wattroff(form_win, COLOR_PAIR(3)); - ca++; - } - - wrefresh(form_win); - - print_in_middle(form_win, 3, 0, _cols, string("Use the TAB key to switch between fields."), COLOR_PAIR(1)); - print_in_middle(form_win, 4, 0, _cols, string("Use UP, DOWN arrow keys to switch between lines."), COLOR_PAIR(1)); - print_in_middle(form_win, 6, 0, _cols, string("Press ENTER to submit the form and ESC to cancel."), COLOR_PAIR(1)); - refresh(); - - while ((ch = wgetch(form_win)) != 27 && ch != 13) // KEY_F(1)) - { - switch (ch) - { - case 9: // Tab - form_driver(form, REQ_NEXT_FIELD); - form_driver(form, REQ_END_LINE); - break; - case KEY_DOWN: - form_driver(form, REQ_NEXT_LINE); - break; - case KEY_UP: - form_driver(form, REQ_PREV_LINE); - break; - case KEY_LEFT: - form_driver(form, REQ_LEFT_CHAR); - break; - case KEY_RIGHT: - form_driver(form, REQ_RIGHT_CHAR); - break; - case KEY_BACKSPACE: // Backspace - case KEY_DC: - case KEY_DL: - case 127: - form_driver(form, REQ_DEL_PREV); - wrefresh(form_win); - break; - case KEY_ENTER: // Enter - case 13: - case 27: // Esc - break; - default: - form_driver(form, ch); - break; - } - } - - if (form_driver(form, REQ_VALIDATION) != E_OK) - cwarn << "Validation error"; - - int fi; - for (fi = 0; fi < maxfields; ++fi) - free_field(field[fi]); - free_form(form); - unpost_form(form); - echo(); - timeout(30000); - delwin(form_win); - - if (ch == 13) - for (int fi = 0; fi < maxfields; ++fi) - vs.push_back(field_buffer(field[fi], 0)); - - return vs; -}