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*/ , evmc_trace_callback _callback,
90- evmc_tracer_context* _context) noexcept
91- {
92- g_traceCallback = _callback;
93- g_traceContext = _context;
94- }
95116} // namespace
96117
97118extern " C" evmc_instance* 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