main.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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. /** @file main.cpp
  15. * @author Gav Wood <i@gavwood.com>
  16. * @date 2014
  17. * EVM Execution tool.
  18. */
  19. #include <fstream>
  20. #include <iostream>
  21. #include <ctime>
  22. #include <boost/algorithm/string.hpp>
  23. #include <libdevcore/CommonIO.h>
  24. #include <libdevcore/RLP.h>
  25. #include <libdevcore/SHA3.h>
  26. #include <libethcore/SealEngine.h>
  27. #include <libethereum/Block.h>
  28. #include <libethereum/Executive.h>
  29. #include <libethereum/ChainParams.h>
  30. #include <libethashseal/GenesisInfo.h>
  31. #include <libethashseal/Ethash.h>
  32. #include <libevm/VM.h>
  33. #include <libevm/VMFactory.h>
  34. using namespace std;
  35. using namespace dev;
  36. using namespace eth;
  37. static const int64_t MaxBlockGasLimit = ChainParams(genesisInfo(Network::HomesteadTest)).u256Param("maxGasLimit").convert_to<int64_t>();
  38. void help()
  39. {
  40. cout
  41. << "Usage ethvm <options> [trace|stats|output|test] (<file>|-)" << endl
  42. << "Transaction options:" << endl
  43. << " --value <n> Transaction should transfer the <n> wei (default: 0)." << endl
  44. << " --gas <n> Transaction should be given <n> gas (default: block gas limit)." << endl
  45. << " --gas-limit <n> Block gas limit (default: " << MaxBlockGasLimit << ")." << endl
  46. << " --gas-price <n> Transaction's gas price' should be <n> (default: 0)." << endl
  47. << " --sender <a> Transaction sender should be <a> (default: 0000...0069)." << endl
  48. << " --origin <a> Transaction origin should be <a> (default: 0000...0069)." << endl
  49. << " --input <d> Transaction code should be <d>" << endl
  50. << " --code <d> Contract code <d>. Makes transaction a call to this contract" << endl
  51. #if ETH_EVMJIT
  52. << endl
  53. << "VM options:" << endl
  54. << " --vm <vm-kind> Select VM. Options are: interpreter, jit, smart. (default: interpreter)" << endl
  55. #endif // ETH_EVMJIT
  56. << "Network options:" << endl
  57. << " --network Olympic|Frontier|Morden|Homestead" << endl
  58. << endl
  59. << "Options for trace:" << endl
  60. << " --flat Minimal whitespace in the JSON." << endl
  61. << " --mnemonics Show instruction mnemonics in the trace (non-standard)." << endl
  62. << endl
  63. << "General options:" << endl
  64. << " -V,--version Show the version and exit." << endl
  65. << " -h,--help Show this help message and exit." << endl;
  66. exit(0);
  67. }
  68. void version()
  69. {
  70. cout << "ethvm version " << dev::Version << endl;
  71. cout << "By Gav Wood, 2015." << endl;
  72. cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl;
  73. exit(0);
  74. }
  75. /*
  76. The equivalent of setlocale(LC_ALL, “C”) is called before any user code is run.
  77. If the user has an invalid environment setting then it is possible for the call
  78. to set locale to fail, so there are only two possible actions, the first is to
  79. throw a runtime exception and cause the program to quit (default behaviour),
  80. or the second is to modify the environment to something sensible (least
  81. surprising behaviour).
  82. The follow code produces the least surprising behaviour. It will use the user
  83. specified default locale if it is valid, and if not then it will modify the
  84. environment the process is running in to use a sensible default. This also means
  85. that users do not need to install language packs for their OS.
  86. */
  87. void setDefaultOrCLocale()
  88. {
  89. #if __unix__
  90. if (!std::setlocale(LC_ALL, ""))
  91. {
  92. setenv("LC_ALL", "C", 1);
  93. }
  94. #endif
  95. }
  96. enum class Mode
  97. {
  98. Trace,
  99. Statistics,
  100. OutputOnly,
  101. /// Test mode -- output information needed for test verification and
  102. /// benchmarking. The execution is not introspected not to degrade
  103. /// performance.
  104. Test
  105. };
  106. int main(int argc, char** argv)
  107. {
  108. setDefaultOrCLocale();
  109. string inputFile;
  110. Mode mode = Mode::Statistics;
  111. VMKind vmKind = VMKind::Interpreter;
  112. State state(0);
  113. Address sender = Address(69);
  114. Address origin = Address(69);
  115. u256 value = 0;
  116. u256 gas = MaxBlockGasLimit;
  117. u256 gasPrice = 0;
  118. bool styledJson = true;
  119. StandardTrace st;
  120. EnvInfo envInfo;
  121. Network networkName = Network::HomesteadTest;
  122. envInfo.setGasLimit(MaxBlockGasLimit);
  123. bytes data;
  124. bytes code;
  125. Ethash::init();
  126. NoProof::init();
  127. for (int i = 1; i < argc; ++i)
  128. {
  129. string arg = argv[i];
  130. if (arg == "-h" || arg == "--help")
  131. help();
  132. else if (arg == "-V" || arg == "--version")
  133. version();
  134. else if (arg == "--vm" && i + 1 < argc)
  135. {
  136. string vmKindStr = argv[++i];
  137. if (vmKindStr == "interpreter")
  138. vmKind = VMKind::Interpreter;
  139. #if ETH_EVMJIT
  140. else if (vmKindStr == "jit")
  141. vmKind = VMKind::JIT;
  142. else if (vmKindStr == "smart")
  143. vmKind = VMKind::Smart;
  144. #endif
  145. else
  146. {
  147. cerr << "Unknown/unsupported VM kind: " << vmKindStr << endl;
  148. return -1;
  149. }
  150. }
  151. else if (arg == "--mnemonics")
  152. st.setShowMnemonics();
  153. else if (arg == "--flat")
  154. styledJson = false;
  155. else if (arg == "--sender" && i + 1 < argc)
  156. sender = Address(argv[++i]);
  157. else if (arg == "--origin" && i + 1 < argc)
  158. origin = Address(argv[++i]);
  159. else if (arg == "--gas" && i + 1 < argc)
  160. gas = u256(argv[++i]);
  161. else if (arg == "--gas-price" && i + 1 < argc)
  162. gasPrice = u256(argv[++i]);
  163. else if (arg == "--author" && i + 1 < argc)
  164. envInfo.setAuthor(Address(argv[++i]));
  165. else if (arg == "--number" && i + 1 < argc)
  166. envInfo.setNumber(u256(argv[++i]));
  167. else if (arg == "--difficulty" && i + 1 < argc)
  168. envInfo.setDifficulty(u256(argv[++i]));
  169. else if (arg == "--timestamp" && i + 1 < argc)
  170. envInfo.setTimestamp(u256(argv[++i]));
  171. else if (arg == "--gas-limit" && i + 1 < argc)
  172. envInfo.setGasLimit(u256(argv[++i]).convert_to<int64_t>());
  173. else if (arg == "--value" && i + 1 < argc)
  174. value = u256(argv[++i]);
  175. else if (arg == "--network" && i + 1 < argc)
  176. {
  177. string network = argv[++i];
  178. if (network == "Frontier")
  179. networkName = Network::FrontierTest;
  180. else if (network == "Ropsten")
  181. networkName = Network::Ropsten;
  182. else if (network == "Homestead")
  183. networkName = Network::HomesteadTest;
  184. else
  185. {
  186. cerr << "Unknown network type: " << network << endl;
  187. return -1;
  188. }
  189. }
  190. else if (arg == "stats")
  191. mode = Mode::Statistics;
  192. else if (arg == "output")
  193. mode = Mode::OutputOnly;
  194. else if (arg == "trace")
  195. mode = Mode::Trace;
  196. else if (arg == "test")
  197. mode = Mode::Test;
  198. else if (arg == "--input" && i + 1 < argc)
  199. data = fromHex(argv[++i]);
  200. else if (arg == "--code" && i + 1 < argc)
  201. code = fromHex(argv[++i]);
  202. else if (inputFile.empty())
  203. inputFile = arg; // Assign input file name only once.
  204. else
  205. {
  206. cerr << "Unknown argument: " << arg << '\n';
  207. return -1;
  208. }
  209. }
  210. VMFactory::setKind(vmKind);
  211. // Read code from input file.
  212. if (!inputFile.empty())
  213. {
  214. if (!code.empty())
  215. cerr << "--code argument overwritten by input file "
  216. << inputFile << '\n';
  217. if (inputFile == "-")
  218. for (int i = cin.get(); i != -1; i = cin.get())
  219. code.push_back((char)i);
  220. else
  221. code = contents(inputFile);
  222. try // Try decoding from hex.
  223. {
  224. std::string strCode{reinterpret_cast<char const*>(code.data()), code.size()};
  225. strCode.erase(strCode.find_last_not_of(" \t\n\r") + 1); // Right trim.
  226. code = fromHex(strCode, WhenError::Throw);
  227. }
  228. catch (BadHexCharacter const&) {} // Ignore decoding errors.
  229. }
  230. Transaction t;
  231. Address contractDestination("1122334455667788991011121314151617181920");
  232. if (!code.empty())
  233. {
  234. // Deploy the code on some fake account to be called later.
  235. Account account(0,0, Account::ContractConception);
  236. account.setCode(bytes{code});
  237. std::unordered_map<Address, Account> map;
  238. map[contractDestination] = account;
  239. state.populateFrom(map);
  240. t = Transaction(value, gasPrice, gas, contractDestination, data, 0);
  241. }
  242. else
  243. // If not code provided construct "create" transaction out of the input
  244. // data.
  245. t = Transaction(value, gasPrice, gas, data, 0);
  246. state.addBalance(sender, value);
  247. unique_ptr<SealEngineFace> se(ChainParams(genesisInfo(networkName)).createSealEngine());
  248. Executive executive(state, envInfo, *se);
  249. ExecutionResult res;
  250. executive.setResultRecipient(res);
  251. t.forceSender(sender);
  252. unordered_map<byte, pair<unsigned, bigint>> counts;
  253. unsigned total = 0;
  254. bigint memTotal;
  255. auto onOp = [&](uint64_t step, uint64_t PC, Instruction inst, bigint m, bigint gasCost, bigint gas, VM* vm, ExtVMFace const* extVM) {
  256. if (mode == Mode::Statistics)
  257. {
  258. counts[(byte)inst].first++;
  259. counts[(byte)inst].second += gasCost;
  260. total++;
  261. if (m > 0)
  262. memTotal = m;
  263. }
  264. else if (mode == Mode::Trace)
  265. st(step, PC, inst, m, gasCost, gas, vm, extVM);
  266. };
  267. executive.initialize(t);
  268. if (!code.empty())
  269. executive.call(contractDestination, sender, value, gasPrice, &data, gas);
  270. else
  271. executive.create(sender, value, gasPrice, gas, &data, origin);
  272. Timer timer;
  273. if ((mode == Mode::Statistics || mode == Mode::Trace) && vmKind == VMKind::Interpreter)
  274. // If we use onOp, the factory falls back to "interpreter"
  275. executive.go(onOp);
  276. else
  277. executive.go();
  278. double execTime = timer.elapsed();
  279. executive.finalize();
  280. bytes output = std::move(res.output);
  281. if (mode == Mode::Statistics)
  282. {
  283. cout << "Gas used: " << res.gasUsed << " (+" << t.gasRequired(se->evmSchedule(envInfo)) << " for transaction, -" << res.gasRefunded << " refunded)" << endl;
  284. cout << "Output: " << toHex(output) << endl;
  285. LogEntries logs = executive.logs();
  286. cout << logs.size() << " logs" << (logs.empty() ? "." : ":") << endl;
  287. for (LogEntry const& l: logs)
  288. {
  289. cout << " " << l.address.hex() << ": " << toHex(t.data()) << endl;
  290. for (h256 const& t: l.topics)
  291. cout << " " << t.hex() << endl;
  292. }
  293. cout << total << " operations in " << execTime << " seconds." << endl;
  294. cout << "Maximum memory usage: " << memTotal * 32 << " bytes" << endl;
  295. cout << "Expensive operations:" << endl;
  296. for (auto const& c: {Instruction::SSTORE, Instruction::SLOAD, Instruction::CALL, Instruction::CREATE, Instruction::CALLCODE, Instruction::DELEGATECALL, Instruction::MSTORE8, Instruction::MSTORE, Instruction::MLOAD, Instruction::SHA3})
  297. if (!!counts[(byte)c].first)
  298. cout << " " << instructionInfo(c).name << " x " << counts[(byte)c].first << " (" << counts[(byte)c].second << " gas)" << endl;
  299. }
  300. else if (mode == Mode::Trace)
  301. cout << st.json(styledJson);
  302. else if (mode == Mode::OutputOnly)
  303. cout << toHex(output) << '\n';
  304. else if (mode == Mode::Test)
  305. {
  306. // Output information needed for test verification and benchmarking
  307. // in YAML-like dictionaly format.
  308. auto exception = res.excepted != TransactionException::None;
  309. cout << "output: '" << toHex(output) << "'\n";
  310. cout << "gas used: " << res.gasUsed << '\n';
  311. cout << "exception: " << boolalpha << exception << '\n';
  312. cout << "exec time: " << fixed << setprecision(6) << execTime << '\n';
  313. }
  314. return 0;
  315. }