Fabcoin Core  0.16.2
P2P Digital Currency
main.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
22 #include <fstream>
23 #include <iostream>
24 #include <ctime>
25 #include <boost/algorithm/string.hpp>
26 #include <libdevcore/CommonIO.h>
27 #include <libdevcore/RLP.h>
28 #include <libdevcore/SHA3.h>
29 #include <libethcore/SealEngine.h>
30 #include <libethereum/Block.h>
31 #include <libethereum/Executive.h>
34 #include <libethashseal/Ethash.h>
35 #include <libevm/VM.h>
36 #include <libevm/VMFactory.h>
37 using namespace std;
38 using namespace dev;
39 using namespace eth;
40 
41 static const int64_t MaxBlockGasLimit = ChainParams(genesisInfo(Network::MainNetwork)).u256Param("maxGasLimit").convert_to<int64_t>();
42 
43 void help()
44 {
45  cout
46  << "Usage ethvm <options> [trace|stats|output|test] (<file>|-)" << endl
47  << "Transaction options:" << endl
48  << " --value <n> Transaction should transfer the <n> wei (default: 0)." << endl
49  << " --gas <n> Transaction should be given <n> gas (default: block gas limit)." << endl
50  << " --gas-limit <n> Block gas limit (default: " << MaxBlockGasLimit << ")." << endl
51  << " --gas-price <n> Transaction's gas price' should be <n> (default: 0)." << endl
52  << " --sender <a> Transaction sender should be <a> (default: 0000...0069)." << endl
53  << " --origin <a> Transaction origin should be <a> (default: 0000...0069)." << endl
54  << " --input <d> Transaction code should be <d>" << endl
55  << " --code <d> Contract code <d>. Makes transaction a call to this contract" << endl
56 #if ETH_EVMJIT
57  << endl
58  << "VM options:" << endl
59  << " --vm <vm-kind> Select VM. Options are: interpreter, jit, smart. (default: interpreter)" << endl
60 #endif // ETH_EVMJIT
61  << "Network options:" << endl
62  << " --network Main|Ropsten|Homestead|Frontier" << endl
63  << endl
64  << "Options for trace:" << endl
65  << " --flat Minimal whitespace in the JSON." << endl
66  << " --mnemonics Show instruction mnemonics in the trace (non-standard)." << endl
67  << endl
68  << "General options:" << endl
69  << " -V,--version Show the version and exit." << endl
70  << " -h,--help Show this help message and exit." << endl;
71  exit(0);
72 }
73 
74 void version()
75 {
76  cout << "ethvm version " << dev::Version << endl;
77  cout << "By Gav Wood, 2015." << endl;
78  cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl;
79  exit(0);
80 }
81 
82 /*
83 The equivalent of setlocale(LC_ALL, ā€œCā€) is called before any user code is run.
84 If the user has an invalid environment setting then it is possible for the call
85 to set locale to fail, so there are only two possible actions, the first is to
86 throw a runtime exception and cause the program to quit (default behaviour),
87 or the second is to modify the environment to something sensible (least
88 surprising behaviour).
89 
90 The follow code produces the least surprising behaviour. It will use the user
91 specified default locale if it is valid, and if not then it will modify the
92 environment the process is running in to use a sensible default. This also means
93 that users do not need to install language packs for their OS.
94 */
96 {
97 #if __unix__
98  if (!std::setlocale(LC_ALL, ""))
99  {
100  setenv("LC_ALL", "C", 1);
101  }
102 #endif
103 }
104 
105 enum class Mode
106 {
107  Trace,
108  Statistics,
109  OutputOnly,
110 
114  Test
115 };
116 
117 int main(int argc, char** argv)
118 {
120  string inputFile;
122  VMKind vmKind = VMKind::Interpreter;
123  State state(0);
124  Address sender = Address(69);
125  Address origin = Address(69);
126  u256 value = 0;
127  u256 gas = MaxBlockGasLimit;
128  u256 gasPrice = 0;
129  bool styledJson = true;
130  StandardTrace st;
131  EnvInfo envInfo;
132  Network networkName = Network::MainNetwork;
133  envInfo.setGasLimit(MaxBlockGasLimit);
134  bytes data;
135  bytes code;
136 
137  Ethash::init();
138  NoProof::init();
139 
140  for (int i = 1; i < argc; ++i)
141  {
142  string arg = argv[i];
143  if (arg == "-h" || arg == "--help")
144  help();
145  else if (arg == "-V" || arg == "--version")
146  version();
147  else if (arg == "--vm" && i + 1 < argc)
148  {
149  string vmKindStr = argv[++i];
150  if (vmKindStr == "interpreter")
151  vmKind = VMKind::Interpreter;
152 #if ETH_EVMJIT
153  else if (vmKindStr == "jit")
154  vmKind = VMKind::JIT;
155  else if (vmKindStr == "smart")
156  vmKind = VMKind::Smart;
157 #endif
158  else
159  {
160  cerr << "Unknown/unsupported VM kind: " << vmKindStr << endl;
161  return -1;
162  }
163  }
164  else if (arg == "--mnemonics")
165  st.setShowMnemonics();
166  else if (arg == "--flat")
167  styledJson = false;
168  else if (arg == "--sender" && i + 1 < argc)
169  sender = Address(argv[++i]);
170  else if (arg == "--origin" && i + 1 < argc)
171  origin = Address(argv[++i]);
172  else if (arg == "--gas" && i + 1 < argc)
173  gas = u256(argv[++i]);
174  else if (arg == "--gas-price" && i + 1 < argc)
175  gasPrice = u256(argv[++i]);
176  else if (arg == "--author" && i + 1 < argc)
177  envInfo.setAuthor(Address(argv[++i]));
178  else if (arg == "--number" && i + 1 < argc)
179  envInfo.setNumber(u256(argv[++i]));
180  else if (arg == "--difficulty" && i + 1 < argc)
181  envInfo.setDifficulty(u256(argv[++i]));
182  else if (arg == "--timestamp" && i + 1 < argc)
183  envInfo.setTimestamp(u256(argv[++i]));
184  else if (arg == "--gas-limit" && i + 1 < argc)
185  envInfo.setGasLimit(u256(argv[++i]).convert_to<int64_t>());
186  else if (arg == "--value" && i + 1 < argc)
187  value = u256(argv[++i]);
188  else if (arg == "--network" && i + 1 < argc)
189  {
190  string network = argv[++i];
191  if (network == "Frontier")
192  networkName = Network::FrontierTest;
193  else if (network == "Ropsten")
194  networkName = Network::Ropsten;
195  else if (network == "Homestead")
196  networkName = Network::HomesteadTest;
197  else if (network == "Main")
198  networkName = Network::MainNetwork;
199  else
200  {
201  cerr << "Unknown network type: " << network << endl;
202  return -1;
203  }
204  }
205  else if (arg == "stats")
206  mode = Mode::Statistics;
207  else if (arg == "output")
208  mode = Mode::OutputOnly;
209  else if (arg == "trace")
210  mode = Mode::Trace;
211  else if (arg == "test")
212  mode = Mode::Test;
213  else if (arg == "--input" && i + 1 < argc)
214  data = fromHex(argv[++i]);
215  else if (arg == "--code" && i + 1 < argc)
216  code = fromHex(argv[++i]);
217  else if (inputFile.empty())
218  inputFile = arg; // Assign input file name only once.
219  else
220  {
221  cerr << "Unknown argument: " << arg << '\n';
222  return -1;
223  }
224  }
225 
226  VMFactory::setKind(vmKind);
227 
228 
229  // Read code from input file.
230  if (!inputFile.empty())
231  {
232  if (!code.empty())
233  cerr << "--code argument overwritten by input file "
234  << inputFile << '\n';
235 
236  if (inputFile == "-")
237  for (int i = cin.get(); i != -1; i = cin.get())
238  code.push_back((char)i);
239  else
240  code = contents(inputFile);
241 
242  try // Try decoding from hex.
243  {
244  std::string strCode{reinterpret_cast<char const*>(code.data()), code.size()};
245  strCode.erase(strCode.find_last_not_of(" \t\n\r") + 1); // Right trim.
246  code = fromHex(strCode, WhenError::Throw);
247  }
248  catch (BadHexCharacter const&) {} // Ignore decoding errors.
249  }
250 
251  Transaction t;
252  Address contractDestination("1122334455667788991011121314151617181920");
253  if (!code.empty())
254  {
255  // Deploy the code on some fake account to be called later.
256  Account account(0, 0);
257  account.setNewCode(bytes{code});
258  std::unordered_map<Address, Account> map;
259  map[contractDestination] = account;
260  state.populateFrom(map);
261  t = Transaction(value, gasPrice, gas, contractDestination, data, 0);
262  }
263  else
264  // If not code provided construct "create" transaction out of the input
265  // data.
266  t = Transaction(value, gasPrice, gas, data, 0);
267 
268  state.addBalance(sender, value);
269 
270  unique_ptr<SealEngineFace> se(ChainParams(genesisInfo(networkName)).createSealEngine());
271  Executive executive(state, envInfo, *se);
272  ExecutionResult res;
273  executive.setResultRecipient(res);
274  t.forceSender(sender);
275 
276  unordered_map<byte, pair<unsigned, bigint>> counts;
277  unsigned total = 0;
278  bigint memTotal;
279  auto onOp = [&](uint64_t step, uint64_t PC, Instruction inst, bigint m, bigint gasCost, bigint gas, VM* vm, ExtVMFace const* extVM) {
280  if (mode == Mode::Statistics)
281  {
282  counts[(byte)inst].first++;
283  counts[(byte)inst].second += gasCost;
284  total++;
285  if (m > 0)
286  memTotal = m;
287  }
288  else if (mode == Mode::Trace)
289  st(step, PC, inst, m, gasCost, gas, vm, extVM);
290  };
291 
292  executive.initialize(t);
293  if (!code.empty())
294  executive.call(contractDestination, sender, value, gasPrice, &data, gas);
295  else
296  executive.create(sender, value, gasPrice, gas, &data, origin);
297 
298  Timer timer;
299  if ((mode == Mode::Statistics || mode == Mode::Trace) && vmKind == VMKind::Interpreter)
300  // If we use onOp, the factory falls back to "interpreter"
301  executive.go(onOp);
302  else
303  executive.go();
304  double execTime = timer.elapsed();
305  executive.finalize();
306  bytes output = std::move(res.output);
307 
308  if (mode == Mode::Statistics)
309  {
310  cout << "Gas used: " << res.gasUsed << " (+" << t.baseGasRequired(se->evmSchedule(envInfo)) << " for transaction, -" << res.gasRefunded << " refunded)" << endl;
311  cout << "Output: " << toHex(output) << endl;
312  LogEntries logs = executive.logs();
313  cout << logs.size() << " logs" << (logs.empty() ? "." : ":") << endl;
314  for (LogEntry const& l: logs)
315  {
316  cout << " " << l.address.hex() << ": " << toHex(t.data()) << endl;
317  for (h256 const& t: l.topics)
318  cout << " " << t.hex() << endl;
319  }
320 
321  cout << total << " operations in " << execTime << " seconds." << endl;
322  cout << "Maximum memory usage: " << memTotal * 32 << " bytes" << endl;
323  cout << "Expensive operations:" << endl;
324  for (auto const& c: {Instruction::SSTORE, Instruction::SLOAD, Instruction::CALL, Instruction::CREATE, Instruction::CALLCODE, Instruction::DELEGATECALL, Instruction::MSTORE8, Instruction::MSTORE, Instruction::MLOAD, Instruction::SHA3})
325  if (!!counts[(byte)c].first)
326  cout << " " << instructionInfo(c).name << " x " << counts[(byte)c].first << " (" << counts[(byte)c].second << " gas)" << endl;
327  }
328  else if (mode == Mode::Trace)
329  cout << st.json(styledJson);
330  else if (mode == Mode::OutputOnly)
331  cout << toHex(output) << '\n';
332  else if (mode == Mode::Test)
333  {
334  // Output information needed for test verification and benchmarking
335  // in YAML-like dictionaly format.
336  auto exception = res.excepted != TransactionException::None;
337  cout << "output: '" << toHex(output) << "'\n";
338  cout << "exception: " << boolalpha << exception << '\n';
339  cout << "gas used: " << res.gasUsed << '\n';
340  cout << "gas/sec: " << scientific << setprecision(3) << uint64_t(res.gasUsed)/execTime << '\n';
341  cout << "exec time: " << fixed << setprecision(6) << execTime << '\n';
342  }
343 
344  return 0;
345 }
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
bool call(Address _receiveAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256 _gas)
Set up the executive for evaluating a bare CALL (message call) operation.
Definition: Executive.cpp:261
bool create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress)
Set up the executive for evaluating a bare CREATE (contract-creation) operation.
Definition: Executive.cpp:333
void help()
Definition: main.cpp:39
std::string toHex(T const &_data, int _w=2, HexPrefix _prefix=HexPrefix::DontAdd)
Definition: CommonData.h:54
uint8_t byte
Definition: Common.h:57
Network
The network id.
Definition: GenesisInfo.h:34
boost::multiprecision::number< boost::multiprecision::cpp_int_backend<>> bigint
Definition: Common.h:121
Models the state of a single Ethereum account.
Definition: Account.h:67
h160 Address
An Ethereum address: 20 bytes.
Definition: Common.h:62
evm_mode mode
Definition: SmartVM.cpp:47
#define c(i)
std::hash for asio::adress
Definition: Common.h:323
Test mode ā€“ output information needed for test verification and benchmarking.
#define DEV_QUOTED(s)
Definition: Common.h:61
void setGasLimit(int64_t _v)
Definition: ExtVMFace.h:249
int64_t baseGasRequired(EVMSchedule const &_es) const
Definition: Transaction.h:148
Description of the result of executing a transaction.
Definition: Transaction.h:69
bytes code
Definition: SmartVM.cpp:45
Model of an Ethereum state, essentially a facade for the trie.
Definition: State.h:161
bool go(OnOpFunc const &_onOp=OnOpFunc())
Executes (or continues execution of) the VM.
Definition: Executive.cpp:386
void populateFrom(AccountMap const &_map)
Populate the state from the given AccountMap. Just uses dev::eth::commit().
Definition: State.cpp:115
void version()
Definition: main.cpp:53
InstructionInfo instructionInfo(Instruction _inst)
Information on all the instructions.
bytes fromHex(std::string const &_s, WhenError _throw=WhenError::DontThrow)
Definition: CommonData.cpp:99
double elapsed() const
Definition: Common.h:280
void setDefaultOrCLocale()
Definition: main.cpp:72
std::string json(bool _styled=false) const
Definition: Executive.cpp:150
std::string name
The name of the instruction.
Definition: Instruction.h:260
int main(int argc, char **argv)
Definition: main.cpp:149
void setNewCode(bytes &&_code)
Sets the code of the account. Used by "create" messages.
Definition: Account.cpp:31
void finalize()
Finalise a transaction previously set up with initialize().
Definition: Executive.cpp:466
void setTimestamp(u256 const &_v)
Definition: ExtVMFace.h:247
std::vector< byte > bytes
Definition: Common.h:75
Fixed-size raw-byte array container type, with an API optimised for storing hashes.
Definition: FixedHash.h:47
bytes const & data() const
Definition: Transaction.h:131
void setNumber(u256 const &_v)
Definition: ExtVMFace.h:245
Message-call/contract-creation executor; useful for executing transactions.
Definition: Executive.h:106
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u256
Definition: Common.h:125
LogEntries const & logs() const
Definition: Executive.h:148
Encodes a transaction, ready to be exported to or freshly imported from RLP.
Definition: Transaction.h:84
TransactionException excepted
Definition: Transaction.h:72
Instruction
Virtual machine bytecode instruction.
Definition: Instruction.h:39
void initialize(bytesConstRef _transaction)
Initializes the executive for evaluating a transaction. You must call finalize() at some point follow...
Definition: Executive.h:135
Interface and null implementation of the class for specifying VM externalities.
Definition: ExtVMFace.h:265
u256 u256Param(std::string const &_name) const
Convenience method to get an otherParam as a u256 int.
std::string const & genesisInfo(Network _n)
Definition: GenesisInfo.cpp:37
uint8_t byte
Definition: Common.h:10
void forceSender(Address const &_a)
Force the sender to a particular value. This will result in an invalid transaction RLP...
Definition: Transaction.h:87
virtual void addBalance(Address const &_id, u256 const &_amount)
Add some amount to balance.
Definition: State.cpp:286
char const * Version
Definition: Common.cpp:36
void setAuthor(Address const &_v)
Definition: ExtVMFace.h:246
Mode
Definition: main.cpp:82
void setDifficulty(u256 const &_v)
Definition: ExtVMFace.h:248
bytes contents(std::string const &_file)
Retrieve and returns the contents of the given file.
uint8_t const * data
Definition: sha3.h:19
std::vector< LogEntry > LogEntries
Definition: ExtVMFace.h:110
void setResultRecipient(ExecutionResult &_res)
Collect execution results in the result storage provided.
Definition: Executive.h:184
std::string hex() const
Definition: FixedHash.h:130
Definition: ExtVMFace.h:88