main.cpp 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /**
  15. * @file main.cpp
  16. * @author Gav Wood <i@gavwood.com>
  17. * @author Tasha Carl <tasha@carl.pro> - I here by place all my contributions in this file under MIT licence, as specified by http://opensource.org/licenses/MIT.
  18. * @date 2014
  19. * Ethereum client.
  20. */
  21. #include <thread>
  22. #include <chrono>
  23. #include <fstream>
  24. #include <iostream>
  25. #include <clocale>
  26. #include <signal.h>
  27. #include <boost/algorithm/string.hpp>
  28. #include <boost/algorithm/string/trim_all.hpp>
  29. #include <boost/filesystem.hpp>
  30. #include <libdevcore/FileSystem.h>
  31. #include <libethashseal/EthashAux.h>
  32. #include <libevm/VM.h>
  33. #include <libevm/VMFactory.h>
  34. #include <libethcore/KeyManager.h>
  35. #include <libethcore/ICAP.h>
  36. #include <libethereum/All.h>
  37. #include <libethereum/BlockChainSync.h>
  38. #include <libethashseal/EthashClient.h>
  39. #include <libethashseal/GenesisInfo.h>
  40. #include <libwebthree/WebThree.h>
  41. #if ETH_JSONRPC
  42. #include <libweb3jsonrpc/AccountHolder.h>
  43. #include <libweb3jsonrpc/Eth.h>
  44. #include <libweb3jsonrpc/SafeHttpServer.h>
  45. #include <jsonrpccpp/client/connectors/httpclient.h>
  46. #include <libweb3jsonrpc/ModularServer.h>
  47. #include <libweb3jsonrpc/IpcServer.h>
  48. #include <libweb3jsonrpc/LevelDB.h>
  49. #include <libweb3jsonrpc/Whisper.h>
  50. #include <libweb3jsonrpc/Net.h>
  51. #include <libweb3jsonrpc/Web3.h>
  52. #include <libweb3jsonrpc/SessionManager.h>
  53. #include <libweb3jsonrpc/AdminNet.h>
  54. #include <libweb3jsonrpc/AdminEth.h>
  55. #include <libweb3jsonrpc/AdminUtils.h>
  56. #include <libweb3jsonrpc/Personal.h>
  57. #include <libweb3jsonrpc/Debug.h>
  58. #include <libweb3jsonrpc/Test.h>
  59. #include "Farm.h"
  60. #endif // ETH_JSONRPC
  61. #include <ethminer/MinerAux.h>
  62. #include "AccountManager.h"
  63. using namespace std;
  64. using namespace dev;
  65. using namespace dev::p2p;
  66. using namespace dev::eth;
  67. using namespace boost::algorithm;
  68. static std::atomic<bool> g_silence = {false};
  69. void help()
  70. {
  71. cout
  72. << "Usage eth [OPTIONS]" << endl
  73. << "Options:" << endl << endl
  74. << "Wallet usage:" << endl;
  75. AccountManager::streamAccountHelp(cout);
  76. AccountManager::streamWalletHelp(cout);
  77. cout
  78. << endl;
  79. cout
  80. << "Client mode (default):" << endl
  81. << " --frontier Use the Frontier (1.0) protocol." << endl
  82. << " --ropsten Use the Ropsten testnet." << endl
  83. << " --private <name> Use a private chain." << endl
  84. << " --test Testing mode: Disable PoW and provide test rpc interface." << endl
  85. << " --config <file> Configure specialised blockchain using given JSON information." << endl
  86. << " --oppose-dao-fork Ignore DAO hard fork (default is to participate)." << endl
  87. << endl
  88. << " -o,--mode <full/peer> Start a full node or a peer node (default: full)." << endl
  89. << endl
  90. #if ETH_JSONRPC
  91. << " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl
  92. << " --ipc Enable IPC server (default: on)." << endl
  93. << " --ipcpath Set .ipc socket path (default: data directory)" << endl
  94. << " --admin-via-http Expose admin interface via http - UNSAFE! (default: off)." << endl
  95. << " --no-ipc Disable IPC server." << endl
  96. << " --json-rpc-port <n> Specify JSON-RPC server port (implies '-j', default: " << SensibleHttpPort << ")." << endl
  97. << " --rpccorsdomain <domain> Domain on which to send Access-Control-Allow-Origin header." << endl
  98. << " --admin <password> Specify admin session key for JSON-RPC (default: auto-generated and printed at start-up)." << endl
  99. #endif // ETH_JSONRPC
  100. << " -K,--kill Kill the blockchain first." << endl
  101. << " -R,--rebuild Rebuild the blockchain from the existing database." << endl
  102. << " --rescue Attempt to rescue a corrupt database." << endl
  103. << endl
  104. << " --import-presale <file> Import a pre-sale key; you'll need to specify the password to this key." << endl
  105. << " -s,--import-secret <secret> Import a secret key into the key store." << endl
  106. << " --master <password> Give the master password for the key store. Use --master \"\" to show a prompt." << endl
  107. << " --password <password> Give a password for a private key." << endl
  108. << endl
  109. << "Client transacting:" << endl
  110. /*<< " -B,--block-fees <n> Set the block fee profit in the reference unit, e.g. ¢ (default: 15)." << endl
  111. << " -e,--ether-price <n> Set the ether price in the reference unit, e.g. ¢ (default: 30.679)." << endl
  112. << " -P,--priority <0 - 100> Set the default priority percentage (%) of a transaction (default: 50)." << endl*/
  113. << " --ask <wei> Set the minimum ask gas price under which no transaction will be mined (default " << toString(DefaultGasPrice) << " )." << endl
  114. << " --bid <wei> Set the bid gas price to pay for transactions (default " << toString(DefaultGasPrice) << " )." << endl
  115. << " --unsafe-transactions Allow all transactions to proceed without verification. EXTREMELY UNSAFE."
  116. << endl
  117. << "Client mining:" << endl
  118. << " -a,--address <addr> Set the author (mining payout) address to given address (default: auto)." << endl
  119. << " -m,--mining <on/off/number> Enable mining, optionally for a specified number of blocks (default: off)." << endl
  120. << " -f,--force-mining Mine even when there are no transactions to mine (default: off)." << endl
  121. << " -C,--cpu When mining, use the CPU." << endl
  122. << " -G,--opencl When mining, use the GPU via OpenCL." << endl
  123. << " --opencl-platform <n> When mining using -G/--opencl, use OpenCL platform n (default: 0)." << endl
  124. << " --opencl-device <n> When mining using -G/--opencl, use OpenCL device n (default: 0)." << endl
  125. << " -t, --mining-threads <n> Limit number of CPU/GPU miners to n (default: use everything available on selected platform)." << endl
  126. << endl
  127. << "Client networking:" << endl
  128. << " --client-name <name> Add a name to your client's version string (default: blank)." << endl
  129. << " --bootstrap Connect to the default Ethereum peer servers (default unless --no-discovery used)." << endl
  130. << " --no-bootstrap Do not connect to the default Ethereum peer servers (default only when --no-discovery is used)." << endl
  131. << " -x,--peers <number> Attempt to connect to a given number of peers (default: 11)." << endl
  132. << " --peer-stretch <number> Give the accepted connection multiplier (default: 7)." << endl
  133. << " --public-ip <ip> Force advertised public IP to the given IP (default: auto)." << endl
  134. << " --listen-ip <ip>(:<port>) Listen on the given IP for incoming connections (default: 0.0.0.0)." << endl
  135. << " --listen <port> Listen on the given port for incoming connections (default: 30303)." << endl
  136. << " -r,--remote <host>(:<port>) Connect to the given remote host (default: none)." << endl
  137. << " --port <port> Connect to the given remote port (default: 30303)." << endl
  138. << " --network-id <n> Only connect to other hosts with this network id." << endl
  139. << " --upnp <on/off> Use UPnP for NAT (default: on)." << endl
  140. << " --peerset <list> Space delimited list of peers; element format: type:publickey@ipAddress[:port]." << endl
  141. << " Types:" << endl
  142. << " default Attempt connection when no other peers are available and pinning is disabled." << endl
  143. << " required Keep connected at all times." << endl
  144. // TODO:
  145. // << " --trust-peers <filename> Space delimited list of publickeys." << endl
  146. << " --no-discovery Disable node discovery, implies --no-bootstrap." << endl
  147. << " --pin Only accept or connect to trusted peers." << endl
  148. << " --hermit Equivalent to --no-discovery --pin." << endl
  149. << " --sociable Force discovery and no pinning." << endl
  150. << endl;
  151. MinerCLI::streamHelp(cout);
  152. cout
  153. << "Import/export modes:" << endl
  154. << " --from <n> Export only from block n; n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
  155. << " --to <n> Export only to block n (inclusive); n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
  156. << " --only <n> Equivalent to --export-from n --export-to n." << endl
  157. << " --dont-check Prevent checking some block aspects. Faster importing, but to apply only when the data is known to be valid." << endl
  158. << endl
  159. << "General Options:" << endl
  160. << " -d,--db-path,--datadir <path> Load database from path (default: " << getDataDir() << ")." << endl
  161. #if ETH_EVMJIT
  162. << " --vm <vm-kind> Select VM; options are: interpreter, jit or smart (default: interpreter)." << endl
  163. #endif // ETH_EVMJIT
  164. << " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl
  165. << " -V,--version Show the version and exit." << endl
  166. << " -h,--help Show this help message and exit." << endl
  167. << endl
  168. << "Experimental / Proof of Concept:" << endl
  169. << " --shh Enable Whisper." << endl
  170. << endl
  171. ;
  172. exit(0);
  173. }
  174. string ethCredits(bool _interactive = false)
  175. {
  176. std::ostringstream cout;
  177. if (_interactive)
  178. cout
  179. << "Type 'exit' to quit" << endl << endl;
  180. return credits() + cout.str();
  181. }
  182. void version()
  183. {
  184. cout << "eth version " << dev::Version << endl;
  185. cout << "eth network protocol version: " << dev::eth::c_protocolVersion << endl;
  186. cout << "Client database version: " << dev::eth::c_databaseVersion << endl;
  187. cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl;
  188. exit(0);
  189. }
  190. /*
  191. The equivalent of setlocale(LC_ALL, “C”) is called before any user code is run.
  192. If the user has an invalid environment setting then it is possible for the call
  193. to set locale to fail, so there are only two possible actions, the first is to
  194. throw a runtime exception and cause the program to quit (default behaviour),
  195. or the second is to modify the environment to something sensible (least
  196. surprising behaviour).
  197. The follow code produces the least surprising behaviour. It will use the user
  198. specified default locale if it is valid, and if not then it will modify the
  199. environment the process is running in to use a sensible default. This also means
  200. that users do not need to install language packs for their OS.
  201. */
  202. void setDefaultOrCLocale()
  203. {
  204. #if __unix__
  205. if (!std::setlocale(LC_ALL, ""))
  206. {
  207. setenv("LC_ALL", "C", 1);
  208. }
  209. #endif
  210. }
  211. void importPresale(KeyManager& _km, string const& _file, function<string()> _pass)
  212. {
  213. KeyPair k = _km.presaleSecret(contentsString(_file), [&](bool){ return _pass(); });
  214. _km.import(k.secret(), "Presale wallet" + _file + " (insecure)");
  215. }
  216. Address c_config = Address("ccdeac59d35627b7de09332e819d5159e7bb7250");
  217. string pretty(h160 _a, dev::eth::State const& _st)
  218. {
  219. string ns;
  220. h256 n;
  221. if (h160 nameReg = (u160)_st.storage(c_config, 0))
  222. n = _st.storage(nameReg, (u160)(_a));
  223. if (n)
  224. {
  225. std::string s((char const*)n.data(), 32);
  226. if (s.find_first_of('\0') != string::npos)
  227. s.resize(s.find_first_of('\0'));
  228. ns = " " + s;
  229. }
  230. return ns;
  231. }
  232. inline bool isPrime(unsigned _number)
  233. {
  234. if (((!(_number & 1)) && _number != 2 ) || (_number < 2) || (_number % 3 == 0 && _number != 3))
  235. return false;
  236. for(unsigned k = 1; 36 * k * k - 12 * k < _number; ++k)
  237. if ((_number % (6 * k + 1) == 0) || (_number % (6 * k - 1) == 0))
  238. return false;
  239. return true;
  240. }
  241. enum class NodeMode
  242. {
  243. PeerServer,
  244. Full
  245. };
  246. enum class OperationMode
  247. {
  248. Node,
  249. Import,
  250. Export
  251. };
  252. enum class Format
  253. {
  254. Binary,
  255. Hex,
  256. Human
  257. };
  258. void stopSealingAfterXBlocks(eth::Client* _c, unsigned _start, unsigned& io_mining)
  259. {
  260. try
  261. {
  262. if (io_mining != ~(unsigned)0 && io_mining && asEthashClient(_c)->isMining() && _c->blockChain().details().number - _start == io_mining)
  263. {
  264. _c->stopSealing();
  265. io_mining = ~(unsigned)0;
  266. }
  267. }
  268. catch (InvalidSealEngine&)
  269. {
  270. }
  271. this_thread::sleep_for(chrono::milliseconds(100));
  272. }
  273. class ExitHandler: public SystemManager
  274. {
  275. public:
  276. void exit() { exitHandler(0); }
  277. static void exitHandler(int) { s_shouldExit = true; }
  278. bool shouldExit() const { return s_shouldExit; }
  279. private:
  280. static bool s_shouldExit;
  281. };
  282. bool ExitHandler::s_shouldExit = false;
  283. int main(int argc, char** argv)
  284. {
  285. setDefaultOrCLocale();
  286. // Init defaults
  287. Defaults::get();
  288. Ethash::init();
  289. NoProof::init();
  290. #if ETH_DEBUG
  291. g_logVerbosity = 4;
  292. #else
  293. g_logVerbosity = 1;
  294. #endif
  295. /// Operating mode.
  296. OperationMode mode = OperationMode::Node;
  297. // unsigned prime = 0;
  298. // bool yesIReallyKnowWhatImDoing = false;
  299. strings scripts;
  300. /// File name for import/export.
  301. string filename;
  302. bool safeImport = false;
  303. /// Hashes/numbers for export range.
  304. string exportFrom = "1";
  305. string exportTo = "latest";
  306. Format exportFormat = Format::Binary;
  307. /// General params for Node operation
  308. NodeMode nodeMode = NodeMode::Full;
  309. bool interactive = false;
  310. #if ETH_JSONRPC
  311. int jsonRPCURL = -1;
  312. bool adminViaHttp = false;
  313. bool ipc = true;
  314. std::string rpcCorsDomain = "";
  315. #endif // ETH_JSONRPC
  316. string jsonAdmin;
  317. ChainParams chainParams(genesisInfo(eth::Network::Frontier), genesisStateRoot(eth::Network::Frontier));
  318. u256 gasFloor = Invalid256;
  319. string privateChain;
  320. bool upnp = true;
  321. WithExisting withExisting = WithExisting::Trust;
  322. /// Networking params.
  323. string clientName;
  324. string listenIP;
  325. unsigned short listenPort = 30303;
  326. string publicIP;
  327. string remoteHost;
  328. unsigned short remotePort = 30303;
  329. unsigned peers = 11;
  330. unsigned peerStretch = 7;
  331. std::map<NodeID, pair<NodeIPEndpoint,bool>> preferredNodes;
  332. bool bootstrap = true;
  333. bool disableDiscovery = false;
  334. bool pinning = false;
  335. bool enableDiscovery = false;
  336. bool noPinning = false;
  337. static const unsigned NoNetworkID = (unsigned)-1;
  338. unsigned networkID = NoNetworkID;
  339. /// Mining params
  340. unsigned mining = 0;
  341. Address author;
  342. strings presaleImports;
  343. bytes extraData;
  344. /// Transaction params
  345. // TransactionPriority priority = TransactionPriority::Medium;
  346. // double etherPrice = 30.679;
  347. // double blockFees = 15.0;
  348. u256 askPrice = DefaultGasPrice;
  349. u256 bidPrice = DefaultGasPrice;
  350. bool alwaysConfirm = true;
  351. /// Wallet password stuff
  352. string masterPassword;
  353. bool masterSet = false;
  354. /// Whisper
  355. bool useWhisper = false;
  356. bool testingMode = false;
  357. string configFile = getDataDir() + "/config.rlp";
  358. bytes b = contents(configFile);
  359. strings passwordsToNote;
  360. Secrets toImport;
  361. if (b.size())
  362. {
  363. try
  364. {
  365. RLP config(b);
  366. author = config[1].toHash<Address>();
  367. }
  368. catch (...) {}
  369. }
  370. if (argc > 1 && (string(argv[1]) == "wallet" || string(argv[1]) == "account"))
  371. {
  372. AccountManager accountm;
  373. return !accountm.execute(argc, argv);
  374. }
  375. MinerCLI m(MinerCLI::OperationMode::None);
  376. string configJSON;
  377. string genesisJSON;
  378. for (int i = 1; i < argc; ++i)
  379. {
  380. string arg = argv[i];
  381. if (m.interpretOption(i, argc, argv))
  382. {
  383. }
  384. else if (arg == "--listen-ip" && i + 1 < argc)
  385. listenIP = argv[++i];
  386. else if ((arg == "--listen" || arg == "--listen-port") && i + 1 < argc)
  387. {
  388. listenPort = (short)atoi(argv[++i]);
  389. }
  390. else if ((arg == "--public-ip" || arg == "--public") && i + 1 < argc)
  391. {
  392. publicIP = argv[++i];
  393. }
  394. else if ((arg == "-r" || arg == "--remote") && i + 1 < argc)
  395. {
  396. string host = argv[++i];
  397. string::size_type found = host.find_first_of(':');
  398. if (found != std::string::npos)
  399. {
  400. remoteHost = host.substr(0, found);
  401. remotePort = (short)atoi(host.substr(found + 1, host.length()).c_str());
  402. }
  403. else
  404. remoteHost = host;
  405. }
  406. else if (arg == "--port" && i + 1 < argc)
  407. {
  408. remotePort = (short)atoi(argv[++i]);
  409. }
  410. else if (arg == "--password" && i + 1 < argc)
  411. passwordsToNote.push_back(argv[++i]);
  412. else if (arg == "--master" && i + 1 < argc)
  413. {
  414. masterPassword = argv[++i];
  415. masterSet = true;
  416. }
  417. else if ((arg == "-I" || arg == "--import" || arg == "import") && i + 1 < argc)
  418. {
  419. mode = OperationMode::Import;
  420. filename = argv[++i];
  421. }
  422. else if (arg == "--dont-check")
  423. safeImport = true;
  424. else if ((arg == "-E" || arg == "--export" || arg == "export") && i + 1 < argc)
  425. {
  426. mode = OperationMode::Export;
  427. filename = argv[++i];
  428. }
  429. else if (arg == "--script" && i + 1 < argc)
  430. scripts.push_back(argv[++i]);
  431. else if (arg == "--format" && i + 1 < argc)
  432. {
  433. string m = argv[++i];
  434. if (m == "binary")
  435. exportFormat = Format::Binary;
  436. else if (m == "hex")
  437. exportFormat = Format::Hex;
  438. else if (m == "human")
  439. exportFormat = Format::Human;
  440. else
  441. {
  442. cerr << "Bad " << arg << " option: " << m << endl;
  443. return -1;
  444. }
  445. }
  446. else if (arg == "--to" && i + 1 < argc)
  447. exportTo = argv[++i];
  448. else if (arg == "--from" && i + 1 < argc)
  449. exportFrom = argv[++i];
  450. else if (arg == "--only" && i + 1 < argc)
  451. exportTo = exportFrom = argv[++i];
  452. else if (arg == "--upnp" && i + 1 < argc)
  453. {
  454. string m = argv[++i];
  455. if (isTrue(m))
  456. upnp = true;
  457. else if (isFalse(m))
  458. upnp = false;
  459. else
  460. {
  461. cerr << "Bad " << arg << " option: " << m << endl;
  462. return -1;
  463. }
  464. }
  465. else if (arg == "--network-id" && i + 1 < argc)
  466. try {
  467. networkID = stol(argv[++i]);
  468. }
  469. catch (...)
  470. {
  471. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  472. return -1;
  473. }
  474. else if (arg == "--private" && i + 1 < argc)
  475. try {
  476. privateChain = argv[++i];
  477. }
  478. catch (...)
  479. {
  480. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  481. return -1;
  482. }
  483. else if (arg == "--independent" && i + 1 < argc)
  484. try {
  485. privateChain = argv[++i];
  486. noPinning = enableDiscovery = true;
  487. }
  488. catch (...)
  489. {
  490. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  491. return -1;
  492. }
  493. else if (arg == "-K" || arg == "--kill-blockchain" || arg == "--kill")
  494. withExisting = WithExisting::Kill;
  495. else if (arg == "-R" || arg == "--rebuild")
  496. withExisting = WithExisting::Verify;
  497. else if (arg == "-R" || arg == "--rescue")
  498. withExisting = WithExisting::Rescue;
  499. else if (arg == "--client-name" && i + 1 < argc)
  500. clientName = argv[++i];
  501. else if ((arg == "-a" || arg == "--address" || arg == "--author") && i + 1 < argc)
  502. try {
  503. author = h160(fromHex(argv[++i], WhenError::Throw));
  504. }
  505. catch (BadHexCharacter&)
  506. {
  507. cerr << "Bad hex in " << arg << " option: " << argv[i] << endl;
  508. return -1;
  509. }
  510. catch (...)
  511. {
  512. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  513. return -1;
  514. }
  515. else if ((arg == "-s" || arg == "--import-secret") && i + 1 < argc)
  516. {
  517. Secret s(fromHex(argv[++i]));
  518. toImport.emplace_back(s);
  519. }
  520. else if ((arg == "-S" || arg == "--import-session-secret") && i + 1 < argc)
  521. {
  522. Secret s(fromHex(argv[++i]));
  523. toImport.emplace_back(s);
  524. }
  525. else if ((arg == "-d" || arg == "--path" || arg == "--db-path" || arg == "--datadir") && i + 1 < argc)
  526. setDataDir(argv[++i]);
  527. else if (arg == "--ipcpath" && i + 1 < argc )
  528. setIpcPath(argv[++i]);
  529. else if ((arg == "--genesis-json" || arg == "--genesis") && i + 1 < argc)
  530. {
  531. try
  532. {
  533. genesisJSON = contentsString(argv[++i]);
  534. }
  535. catch (...)
  536. {
  537. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  538. return -1;
  539. }
  540. }
  541. else if (arg == "--config" && i + 1 < argc)
  542. {
  543. try
  544. {
  545. configJSON = contentsString(argv[++i]);
  546. }
  547. catch (...)
  548. {
  549. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  550. return -1;
  551. }
  552. }
  553. else if (arg == "--extra-data" && i + 1 < argc)
  554. {
  555. try
  556. {
  557. extraData = fromHex(argv[++i]);
  558. }
  559. catch (...)
  560. {
  561. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  562. return -1;
  563. }
  564. }
  565. else if (arg == "--gas-floor" && i + 1 < argc)
  566. gasFloor = u256(argv[++i]);
  567. else if (arg == "--frontier")
  568. chainParams = ChainParams(genesisInfo(eth::Network::Frontier), genesisStateRoot(eth::Network::Frontier));
  569. else if (arg == "--ropsten" || arg == "--testnet")
  570. chainParams = ChainParams(genesisInfo(eth::Network::Ropsten), genesisStateRoot(eth::Network::Ropsten));
  571. else if (arg == "--oppose-dao-fork")
  572. {
  573. chainParams = ChainParams(genesisInfo(eth::Network::Frontier), genesisStateRoot(eth::Network::Frontier));
  574. chainParams.otherParams["daoHardforkBlock"] = toHex(u256(-1) - 10, HexPrefix::Add);
  575. }
  576. else if (arg == "--support-dao-fork")
  577. {
  578. // default
  579. }
  580. else if (arg == "--bob")
  581. {
  582. cout << "Asking Bob for blocks (this should work in theoreum)..." << endl;
  583. while (true)
  584. {
  585. u256 x(h256::random());
  586. u256 c;
  587. for (; x != 1; ++c)
  588. {
  589. x = (x & 1) == 0 ? x / 2 : 3 * x + 1;
  590. cout << toHex(x) << endl;
  591. this_thread::sleep_for(chrono::seconds(1));
  592. }
  593. cout << "Block number: " << hex << c << endl;
  594. exit(0);
  595. }
  596. }
  597. /* else if ((arg == "-B" || arg == "--block-fees") && i + 1 < argc)
  598. {
  599. try
  600. {
  601. blockFees = stof(argv[++i]);
  602. }
  603. catch (...)
  604. {
  605. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  606. return -1;
  607. }
  608. }
  609. else if ((arg == "-e" || arg == "--ether-price") && i + 1 < argc)
  610. {
  611. try
  612. {
  613. etherPrice = stof(argv[++i]);
  614. }
  615. catch (...)
  616. {
  617. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  618. return -1;
  619. }
  620. }*/
  621. else if (arg == "--ask" && i + 1 < argc)
  622. {
  623. try
  624. {
  625. askPrice = u256(argv[++i]);
  626. }
  627. catch (...)
  628. {
  629. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  630. return -1;
  631. }
  632. }
  633. else if (arg == "--bid" && i + 1 < argc)
  634. {
  635. try
  636. {
  637. bidPrice = u256(argv[++i]);
  638. }
  639. catch (...)
  640. {
  641. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  642. return -1;
  643. }
  644. }
  645. /* else if ((arg == "-P" || arg == "--priority") && i + 1 < argc)
  646. {
  647. string m = boost::to_lower_copy(string(argv[++i]));
  648. if (m == "lowest")
  649. priority = TransactionPriority::Lowest;
  650. else if (m == "low")
  651. priority = TransactionPriority::Low;
  652. else if (m == "medium" || m == "mid" || m == "default" || m == "normal")
  653. priority = TransactionPriority::Medium;
  654. else if (m == "high")
  655. priority = TransactionPriority::High;
  656. else if (m == "highest")
  657. priority = TransactionPriority::Highest;
  658. else
  659. try {
  660. priority = (TransactionPriority)(max(0, min(100, stoi(m))) * 8 / 100);
  661. }
  662. catch (...) {
  663. cerr << "Unknown " << arg << " option: " << m << endl;
  664. return -1;
  665. }
  666. }*/
  667. else if ((arg == "-m" || arg == "--mining") && i + 1 < argc)
  668. {
  669. string m = argv[++i];
  670. if (isTrue(m))
  671. mining = ~(unsigned)0;
  672. else if (isFalse(m))
  673. mining = 0;
  674. else
  675. try {
  676. mining = stoi(m);
  677. }
  678. catch (...) {
  679. cerr << "Unknown " << arg << " option: " << m << endl;
  680. return -1;
  681. }
  682. }
  683. else if (arg == "-b" || arg == "--bootstrap")
  684. bootstrap = true;
  685. else if (arg == "--no-bootstrap")
  686. bootstrap = false;
  687. else if (arg == "--no-discovery")
  688. {
  689. disableDiscovery = true;
  690. bootstrap = false;
  691. }
  692. else if (arg == "--pin")
  693. pinning = true;
  694. else if (arg == "--hermit")
  695. pinning = disableDiscovery = true;
  696. else if (arg == "--sociable")
  697. noPinning = enableDiscovery = true;
  698. else if (arg == "--unsafe-transactions")
  699. alwaysConfirm = false;
  700. else if (arg == "--import-presale" && i + 1 < argc)
  701. presaleImports.push_back(argv[++i]);
  702. else if (arg == "--old-interactive")
  703. interactive = true;
  704. #if ETH_JSONRPC
  705. else if ((arg == "-j" || arg == "--json-rpc"))
  706. jsonRPCURL = jsonRPCURL == -1 ? SensibleHttpPort : jsonRPCURL;
  707. else if (arg == "--admin-via-http")
  708. adminViaHttp = true;
  709. else if (arg == "--json-rpc-port" && i + 1 < argc)
  710. jsonRPCURL = atoi(argv[++i]);
  711. else if (arg == "--rpccorsdomain" && i + 1 < argc)
  712. rpcCorsDomain = argv[++i];
  713. else if (arg == "--json-admin" && i + 1 < argc)
  714. jsonAdmin = argv[++i];
  715. else if (arg == "--ipc")
  716. ipc = true;
  717. else if (arg == "--no-ipc")
  718. ipc = false;
  719. #endif // ETH_JSONRPC
  720. else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc)
  721. g_logVerbosity = atoi(argv[++i]);
  722. else if ((arg == "-x" || arg == "--peers") && i + 1 < argc)
  723. peers = atoi(argv[++i]);
  724. else if (arg == "--peer-stretch" && i + 1 < argc)
  725. peerStretch = atoi(argv[++i]);
  726. else if (arg == "--peerset" && i + 1 < argc)
  727. {
  728. string peerset = argv[++i];
  729. if (peerset.empty())
  730. {
  731. cerr << "--peerset argument must not be empty";
  732. return -1;
  733. }
  734. vector<string> each;
  735. boost::split(each, peerset, boost::is_any_of("\t "));
  736. for (auto const& p: each)
  737. {
  738. string type;
  739. string pubk;
  740. string hostIP;
  741. unsigned short port = c_defaultListenPort;
  742. // type:key@ip[:port]
  743. vector<string> typeAndKeyAtHostAndPort;
  744. boost::split(typeAndKeyAtHostAndPort, p, boost::is_any_of(":"));
  745. if (typeAndKeyAtHostAndPort.size() < 2 || typeAndKeyAtHostAndPort.size() > 3)
  746. continue;
  747. type = typeAndKeyAtHostAndPort[0];
  748. if (typeAndKeyAtHostAndPort.size() == 3)
  749. port = (uint16_t)atoi(typeAndKeyAtHostAndPort[2].c_str());
  750. vector<string> keyAndHost;
  751. boost::split(keyAndHost, typeAndKeyAtHostAndPort[1], boost::is_any_of("@"));
  752. if (keyAndHost.size() != 2)
  753. continue;
  754. pubk = keyAndHost[0];
  755. if (pubk.size() != 128)
  756. continue;
  757. hostIP = keyAndHost[1];
  758. // todo: use Network::resolveHost()
  759. if (hostIP.size() < 4 /* g.it */)
  760. continue;
  761. bool required = type == "required";
  762. if (!required && type != "default")
  763. continue;
  764. Public publicKey(fromHex(pubk));
  765. try
  766. {
  767. preferredNodes[publicKey] = make_pair(NodeIPEndpoint(bi::address::from_string(hostIP), port, port), required);
  768. }
  769. catch (...)
  770. {
  771. cerr << "Unrecognized peerset: " << peerset << endl;
  772. return -1;
  773. }
  774. }
  775. }
  776. else if ((arg == "-o" || arg == "--mode") && i + 1 < argc)
  777. {
  778. string m = argv[++i];
  779. if (m == "full")
  780. nodeMode = NodeMode::Full;
  781. else if (m == "peer")
  782. nodeMode = NodeMode::PeerServer;
  783. else
  784. {
  785. cerr << "Unknown mode: " << m << endl;
  786. return -1;
  787. }
  788. }
  789. #if ETH_EVMJIT
  790. else if (arg == "--vm" && i + 1 < argc)
  791. {
  792. string vmKind = argv[++i];
  793. if (vmKind == "interpreter")
  794. VMFactory::setKind(VMKind::Interpreter);
  795. else if (vmKind == "jit")
  796. VMFactory::setKind(VMKind::JIT);
  797. else if (vmKind == "smart")
  798. VMFactory::setKind(VMKind::Smart);
  799. else
  800. {
  801. cerr << "Unknown VM kind: " << vmKind << endl;
  802. return -1;
  803. }
  804. }
  805. #endif
  806. else if (arg == "--shh")
  807. useWhisper = true;
  808. else if (arg == "-h" || arg == "--help")
  809. help();
  810. else if (arg == "-V" || arg == "--version")
  811. version();
  812. else if (arg == "--test")
  813. {
  814. testingMode = true;
  815. enableDiscovery = false;
  816. disableDiscovery = true;
  817. bootstrap = false;
  818. }
  819. else
  820. {
  821. cerr << "Invalid argument: " << arg << endl;
  822. exit(-1);
  823. }
  824. }
  825. if (!configJSON.empty())
  826. {
  827. try
  828. {
  829. chainParams = chainParams.loadConfig(configJSON);
  830. }
  831. catch (...)
  832. {
  833. cerr << "provided configuration is not well formatted" << endl;
  834. cerr << "sample: " << endl << genesisInfo(eth::Network::Ropsten) << endl;
  835. return 0;
  836. }
  837. }
  838. if (!genesisJSON.empty())
  839. {
  840. try
  841. {
  842. chainParams = chainParams.loadGenesis(genesisJSON);
  843. }
  844. catch (...)
  845. {
  846. cerr << "provided genesis block description is not well formatted" << endl;
  847. string genesisSample =
  848. R"E(
  849. {
  850. "nonce": "0x0000000000000042",
  851. "difficulty": "0x400000000",
  852. "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  853. "author": "0x0000000000000000000000000000000000000000",
  854. "timestamp": "0x00",
  855. "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  856. "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
  857. "gasLimit": "0x1388"
  858. }
  859. )E";
  860. cerr << "sample: " << endl << genesisSample << endl;
  861. return 0;
  862. }
  863. }
  864. if (!privateChain.empty())
  865. {
  866. chainParams.extraData = sha3(privateChain).asBytes();
  867. chainParams.difficulty = chainParams.u256Param("minimumDifficulty");
  868. chainParams.gasLimit = u256(1) << 32;
  869. }
  870. // TODO: Open some other API path
  871. // if (gasFloor != Invalid256)
  872. // c_gasFloorTarget = gasFloor;
  873. if (g_logVerbosity > 0)
  874. cout << EthGrayBold "cpp-ethereum, a C++ Ethereum client" EthReset << endl;
  875. m.execute();
  876. std::string secretsPath;
  877. if (testingMode)
  878. secretsPath = (boost::filesystem::path(getDataDir()) / "keystore").string();
  879. else
  880. secretsPath = SecretStore::defaultPath();
  881. KeyManager keyManager(KeyManager::defaultPath(), secretsPath);
  882. for (auto const& s: passwordsToNote)
  883. keyManager.notePassword(s);
  884. // the first value is deprecated (never used)
  885. writeFile(configFile, rlpList(author, author));
  886. if (!clientName.empty())
  887. clientName += "/";
  888. string logbuf;
  889. std::string additional;
  890. if (interactive)
  891. g_logPost = [&](std::string const& a, char const*){
  892. static SpinLock s_lock;
  893. SpinGuard l(s_lock);
  894. if (g_silence)
  895. logbuf += a + "\n";
  896. else
  897. cout << "\r \r" << a << endl << additional << flush;
  898. // helpful to use OutputDebugString on windows
  899. #if defined(_WIN32)
  900. {
  901. OutputDebugStringA(a.data());
  902. OutputDebugStringA("\n");
  903. }
  904. #endif
  905. };
  906. auto getPassword = [&](string const& prompt) {
  907. bool s = g_silence;
  908. g_silence = true;
  909. cout << endl;
  910. string ret = dev::getPassword(prompt);
  911. g_silence = s;
  912. return ret;
  913. };
  914. auto getResponse = [&](string const& prompt, unordered_set<string> const& acceptable) {
  915. bool s = g_silence;
  916. g_silence = true;
  917. cout << endl;
  918. string ret;
  919. while (true)
  920. {
  921. cout << prompt;
  922. getline(cin, ret);
  923. if (acceptable.count(ret))
  924. break;
  925. cout << "Invalid response: " << ret << endl;
  926. }
  927. g_silence = s;
  928. return ret;
  929. };
  930. auto getAccountPassword = [&](Address const& a){
  931. return getPassword("Enter password for address " + keyManager.accountName(a) + " (" + a.abridged() + "; hint:" + keyManager.passwordHint(a) + "): ");
  932. };
  933. auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP, listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp);
  934. netPrefs.discovery = (privateChain.empty() && !disableDiscovery) || enableDiscovery;
  935. netPrefs.pin = (pinning || !privateChain.empty()) && !noPinning;
  936. auto nodesState = contents(getDataDir() + "/network.rlp");
  937. auto caps = useWhisper ? set<string>{"eth", "shh"} : set<string>{"eth"};
  938. if (testingMode)
  939. {
  940. chainParams.sealEngineName = "NoProof";
  941. chainParams.otherParams["allowFutureBlocks"] = "1";
  942. }
  943. dev::WebThreeDirect web3(
  944. WebThreeDirect::composeClientVersion("eth"),
  945. getDataDir(),
  946. chainParams,
  947. withExisting,
  948. nodeMode == NodeMode::Full ? caps : set<string>(),
  949. netPrefs,
  950. &nodesState,
  951. testingMode
  952. );
  953. if (!extraData.empty())
  954. web3.ethereum()->setExtraData(extraData);
  955. auto toNumber = [&](string const& s) -> unsigned {
  956. if (s == "latest")
  957. return web3.ethereum()->number();
  958. if (s.size() == 64 || (s.size() == 66 && s.substr(0, 2) == "0x"))
  959. return web3.ethereum()->blockChain().number(h256(s));
  960. try {
  961. return stol(s);
  962. }
  963. catch (...)
  964. {
  965. cerr << "Bad block number/hash option: " << s << endl;
  966. exit(-1);
  967. }
  968. };
  969. if (mode == OperationMode::Export)
  970. {
  971. ofstream fout(filename, std::ofstream::binary);
  972. ostream& out = (filename.empty() || filename == "--") ? cout : fout;
  973. unsigned last = toNumber(exportTo);
  974. for (unsigned i = toNumber(exportFrom); i <= last; ++i)
  975. {
  976. bytes block = web3.ethereum()->blockChain().block(web3.ethereum()->blockChain().numberHash(i));
  977. switch (exportFormat)
  978. {
  979. case Format::Binary: out.write((char const*)block.data(), block.size()); break;
  980. case Format::Hex: out << toHex(block) << endl; break;
  981. case Format::Human: out << RLP(block) << endl; break;
  982. default:;
  983. }
  984. }
  985. return 0;
  986. }
  987. if (mode == OperationMode::Import)
  988. {
  989. ifstream fin(filename, std::ifstream::binary);
  990. istream& in = (filename.empty() || filename == "--") ? cin : fin;
  991. unsigned alreadyHave = 0;
  992. unsigned good = 0;
  993. unsigned futureTime = 0;
  994. unsigned unknownParent = 0;
  995. unsigned bad = 0;
  996. chrono::steady_clock::time_point t = chrono::steady_clock::now();
  997. double last = 0;
  998. unsigned lastImported = 0;
  999. unsigned imported = 0;
  1000. while (in.peek() != -1)
  1001. {
  1002. bytes block(8);
  1003. in.read((char*)block.data(), 8);
  1004. block.resize(RLP(block, RLP::LaissezFaire).actualSize());
  1005. in.read((char*)block.data() + 8, block.size() - 8);
  1006. switch (web3.ethereum()->queueBlock(block, safeImport))
  1007. {
  1008. case ImportResult::Success: good++; break;
  1009. case ImportResult::AlreadyKnown: alreadyHave++; break;
  1010. case ImportResult::UnknownParent: unknownParent++; break;
  1011. case ImportResult::FutureTimeUnknown: unknownParent++; futureTime++; break;
  1012. case ImportResult::FutureTimeKnown: futureTime++; break;
  1013. default: bad++; break;
  1014. }
  1015. // sync chain with queue
  1016. tuple<ImportRoute, bool, unsigned> r = web3.ethereum()->syncQueue(10);
  1017. imported += get<2>(r);
  1018. double e = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - t).count() / 1000.0;
  1019. if ((unsigned)e >= last + 10)
  1020. {
  1021. auto i = imported - lastImported;
  1022. auto d = e - last;
  1023. cout << i << " more imported at " << (round(i * 10 / d) / 10) << " blocks/s. " << imported << " imported in " << e << " seconds at " << (round(imported * 10 / e) / 10) << " blocks/s (#" << web3.ethereum()->number() << ")" << endl;
  1024. last = (unsigned)e;
  1025. lastImported = imported;
  1026. // cout << web3.ethereum()->blockQueueStatus() << endl;
  1027. }
  1028. }
  1029. while (web3.ethereum()->blockQueue().items().first + web3.ethereum()->blockQueue().items().second > 0)
  1030. {
  1031. this_thread::sleep_for(chrono::seconds(1));
  1032. web3.ethereum()->syncQueue(100000);
  1033. }
  1034. double e = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - t).count() / 1000.0;
  1035. cout << imported << " imported in " << e << " seconds at " << (round(imported * 10 / e) / 10) << " blocks/s (#" << web3.ethereum()->number() << ")" << endl;
  1036. return 0;
  1037. }
  1038. try
  1039. {
  1040. if (keyManager.exists())
  1041. {
  1042. if (!keyManager.load(masterPassword) && masterSet)
  1043. {
  1044. while (true)
  1045. {
  1046. masterPassword = getPassword("Please enter your MASTER password: ");
  1047. if (keyManager.load(masterPassword))
  1048. break;
  1049. cout << "The password you entered is incorrect. If you have forgotten your password, and you wish to start afresh, manually remove the file: " + getDataDir("ethereum") + "/keys.info" << endl;
  1050. }
  1051. }
  1052. }
  1053. else
  1054. {
  1055. if (masterSet)
  1056. keyManager.create(masterPassword);
  1057. else
  1058. keyManager.create(std::string());
  1059. }
  1060. }
  1061. catch(...)
  1062. {
  1063. cerr << "Error initializing key manager: " << boost::current_exception_diagnostic_information() << endl;
  1064. return -1;
  1065. }
  1066. for (auto const& presale: presaleImports)
  1067. importPresale(keyManager, presale, [&](){ return getPassword("Enter your wallet password for " + presale + ": "); });
  1068. for (auto const& s: toImport)
  1069. {
  1070. keyManager.import(s, "Imported key (UNSAFE)");
  1071. }
  1072. cout << ethCredits();
  1073. web3.setIdealPeerCount(peers);
  1074. web3.setPeerStretch(peerStretch);
  1075. // std::shared_ptr<eth::BasicGasPricer> gasPricer = make_shared<eth::BasicGasPricer>(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000));
  1076. std::shared_ptr<eth::TrivialGasPricer> gasPricer = make_shared<eth::TrivialGasPricer>(askPrice, bidPrice);
  1077. eth::Client* c = nodeMode == NodeMode::Full ? web3.ethereum() : nullptr;
  1078. if (c)
  1079. {
  1080. c->setGasPricer(gasPricer);
  1081. DEV_IGNORE_EXCEPTIONS(asEthashClient(c)->setShouldPrecomputeDAG(m.shouldPrecompute()));
  1082. c->setSealer(m.minerType());
  1083. c->setAuthor(author);
  1084. if (networkID != NoNetworkID)
  1085. c->setNetworkId(networkID);
  1086. }
  1087. auto renderFullAddress = [&](Address const& _a) -> std::string
  1088. {
  1089. return ICAP(_a).encoded() + " (" + toUUID(keyManager.uuid(_a)) + " - " + toHex(_a.ref().cropped(0, 4)) + ")";
  1090. };
  1091. if (author)
  1092. cout << "Mining Beneficiary: " << renderFullAddress(author) << endl;
  1093. if (bootstrap || !remoteHost.empty() || enableDiscovery)
  1094. {
  1095. web3.startNetwork();
  1096. cout << "Node ID: " << web3.enode() << endl;
  1097. }
  1098. else
  1099. cout << "Networking disabled. To start, use netstart or pass --bootstrap or a remote host." << endl;
  1100. #if ETH_JSONRPC
  1101. unique_ptr<ModularServer<>> jsonrpcHttpServer;
  1102. unique_ptr<ModularServer<>> jsonrpcIpcServer;
  1103. unique_ptr<rpc::SessionManager> sessionManager;
  1104. unique_ptr<SimpleAccountHolder> accountHolder;
  1105. AddressHash allowedDestinations;
  1106. std::function<bool(TransactionSkeleton const&, bool)> authenticator;
  1107. if (testingMode)
  1108. authenticator = [](TransactionSkeleton const&, bool) -> bool { return true; };
  1109. else
  1110. authenticator = [&](TransactionSkeleton const& _t, bool isProxy) -> bool {
  1111. // "unlockAccount" functionality is done in the AccountHolder.
  1112. if (!alwaysConfirm || allowedDestinations.count(_t.to))
  1113. return true;
  1114. string r = getResponse(_t.userReadable(isProxy,
  1115. [&](TransactionSkeleton const& _t) -> pair<bool, string>
  1116. {
  1117. h256 contractCodeHash = web3.ethereum()->postState().codeHash(_t.to);
  1118. if (contractCodeHash == EmptySHA3)
  1119. return std::make_pair(false, std::string());
  1120. // TODO: actually figure out the natspec. we'll need the natspec database here though.
  1121. return std::make_pair(true, std::string());
  1122. }, [&](Address const& _a) { return ICAP(_a).encoded() + " (" + _a.abridged() + ")"; }
  1123. ) + "\nEnter yes/no/always (always to this address): ", {"yes", "n", "N", "no", "NO", "always"});
  1124. if (r == "always")
  1125. allowedDestinations.insert(_t.to);
  1126. return r == "yes" || r == "always";
  1127. };
  1128. ExitHandler exitHandler;
  1129. if (jsonRPCURL > -1 || ipc)
  1130. {
  1131. using FullServer = ModularServer<
  1132. rpc::EthFace, rpc::DBFace, rpc::WhisperFace,
  1133. rpc::NetFace, rpc::Web3Face, rpc::PersonalFace,
  1134. rpc::AdminEthFace, rpc::AdminNetFace, rpc::AdminUtilsFace,
  1135. rpc::DebugFace, rpc::TestFace
  1136. >;
  1137. sessionManager.reset(new rpc::SessionManager());
  1138. accountHolder.reset(new SimpleAccountHolder([&](){ return web3.ethereum(); }, getAccountPassword, keyManager, authenticator));
  1139. auto ethFace = new rpc::Eth(*web3.ethereum(), *accountHolder.get());
  1140. rpc::TestFace* testEth = nullptr;
  1141. if (testingMode)
  1142. testEth = new rpc::Test(*web3.ethereum());
  1143. if (jsonRPCURL >= 0)
  1144. {
  1145. rpc::AdminEth* adminEth = nullptr;
  1146. rpc::PersonalFace* personal = nullptr;
  1147. rpc::AdminNet* adminNet = nullptr;
  1148. rpc::AdminUtils* adminUtils = nullptr;
  1149. if (adminViaHttp)
  1150. {
  1151. personal = new rpc::Personal(keyManager, *accountHolder, *web3.ethereum());
  1152. adminEth = new rpc::AdminEth(*web3.ethereum(), *gasPricer.get(), keyManager, *sessionManager.get());
  1153. adminNet = new rpc::AdminNet(web3, *sessionManager.get());
  1154. adminUtils = new rpc::AdminUtils(*sessionManager.get());
  1155. }
  1156. jsonrpcHttpServer.reset(new FullServer(
  1157. ethFace, new rpc::LevelDB(), new rpc::Whisper(web3, {}),
  1158. new rpc::Net(web3), new rpc::Web3(web3.clientVersion()), personal,
  1159. adminEth, adminNet, adminUtils,
  1160. new rpc::Debug(*web3.ethereum()),
  1161. testEth
  1162. ));
  1163. auto httpConnector = new SafeHttpServer(jsonRPCURL, "", "", SensibleHttpThreads);
  1164. httpConnector->setAllowedOrigin(rpcCorsDomain);
  1165. jsonrpcHttpServer->addConnector(httpConnector);
  1166. jsonrpcHttpServer->StartListening();
  1167. }
  1168. if (ipc)
  1169. {
  1170. jsonrpcIpcServer.reset(new FullServer(
  1171. ethFace, new rpc::LevelDB(), new rpc::Whisper(web3, {}), new rpc::Net(web3),
  1172. new rpc::Web3(web3.clientVersion()), new rpc::Personal(keyManager, *accountHolder, *web3.ethereum()),
  1173. new rpc::AdminEth(*web3.ethereum(), *gasPricer.get(), keyManager, *sessionManager.get()),
  1174. new rpc::AdminNet(web3, *sessionManager.get()),
  1175. new rpc::AdminUtils(*sessionManager.get()),
  1176. new rpc::Debug(*web3.ethereum()),
  1177. testEth
  1178. ));
  1179. auto ipcConnector = new IpcServer("geth");
  1180. jsonrpcIpcServer->addConnector(ipcConnector);
  1181. ipcConnector->StartListening();
  1182. }
  1183. if (jsonAdmin.empty())
  1184. jsonAdmin = sessionManager->newSession(rpc::SessionPermissions{{rpc::Privilege::Admin}});
  1185. else
  1186. sessionManager->addSession(jsonAdmin, rpc::SessionPermissions{{rpc::Privilege::Admin}});
  1187. cout << "JSONRPC Admin Session Key: " << jsonAdmin << endl;
  1188. writeFile(getDataDir("web3") + "/session.key", jsonAdmin);
  1189. writeFile(getDataDir("web3") + "/session.url", "http://localhost:" + toString(jsonRPCURL));
  1190. }
  1191. #endif // ETH_JSONRPC
  1192. for (auto const& p: preferredNodes)
  1193. if (p.second.second)
  1194. web3.requirePeer(p.first, p.second.first);
  1195. else
  1196. web3.addNode(p.first, p.second.first);
  1197. if (bootstrap && privateChain.empty())
  1198. for (auto const& i: Host::pocHosts())
  1199. web3.requirePeer(i.first, i.second);
  1200. if (!remoteHost.empty())
  1201. web3.addNode(p2p::NodeID(), remoteHost + ":" + toString(remotePort));
  1202. signal(SIGABRT, &ExitHandler::exitHandler);
  1203. signal(SIGTERM, &ExitHandler::exitHandler);
  1204. signal(SIGINT, &ExitHandler::exitHandler);
  1205. if (c)
  1206. {
  1207. unsigned n = c->blockChain().details().number;
  1208. if (mining)
  1209. c->startSealing();
  1210. while (!exitHandler.shouldExit())
  1211. stopSealingAfterXBlocks(c, n, mining);
  1212. }
  1213. else
  1214. while (!exitHandler.shouldExit())
  1215. this_thread::sleep_for(chrono::milliseconds(1000));
  1216. #if ETH_JSONRPC
  1217. if (jsonrpcHttpServer.get())
  1218. jsonrpcHttpServer->StopListening();
  1219. if (jsonrpcIpcServer.get())
  1220. jsonrpcIpcServer->StopListening();
  1221. #endif
  1222. auto netData = web3.saveNetwork();
  1223. if (!netData.empty())
  1224. writeFile(getDataDir() + "/network.rlp", netData);
  1225. return 0;
  1226. }