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
3326void  delete_output (const  evmc_result* result)
3427{
3528    delete[]  result->output_data ;
3629}
3730
38- evmc_result execute (evmc_instance* _instance, evmc_context* _context, evmc_revision _rev,
39-     evmc_message const * _msg, uint8_t  const * _code, size_t  _codeSize) noexcept 
31+ class  InterpreterEvmcInstance  : public  evmc_instance 
4032{
41-     ( void )_instance; 
42-     std::unique_ptr<dev::eth::VM> vm{ new  dev::eth::VM}; 
33+ public: 
34+     static  InterpreterEvmcInstance*  create () {  return   new  InterpreterEvmcInstance{}; } 
4335
44-     evmc_result result = {};
45-     dev::eth::owning_bytes_ref output;
46- 
47-     try 
48-     {
49-         output = vm->exec (_context, _rev, _msg, _code, _codeSize);
50-         result.status_code  = EVMC_SUCCESS;
51-         result.gas_left  = vm->m_io_gas ;
52-     }
53-     catch  (dev::eth::RevertInstruction& ex)
54-     {
55-         result.status_code  = EVMC_REVERT;
56-         result.gas_left  = vm->m_io_gas ;
57-         output = ex.output ();  //  This moves the output from the exception!
58-     }
59-     catch  (dev::eth::BadInstruction const &)
60-     {
61-         result.status_code  = EVMC_UNDEFINED_INSTRUCTION;
62-     }
63-     catch  (dev::eth::DisallowedStateChange const &)
36+ private: 
37+     InterpreterEvmcInstance ()
38+       : evmc_instance{
39+             EVMC_ABI_VERSION, " interpreter" aleth_get_buildinfo ()->project_version , destroy,
40+             execute, setTracer,
41+             nullptr ,  //  set_option
42+         }
6443    {
65-         result.status_code  = EVMC_STATIC_MODE_VIOLATION;
6644    }
67-     catch  (dev::eth::VMException const &)
45+ 
46+     static  void  destroy (evmc_instance* _instance)
6847    {
69-         result. status_code  = EVMC_FAILURE ;
48+         delete   static_cast <InterpreterEvmcInstance*>(_instance) ;
7049    }
71-     catch  (...)
50+ 
51+     static  evmc_result execute (evmc_instance* _instance, evmc_context* _context, evmc_revision _rev,
52+         evmc_message const * _msg, uint8_t  const * _code, size_t  _codeSize) noexcept 
7253    {
73-         result.status_code  = EVMC_INTERNAL_ERROR;
54+         std::unique_ptr<dev::eth::VM> vm{new  dev::eth::VM};
55+ 
56+         evmc_result result = {};
57+         dev::eth::owning_bytes_ref output;
58+ 
59+         auto  evmc = static_cast <InterpreterEvmcInstance*>(_instance);
60+         try 
61+         {
62+             output = vm->exec (_context, _rev, _msg, _code, _codeSize, evmc->m_traceCallback ,
63+                 evmc->m_traceContext );
64+             result.status_code  = EVMC_SUCCESS;
65+             result.gas_left  = vm->m_io_gas ;
66+         }
67+         catch  (dev::eth::RevertInstruction& ex)
68+         {
69+             result.status_code  = EVMC_REVERT;
70+             result.gas_left  = vm->m_io_gas ;
71+             output = ex.output ();  //  This moves the output from the exception!
72+         }
73+         catch  (dev::eth::BadInstruction const &)
74+         {
75+             result.status_code  = EVMC_UNDEFINED_INSTRUCTION;
76+         }
77+         catch  (dev::eth::DisallowedStateChange const &)
78+         {
79+             result.status_code  = EVMC_STATIC_MODE_VIOLATION;
80+         }
81+         catch  (dev::eth::VMException const &)
82+         {
83+             result.status_code  = EVMC_FAILURE;
84+         }
85+         catch  (...)
86+         {
87+             result.status_code  = EVMC_INTERNAL_ERROR;
88+         }
89+ 
90+         if  (!output.empty ())
91+         {
92+             //  Make a copy of the output.
93+             auto  outputData = new  uint8_t [output.size ()];
94+             std::memcpy (outputData, output.data (), output.size ());
95+             result.output_data  = outputData;
96+             result.output_size  = output.size ();
97+             result.release  = delete_output;
98+         }
99+ 
100+         return  result;
74101    }
75102
76-     if  (!output.empty ())
103+     static  void  setTracer (evmc_instance* _instance, evmc_trace_callback _callback,
104+         evmc_tracer_context* _context) noexcept 
77105    {
78-         //  Make a copy of the output.
79-         auto  outputData = new  uint8_t [output.size ()];
80-         std::memcpy (outputData, output.data (), output.size ());
81-         result.output_data  = outputData;
82-         result.output_size  = output.size ();
83-         result.release  = delete_output;
106+         auto  evmc = static_cast <InterpreterEvmcInstance*>(_instance);
107+ 
108+         evmc->m_traceCallback  = _callback;
109+         evmc->m_traceContext  = _context;
84110    }
85111
86-     return  result;
87- }
112+     evmc_trace_callback m_traceCallback = nullptr ;
113+     evmc_tracer_context* m_traceContext = nullptr ;
114+ };
88115
89- void  setTracer (evmc_instance* /* _instance*/ 
90-     evmc_tracer_context* _context) noexcept 
91- {
92-     g_traceCallback = _callback;
93-     g_traceContext = _context;
94- }
95116}  //  namespace
96117
97118extern  " C" evmc_create_interpreter () noexcept 
98119{
99-     //  TODO: Allow creating multiple instances with different configurations.
100-     static  evmc_instance s_instance{
101-         EVMC_ABI_VERSION, " interpreter" aleth_get_buildinfo ()->project_version , ::destroy,
102-         ::execute, ::setTracer,
103-         nullptr ,  //  set_option
104-     };
105-     return  &s_instance;
120+     return  InterpreterEvmcInstance::create ();
106121}
107122
108123namespace  dev 
@@ -111,7 +126,7 @@ namespace eth
111126{
112127void  VM::trace () noexcept 
113128{
114-     if  (g_traceCallback )
129+     if  (m_traceCallback )
115130    {
116131        auto  const & metrics = c_metrics[static_cast <size_t >(m_OP)];
117132        evmc_uint256be topStackItem;
@@ -121,7 +136,7 @@ void VM::trace() noexcept
121136            topStackItem = toEvmC (m_SPP[0 ]);
122137            pushedStackItem = &topStackItem;
123138        }
124-         g_traceCallback (g_traceContext , m_PC, EVMC_SUCCESS, m_io_gas, m_stackEnd - m_SPP,
139+         m_traceCallback (m_traceContext , m_PC, EVMC_SUCCESS, m_io_gas, m_stackEnd - m_SPP,
125140            pushedStackItem, m_mem.size (), 0 , 0 , nullptr );
126141    }
127142}
@@ -269,7 +284,8 @@ evmc_tx_context const& VM::getTxContext()
269284//  interpreter entry point
270285
271286owning_bytes_ref VM::exec (evmc_context* _context, evmc_revision _rev, const  evmc_message* _msg,
272-     uint8_t  const * _code, size_t  _codeSize)
287+     uint8_t  const * _code, size_t  _codeSize, evmc_trace_callback _traceCallback,
288+     evmc_tracer_context* _traceContext)
273289{
274290    m_context = _context;
275291    m_rev = _rev;
@@ -278,6 +294,8 @@ owning_bytes_ref VM::exec(evmc_context* _context, evmc_revision _rev, const evmc
278294    m_PC = 0 ;
279295    m_pCode = _code;
280296    m_codeSize = _codeSize;
297+     m_traceCallback = _traceCallback;
298+     m_traceContext = _traceContext;
281299
282300    //  trampoline to minimize depth of call stack when calling out
283301    m_bounce = &VM::initEntry;
0 commit comments