2222
2323namespace 
2424{
25- evmc_trace_callback g_traceCallback = nullptr ;
26- evmc_tracer_context* g_traceContext = nullptr ;
27- 
28- void  destroy (evmc_instance* _instance)
29- {
30-     (void )_instance;
31- }
3225
3326evmc_capabilities_flagset getCapabilities (evmc_instance* _instance) noexcept 
3427{
@@ -41,99 +34,115 @@ void delete_output(const evmc_result* result)
4134    delete[]  result->output_data ;
4235}
4336
44- evmc_result execute (evmc_instance* _instance, evmc_context* _context, evmc_revision _rev,
45-     evmc_message const * _msg, uint8_t  const * _code, size_t  _codeSize) noexcept 
37+ class  InterpreterEvmcInstance  : public  evmc_instance 
4638{
47-     ( void )_instance; 
48-     std::unique_ptr<dev::eth::VM> vm{ new  dev::eth::VM}; 
39+ public: 
40+     static  InterpreterEvmcInstance*  create () {  return   new  InterpreterEvmcInstance{}; } 
4941
50-     evmc_result result = {};
51-     dev::eth::owning_bytes_ref output;
42+ private: 
43+     InterpreterEvmcInstance ()
44+       : evmc_instance{
45+             EVMC_ABI_VERSION, " interpreter" aleth_get_buildinfo ()->project_version , destroy,
46+             execute, getCapabilities, setTracer,
47+             nullptr ,  //  set_option
48+         }
49+     {}
5250
53-     try 
54-     {
55-         output = vm->exec (_context, _rev, _msg, _code, _codeSize);
56-         result.status_code  = EVMC_SUCCESS;
57-         result.gas_left  = vm->m_io_gas ;
58-     }
59-     catch  (dev::eth::RevertInstruction& ex)
51+     static  void  destroy (evmc_instance* _instance)
6052    {
61-         result.status_code  = EVMC_REVERT;
62-         result.gas_left  = vm->m_io_gas ;
63-         output = ex.output ();  //  This moves the output from the exception!
53+         delete  static_cast <InterpreterEvmcInstance*>(_instance);
6454    }
65-     catch  (dev::eth::BadInstruction const &)
66-     {
67-         result.status_code  = EVMC_UNDEFINED_INSTRUCTION;
68-     }
69-     catch  (dev::eth::OutOfStack const &)
70-     {
71-         result.status_code  = EVMC_STACK_OVERFLOW;
72-     }
73-     catch  (dev::eth::StackUnderflow const &)
74-     {
75-         result.status_code  = EVMC_STACK_UNDERFLOW;
76-     }
77-     catch  (dev::eth::BufferOverrun const &)
78-     {
79-         result.status_code  = EVMC_INVALID_MEMORY_ACCESS;
80-     }
81-     catch  (dev::eth::OutOfGas const &)
82-     {
83-         result.status_code  = EVMC_OUT_OF_GAS;
84-     }
85-     catch  (dev::eth::BadJumpDestination const &)
86-     {
87-         result.status_code  = EVMC_BAD_JUMP_DESTINATION;
88-     }
89-     catch  (dev::eth::DisallowedStateChange const &)
90-     {
91-         result.status_code  = EVMC_STATIC_MODE_VIOLATION;
92-     }
93-     catch  (dev::eth::VMException const &)
94-     {
95-         result.status_code  = EVMC_FAILURE;
96-     }
97-     catch  (...)
55+ 
56+     static  evmc_result execute (evmc_instance* _instance, evmc_context* _context, evmc_revision _rev,
57+         evmc_message const * _msg, uint8_t  const * _code, size_t  _codeSize) noexcept 
9858    {
99-         result.status_code  = EVMC_INTERNAL_ERROR;
59+         std::unique_ptr<dev::eth::VM> vm{new  dev::eth::VM};
60+ 
61+         evmc_result result = {};
62+         dev::eth::owning_bytes_ref output;
63+ 
64+         auto  evmc = static_cast <InterpreterEvmcInstance*>(_instance);
65+         try 
66+         {
67+             output = vm->exec (_context, _rev, _msg, _code, _codeSize, evmc->m_traceCallback ,
68+                 evmc->m_traceContext );
69+             result.status_code  = EVMC_SUCCESS;
70+             result.gas_left  = vm->m_io_gas ;
71+         }
72+         catch  (dev::eth::RevertInstruction& ex)
73+         {
74+             result.status_code  = EVMC_REVERT;
75+             result.gas_left  = vm->m_io_gas ;
76+             output = ex.output ();  //  This moves the output from the exception!
77+         }
78+         catch  (dev::eth::BadInstruction const &)
79+         {
80+             result.status_code  = EVMC_UNDEFINED_INSTRUCTION;
81+         }
82+         catch  (dev::eth::OutOfStack const &)
83+         {
84+             result.status_code  = EVMC_STACK_OVERFLOW;
85+         }
86+         catch  (dev::eth::StackUnderflow const &)
87+         {
88+             result.status_code  = EVMC_STACK_UNDERFLOW;
89+         }
90+         catch  (dev::eth::BufferOverrun const &)
91+         {
92+             result.status_code  = EVMC_INVALID_MEMORY_ACCESS;
93+         }
94+         catch  (dev::eth::OutOfGas const &)
95+         {
96+             result.status_code  = EVMC_OUT_OF_GAS;
97+         }
98+         catch  (dev::eth::BadJumpDestination const &)
99+         {
100+             result.status_code  = EVMC_BAD_JUMP_DESTINATION;
101+         }
102+         catch  (dev::eth::DisallowedStateChange const &)
103+         {
104+             result.status_code  = EVMC_STATIC_MODE_VIOLATION;
105+         }
106+         catch  (dev::eth::VMException const &)
107+         {
108+             result.status_code  = EVMC_FAILURE;
109+         }
110+         catch  (...)
111+         {
112+             result.status_code  = EVMC_INTERNAL_ERROR;
113+         }
114+ 
115+         if  (!output.empty ())
116+         {
117+             //  Make a copy of the output.
118+             auto  outputData = new  uint8_t [output.size ()];
119+             std::memcpy (outputData, output.data (), output.size ());
120+             result.output_data  = outputData;
121+             result.output_size  = output.size ();
122+             result.release  = delete_output;
123+         }
124+ 
125+         return  result;
100126    }
101127
102-     if  (!output.empty ())
128+     static  void  setTracer (evmc_instance* _instance, evmc_trace_callback _callback,
129+         evmc_tracer_context* _context) noexcept 
103130    {
104-         //  Make a copy of the output.
105-         auto  outputData = new  uint8_t [output.size ()];
106-         std::memcpy (outputData, output.data (), output.size ());
107-         result.output_data  = outputData;
108-         result.output_size  = output.size ();
109-         result.release  = delete_output;
131+         auto  evmc = static_cast <InterpreterEvmcInstance*>(_instance);
132+ 
133+         evmc->m_traceCallback  = _callback;
134+         evmc->m_traceContext  = _context;
110135    }
111136
112-     return  result;
113- }
137+     evmc_trace_callback m_traceCallback = nullptr ;
138+     evmc_tracer_context* m_traceContext = nullptr ;
139+ };
114140
115- void  setTracer (evmc_instance* /* _instance*/ 
116-     evmc_tracer_context* _context) noexcept 
117- {
118-     g_traceCallback = _callback;
119-     g_traceContext = _context;
120- }
121141}  //  namespace
122142
123143extern  " C" evmc_create_interpreter () noexcept 
124144{
125-     //  TODO: Allow creating multiple instances with different configurations.
126-     static  evmc_instance s_instance{
127-         EVMC_ABI_VERSION,
128-         " interpreter" 
129-         aleth_get_buildinfo ()->project_version ,
130-         ::destroy,
131-         ::execute,
132-         getCapabilities,
133-         ::setTracer,
134-         nullptr ,  //  set_option
135-     };
136-     return  &s_instance;
145+     return  InterpreterEvmcInstance::create ();
137146}
138147
139148namespace  dev 
@@ -142,7 +151,7 @@ namespace eth
142151{
143152void  VM::trace () noexcept 
144153{
145-     if  (g_traceCallback )
154+     if  (m_traceCallback )
146155    {
147156        auto  const & metrics = c_metrics[static_cast <size_t >(m_OP)];
148157        evmc_uint256be topStackItem;
@@ -152,7 +161,7 @@ void VM::trace() noexcept
152161            topStackItem = toEvmC (m_SPP[0 ]);
153162            pushedStackItem = &topStackItem;
154163        }
155-         g_traceCallback (g_traceContext , m_PC, EVMC_SUCCESS, m_io_gas, m_stackEnd - m_SPP,
164+         m_traceCallback (m_traceContext , m_PC, EVMC_SUCCESS, m_io_gas, m_stackEnd - m_SPP,
156165            pushedStackItem, m_mem.size (), 0 , 0 , nullptr );
157166    }
158167}
@@ -288,7 +297,8 @@ evmc_tx_context const& VM::getTxContext()
288297//  interpreter entry point
289298
290299owning_bytes_ref VM::exec (evmc_context* _context, evmc_revision _rev, const  evmc_message* _msg,
291-     uint8_t  const * _code, size_t  _codeSize)
300+     uint8_t  const * _code, size_t  _codeSize, evmc_trace_callback _traceCallback,
301+     evmc_tracer_context* _traceContext)
292302{
293303    m_context = _context;
294304    m_rev = _rev;
@@ -297,6 +307,8 @@ owning_bytes_ref VM::exec(evmc_context* _context, evmc_revision _rev, const evmc
297307    m_PC = 0 ;
298308    m_pCode = _code;
299309    m_codeSize = _codeSize;
310+     m_traceCallback = _traceCallback;
311+     m_traceContext = _traceContext;
300312
301313    //  trampoline to minimize depth of call stack when calling out
302314    m_bounce = &VM::initEntry;
0 commit comments