Ethereum  PoC-8
The C++ Implementation of Ethereum
LegacyVM.h
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 */
17 
18 #pragma once
19 
20 #include "Instruction.h"
21 #include "LegacyVMConfig.h"
22 #include "VMFace.h"
23 
24 namespace dev
25 {
26 namespace eth
27 {
28 
29 class LegacyVM: public VMFace
30 {
31 public:
32  virtual owning_bytes_ref exec(u256& _io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp) override final;
33 
34 #if EIP_615
35  // invalid code will throw an exeption
36  void validate(ExtVMFace& _ext);
37  void validateSubroutine(uint64_t _PC, uint64_t* _rp, u256* _sp);
38 #endif
39 
40  bytes const& memory() const { return m_mem; }
41  u256s stack() const {
42  u256s stack(m_SP, m_stackEnd);
43  reverse(stack.begin(), stack.end());
44  return stack;
45  };
46 
47 private:
48 
49  u256* m_io_gas_p = 0;
50  uint64_t m_io_gas = 0;
51  ExtVMFace* m_ext = 0;
52  OnOpFunc m_onOp;
53 
54  static std::array<InstructionMetric, 256> c_metrics;
55  static void initMetrics();
56  static u256 exp256(u256 _base, u256 _exponent);
57  void copyCode(int);
58  typedef void (LegacyVM::*MemFnPtr)();
59  MemFnPtr m_bounce = 0;
60  MemFnPtr m_onFail = 0;
61  uint64_t m_nSteps = 0;
62  EVMSchedule const* m_schedule = nullptr;
63 
64  // return bytes
65  owning_bytes_ref m_output;
66 
67  // space for memory
68  bytes m_mem;
69 
70  // space for code
71  bytes m_code;
72 
74  bytes m_returnData;
75 
76  // space for data stack, grows towards smaller addresses from the end
77  u256 m_stack[1024];
78  u256 *m_stackEnd = &m_stack[1024];
79  size_t stackSize() { return m_stackEnd - m_SP; }
80 
81 #if EIP_615
82  // space for return stack
83  uint64_t m_return[1024];
84 
85  // mark PCs with frame size to detect cycles and stack mismatch
86  std::vector<size_t> m_frameSize;
87 #endif
88 
89  // constant pool
90  std::vector<u256> m_pool;
91 
92  // interpreter state
93  Instruction m_OP; // current operation
94  uint64_t m_PC = 0; // program counter
95  u256* m_SP = m_stackEnd; // stack pointer
96  u256* m_SPP = m_SP; // stack pointer prime (next SP)
97 #if EIP_615
98  uint64_t* m_RP = m_return - 1; // return pointer
99 #endif
100 
101  // metering and memory state
102  uint64_t m_runGas = 0;
103  uint64_t m_newMemSize = 0;
104  uint64_t m_copyMemSize = 0;
105 
106  // initialize interpreter
107  void initEntry();
108  void optimize();
109 
110  // interpreter loop & switch
111  void interpretCases();
112 
113  // interpreter cases that call out
114  void caseCreate();
115  bool caseCallSetup(CallParameters*, bytesRef& o_output);
116  void caseCall();
117 
118  void copyDataToMemory(bytesConstRef _data, u256*_sp);
119  uint64_t memNeed(u256 const& _offset, u256 const& _size);
120 
121  void throwOutOfGas();
122  void throwBadInstruction();
123  void throwBadJumpDestination();
124  void throwBadStack(unsigned _removed, unsigned _added);
125  void throwRevertInstruction(owning_bytes_ref&& _output);
126  void throwDisallowedStateChange();
127  void throwBufferOverrun(bigint const& _enfOfAccess);
128 
129  std::vector<uint64_t> m_beginSubs;
130  std::vector<uint64_t> m_jumpDests;
131  int64_t verifyJumpDest(u256 const& _dest, bool _throw = true);
132 
133  void onOperation();
134  void adjustStack(unsigned _removed, unsigned _added);
135  uint64_t gasForMem(u512 const& _size);
136  void updateSSGas();
137  void updateSSGasPreEIP1283(u256 const& _currentValue, u256 const& _newValue);
138  void updateSSGasEIP1283(u256 const& _currentValue, u256 const& _newValue);
139  void updateIOGas();
140  void updateGas();
141  void updateMem(uint64_t _newMem);
142  void logGasMem();
143  void fetchInstruction();
144 
145  uint64_t decodeJumpDest(const byte* const _code, uint64_t& _pc);
146  uint64_t decodeJumpvDest(const byte* const _code, uint64_t& _pc, byte _voff);
147 
148  template<class T> uint64_t toInt63(T v)
149  {
150  // check for overflow
151  if (v > 0x7FFFFFFFFFFFFFFF)
152  throwOutOfGas();
153  uint64_t w = uint64_t(v);
154  return w;
155  }
156 
157  template<class T> uint64_t toInt15(T v)
158  {
159  // check for overflow
160  if (v > 0x7FFF)
161  throwOutOfGas();
162  uint64_t w = uint64_t(v);
163  return w;
164  }
165 
166  //
167  // implementations of simd opcodes
168  //
169  // input bytes are the inline simd type descriptors for the operand vectors on the stack
170  //
171 #if EIP_616
172 
173  void xadd (uint8_t);
174  void xmul (uint8_t);
175  void xsub (uint8_t);
176  void xdiv (uint8_t);
177  void xsdiv (uint8_t);
178  void xmod (uint8_t);
179  void xsmod (uint8_t);
180  void xlt (uint8_t);
181  void xslt (uint8_t);
182  void xgt (uint8_t);
183  void xsgt (uint8_t);
184  void xeq (uint8_t);
185  void xzero (uint8_t);
186  void xand (uint8_t);
187  void xoor (uint8_t);
188  void xxor (uint8_t);
189  void xnot (uint8_t);
190  void xshr (uint8_t);
191  void xsar (uint8_t);
192  void xshl (uint8_t);
193  void xrol (uint8_t);
194  void xror (uint8_t);
195  void xmload (uint8_t);
196  void xmstore (uint8_t);
197  void xsload (uint8_t);
198  void xsstore (uint8_t);
199  void xvtowide(uint8_t);
200  void xwidetov(uint8_t);
201  void xpush (uint8_t);
202  void xput (uint8_t, uint8_t);
203  void xget (uint8_t, uint8_t);
204  void xswizzle(uint8_t);
205  void xshuffle(uint8_t);
206 
207  u256 vtow(uint8_t _b, const u256& _in);
208  void wtov(uint8_t _b, u256 _in, u256& _o_out);
209 
210  uint8_t simdType()
211  {
212  uint8_t nt = m_code[++m_PC]; // advance PC and get simd type from code
213  ++m_PC; // advance PC to next opcode, ready to continue
214  return nt;
215  }
216 
217 #endif
218 };
219 
220 }
221 }
dev::eth::OnOpFunc
std::function< void(uint64_t, uint64_t, Instruction, bigint, bigint, bigint, VMFace const *, ExtVMFace const *)> OnOpFunc
Definition: ExtVMFace.h:115
dev::vector_ref
Definition: vector_ref.h:22
VMFace.h
dev::u512
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 512, 512, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > u512
Definition: Common.h:125
dev::eth::owning_bytes_ref
Definition: ExtVMFace.h:58
dev::eth::VMFace
EVM Virtual Machine interface.
Definition: VMFace.h:64
dev::eth::ExtVMFace
Interface and null implementation of the class for specifying VM externalities.
Definition: ExtVMFace.h:204
dev::eth::LegacyVM::memory
bytes const & memory() const
Definition: LegacyVM.h:40
dev::eth::LegacyVM::exec
virtual owning_bytes_ref exec(u256 &_io_gas, ExtVMFace &_ext, OnOpFunc const &_onOp) override final
VM implementation.
Definition: LegacyVM.cpp:217
dev::eth::LegacyVM
Definition: LegacyVM.h:30
dev::bytes
std::vector< byte > bytes
Definition: Common.h:72
LegacyVMConfig.h
dev::eth::Instruction
Instruction
Virtual machine bytecode instruction.
Definition: Instruction.h:29
dev::bigint
boost::multiprecision::number< boost::multiprecision::cpp_int_backend<> > bigint
Definition: Common.h:118
dev::u256
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > u256
Definition: Common.h:121
Instruction.h
dev
Definition: Address.cpp:21
dev::eth::EVMSchedule
Definition: EVMSchedule.h:29
dev::eth::LegacyVM::stack
u256s stack() const
Definition: LegacyVM.h:41
dev::u256s
std::vector< u256 > u256s
Definition: Common.h:127