8#include <sysio/vm/backend.hpp>
10#ifdef SYSIO_SYS_VM_OC_RUNTIME_ENABLED
13#include <boost/hana/string.hpp>
14#include <boost/hana/equal.hpp>
16namespace sysio {
namespace chain {
namespace webassembly {
namespace eos_vm_runtime {
24 struct checktime_watchdog {
30 _timer.set_expiration_callback(&callback,
this);
36 _timer.set_expiration_callback(
nullptr,
nullptr);
38 static void callback(
void* data) {
39 guard*
self =
static_cast<guard*
>(data);
46 guard<F> scoped_run(F&& func) {
72 for(std::uint32_t i = 0; i < imports.size(); ++i) {
73 SYS_ASSERT(std::string_view((
char*)imports[i].module_str.raw(), imports[i].module_str.size()) ==
"env" &&
74 is_intrinsic_whitelisted(intrinsics, std::string_view((
char*)imports[i].field_str.raw(), imports[i].field_str.size())),
75 wasm_serialization_error,
"${module}.${fn} unresolveable",
76 (
"module", std::string((
char*)imports[i].module_str.raw(), imports[i].module_str.size()))
77 (
"fn", std::string((
char*)imports[i].field_str.raw(), imports[i].field_str.size())));
93 for(std::uint32_t i = 0; i < imports.size(); ++i) {
94 SYS_ASSERT(std::string_view((
char*)imports[i].module_str.raw(), imports[i].module_str.size()) ==
"env" &&
95 is_intrinsic_whitelisted(intrinsics, std::string_view((
char*)imports[i].field_str.raw(), imports[i].field_str.size())),
96 wasm_serialization_error,
"${module}.${fn} unresolveable",
97 (
"module", std::string((
char*)imports[i].module_str.raw(), imports[i].module_str.size()))
98 (
"fn", std::string((
char*)imports[i].field_str.raw(), imports[i].field_str.size())));
102 SYS_ASSERT(apply_idx < std::numeric_limits<uint32_t>::max(), wasm_serialization_error,
"apply not exported");
121template<
typename Impl>
128 _instantiated_module(
std::move(mod)) {}
131 _instantiated_module->set_wasm_allocator(&
context.control.get_wasm_allocator());
132 _runtime->_bkend = _instantiated_module.get();
140 _runtime->_bkend->initialize(&iface, opts);
141 _runtime->_bkend->call(
142 iface,
"env",
"apply",
143 context.get_receiver().to_uint64_t(),
144 context.get_action().account.to_uint64_t(),
145 context.get_action().name.to_uint64_t());
148 checktime_watchdog
wd(
context.trx_context.transaction_timer);
149 _runtime->_bkend->timed_run(
wd, fn);
150 }
catch(sysio::vm::timeout_exception&) {
151 context.trx_context.checktime();
152 }
catch(sysio::vm::wasm_memory_exception& e) {
157 _runtime->_bkend =
nullptr;
162 std::unique_ptr<backend_t> _instantiated_module;
169 eos_vm_profiling_module(std::unique_ptr<backend_t> mod,
const char * code, std::size_t code_size) :
170 _instantiated_module(
std::move(mod)),
171 _original_code(code, code + code_size) {}
175 _instantiated_module->set_wasm_allocator(&
context.control.get_wasm_allocator());
177 if(
context.control.is_builtin_activated(builtin_protocol_feature_t::configurable_wasm_limits)) {
183 _instantiated_module->initialize(&iface, opts);
184 _instantiated_module->call(
185 iface,
"env",
"apply",
186 context.get_receiver().to_uint64_t(),
187 context.get_action().account.to_uint64_t(),
188 context.get_action().name.to_uint64_t());
193 checktime_watchdog
wd(
context.trx_context.transaction_timer);
194 _instantiated_module->timed_run(
wd, fn);
195 }
catch(sysio::vm::timeout_exception&) {
196 context.trx_context.checktime();
197 }
catch(sysio::vm::wasm_memory_exception& e) {
204 void fast_shutdown()
override {
210 if(!
context.control.is_profiling(account))
return nullptr;
211 if(
auto it = _prof.find(account); it != _prof.end()) {
212 return it->second.get();
215 std::string basename = account.to_string() +
"." + std::to_string(code_sequence);
216 auto prof = std::make_unique<profile_data>(basename +
".profile", *_instantiated_module);
217 auto [pos,
_] = _prof.insert(std::pair{ account, std::move(prof)});
218 std::ofstream outfile(basename +
".wasm");
219 outfile.write(_original_code.data(), _original_code.size());
220 return pos->second.get();
227 std::unique_ptr<backend_t> _instantiated_module;
228 boost::container::flat_map<name, std::unique_ptr<profile_data>> _prof;
229 std::vector<char> _original_code;
233template<
typename Impl>
236template<
typename Impl>
241template<
typename Impl>
249 .max_call_depth = 0 };
250 std::unique_ptr<backend_t>
bkend = std::make_unique<backend_t>(code, code_size,
nullptr,
options);
252 return std::make_unique<eos_vm_instantiated_module<Impl>>(
this, std::move(
bkend));
274 apply_options
options = { .max_pages = 65536,
275 .max_call_depth = 0 };
276 std::unique_ptr<backend_t>
bkend = std::make_unique<backend_t>(code, code_size,
nullptr,
options);
278 return std::make_unique<eos_vm_profiling_module>(std::move(
bkend), code_bytes, code_size);
287template <
auto HostFunction,
typename... Preconditions>
289 template <
typename Mod,
typename Name>
292 rhf_t::add<HostFunction, Preconditions...>(mod_name.c_str(), fn_name.c_str());
293#ifdef SYSIO_SYS_VM_OC_RUNTIME_ENABLED
296 mod_name + BOOST_HANA_STRING(
".") + fn_name);
301#define REGISTER_INJECTED_HOST_FUNCTION(NAME, ...) \
302 static host_function_registrator<&interface::NAME, ##__VA_ARGS__> NAME##_registrator_impl() { \
303 return {BOOST_HANA_STRING(SYSIO_INJECTED_MODULE_NAME), BOOST_HANA_STRING(#NAME)}; \
305 inline static auto NAME##_registrator = NAME##_registrator_impl();
307#define REGISTER_HOST_FUNCTION(NAME, ...) \
308 static host_function_registrator<&interface::NAME, core_precondition, context_aware_check, ##__VA_ARGS__> \
309 NAME##_registrator_impl() { \
310 return {BOOST_HANA_STRING("env"), BOOST_HANA_STRING(#NAME)}; \
312 inline static auto NAME##_registrator = NAME##_registrator_impl();
314#define REGISTER_CF_HOST_FUNCTION(NAME, ...) \
315 static host_function_registrator<&interface::NAME, core_precondition, ##__VA_ARGS__> NAME##_registrator_impl() { \
316 return {BOOST_HANA_STRING("env"), BOOST_HANA_STRING(#NAME)}; \
318 inline static auto NAME##_registrator = NAME##_registrator_impl();
320#define REGISTER_LEGACY_HOST_FUNCTION(NAME, ...) \
321 static host_function_registrator<&interface::NAME, legacy_static_check_wl_args, context_aware_check, ##__VA_ARGS__> \
322 NAME##_registrator_impl() { \
323 return {BOOST_HANA_STRING("env"), BOOST_HANA_STRING(#NAME)}; \
325 inline static auto NAME##_registrator = NAME##_registrator_impl();
327#define REGISTER_LEGACY_CF_HOST_FUNCTION(NAME, ...) \
328 static host_function_registrator<&interface::NAME, legacy_static_check_wl_args, ##__VA_ARGS__> \
329 NAME##_registrator_impl() { \
330 return {BOOST_HANA_STRING("env"), BOOST_HANA_STRING(#NAME)}; \
332 inline static auto NAME##_registrator = NAME##_registrator_impl();
334#define REGISTER_LEGACY_CF_ONLY_HOST_FUNCTION(NAME, ...) \
335 static host_function_registrator<&interface::NAME, legacy_static_check_wl_args, context_free_check, ##__VA_ARGS__> \
336 NAME##_registrator_impl() { \
337 return {BOOST_HANA_STRING("env"), BOOST_HANA_STRING(#NAME)}; \
339 inline static auto NAME##_registrator = NAME##_registrator_impl();
#define SYS_THROW(exc_type, FORMAT,...)
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
void apply(apply_context &context) override
eos_vm_instantiated_module(eos_vm_runtime< Impl > *runtime, std::unique_ptr< backend_t > mod)
void immediately_exit_currently_running_module() override
std::unique_ptr< wasm_instantiated_module_interface > instantiate_module(const char *code_bytes, size_t code_size, std::vector< uint8_t >, const digest_type &code_hash, const uint8_t &vm_type, const uint8_t &vm_version) override
std::unique_ptr< wasm_instantiated_module_interface > instantiate_module(const char *code_bytes, size_t code_size, std::vector< uint8_t >, const digest_type &code_hash, const uint8_t &vm_type, const uint8_t &vm_version) override
void immediately_exit_currently_running_module() override
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
backend_t bkend(hello_wasm, ehm, &wa)
#define SYSIO_INJECTED_MODULE_NAME
std::vector< char > bytes
std::variant< alt_bn128_error, bytes > alt_bn128_add(const bytes &op1, const bytes &op2)
std::variant< k1_recover_error, bytes > k1_recover(const bytes &signature, const bytes &digest)
std::variant< alt_bn128_error, bytes > alt_bn128_mul(const bytes &g1_point, const bytes &scalar)
std::variant< alt_bn128_error, bool > alt_bn128_pair(const bytes &g1_g2_pairs, const yield_function_t &yield)
constexpr unsigned maximum_linear_memory
constexpr unsigned maximum_call_depth
void validate(const bytes &code, const whitelisted_intrinsics_type &intrinsics)
void register_eosvm_oc(Name n)
@ configurable_wasm_limits
bool is_intrinsic_whitelisted(const whitelisted_intrinsics_type &whitelisted_intrinsics, std::string_view name)
sysio::vm::registered_host_functions< webassembly::interface, sysio::vm::execution_interface, sysio::chain::type_converter > eos_vm_host_functions_t
shared_flat_multimap< uint64_t, shared_string > whitelisted_intrinsics_type
@ self
the connection is to itself
void apply(uint64_t, uint64_t, uint64_t)
Immutable except for fc::from_variant.
std::uint32_t max_module_bytes
static constexpr bool allow_invalid_empty_local_set
static constexpr bool allow_code_after_function_end
static constexpr bool forbid_export_mutable_globals
static constexpr bool allow_zero_blocktype
std::uint32_t max_call_depth
static constexpr bool allow_u32_limits_flags
static constexpr bool allow_invalid_empty_local_set
static constexpr bool allow_u32_limits_flags
static constexpr bool allow_zero_blocktype
static constexpr bool forbid_export_mutable_globals
static constexpr bool allow_code_after_function_end
constexpr host_function_registrator(Mod mod_name, Name fn_name)
virtual const char * what() const =0
virtual const char * detail() const =0
uint32_t get_exported_function(const std::string_view str)
guarded_vector< import_entry > imports
auto & get_function_type(uint32_t index) const
static void add(const std::string &mod, const std::string &name)
static void resolve(Module &mod)
#define REGISTER_CF_HOST_FUNCTION(NAME,...)
#define REGISTER_LEGACY_HOST_FUNCTION(NAME,...)
#define REGISTER_LEGACY_CF_ONLY_HOST_FUNCTION(NAME,...)
transaction_checktime_timer & _timer
#define REGISTER_LEGACY_CF_HOST_FUNCTION(NAME,...)
#define REGISTER_HOST_FUNCTION(NAME,...)
#define REGISTER_INJECTED_HOST_FUNCTION(NAME,...)
memset(pInfo->slotDescription, ' ', 64)
memcpy((char *) pInfo->slotDescription, s, l)