-
Notifications
You must be signed in to change notification settings - Fork 73
/
Copy pathwasm_interface.cpp
151 lines (131 loc) · 6.54 KB
/
wasm_interface.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <eosio/chain/webassembly/interface.hpp>
#include <eosio/chain/webassembly/eos-vm.hpp>
#include <eosio/chain/wasm_interface.hpp>
#include <eosio/chain/apply_context.hpp>
#include <eosio/chain/controller.hpp>
#include <eosio/chain/transaction_context.hpp>
#include <eosio/chain/producer_schedule.hpp>
#include <eosio/chain/exceptions.hpp>
#include <boost/core/ignore_unused.hpp>
#include <eosio/chain/authorization_manager.hpp>
#include <eosio/chain/resource_limits.hpp>
#include <eosio/chain/wasm_interface_private.hpp>
#include <eosio/chain/wasm_eosio_validation.hpp>
#include <eosio/chain/wasm_eosio_injection.hpp>
#include <eosio/chain/global_property_object.hpp>
#include <eosio/chain/protocol_state_object.hpp>
#include <eosio/chain/account_object.hpp>
#include <fc/exception/exception.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/crypto/sha1.hpp>
#include <fc/io/raw.hpp>
#include <softfloat.hpp>
#include <compiler_builtins.hpp>
#include <boost/asio.hpp>
#include <fstream>
#include <string.h>
#if defined(EOSIO_EOS_VM_RUNTIME_ENABLED) || defined(EOSIO_EOS_VM_JIT_RUNTIME_ENABLED)
#include <eosio/vm/allocator.hpp>
#endif
namespace eosio { namespace chain {
wasm_interface::wasm_interface(vm_type vm, vm_oc_enable eosvmoc_tierup, const chainbase::database& d, const std::filesystem::path data_dir, const eosvmoc::config& eosvmoc_config, bool profile)
: my( new wasm_interface_impl(vm, eosvmoc_tierup, d, data_dir, eosvmoc_config, profile) ) {}
wasm_interface::~wasm_interface() {}
#ifdef EOSIO_EOS_VM_OC_RUNTIME_ENABLED
void wasm_interface::init_thread_local_data() {
if (my->eosvmoc)
my->eosvmoc->init_thread_local_data();
else if (my->wasm_runtime_time == wasm_interface::vm_type::eos_vm_oc && my->runtime_interface)
my->runtime_interface->init_thread_local_data();
}
#endif
void wasm_interface::validate(const controller& control, const bytes& code) {
const auto& pso = control.db().get<protocol_state_object>();
if (control.is_builtin_activated(builtin_protocol_feature_t::configurable_wasm_limits)) {
const auto& gpo = control.get_global_properties();
webassembly::eos_vm_runtime::validate( code, gpo.wasm_configuration, pso.whitelisted_intrinsics );
return;
}
Module module;
try {
Serialization::MemoryInputStream stream((U8*)code.data(), code.size());
WASM::serialize(stream, module);
} catch(const Serialization::FatalSerializationException& e) {
EOS_ASSERT(false, wasm_serialization_error, e.message.c_str());
} catch(const IR::ValidationException& e) {
EOS_ASSERT(false, wasm_serialization_error, e.message.c_str());
}
wasm_validations::wasm_binary_validation validator(control, module);
validator.validate();
webassembly::eos_vm_runtime::validate( code, pso.whitelisted_intrinsics );
//there are a couple opportunties for improvement here--
//Easy: Cache the Module created here so it can be reused for instantiaion
//Hard: Kick off instantiation in a separate thread at this location
}
void wasm_interface::indicate_shutting_down() {
my->is_shutting_down = true;
}
void wasm_interface::code_block_num_last_used(const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version, const uint32_t& block_num) {
my->code_block_num_last_used(code_hash, vm_type, vm_version, block_num);
}
void wasm_interface::current_lib(const uint32_t lib) {
my->current_lib(lib);
}
void wasm_interface::apply( const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version, apply_context& context ) {
if(substitute_apply && substitute_apply(code_hash, vm_type, vm_version, context))
return;
#ifdef EOSIO_EOS_VM_OC_RUNTIME_ENABLED
if(my->eosvmoc && (my->should_always_oc_tierup() || context.should_use_eos_vm_oc())) {
const chain::eosvmoc::code_descriptor* cd = nullptr;
chain::eosvmoc::code_cache_base::get_cd_failure failure = chain::eosvmoc::code_cache_base::get_cd_failure::temporary;
try {
cd = my->eosvmoc->cc.get_descriptor_for_code(code_hash, vm_version, context.control.is_write_window(), failure);
}
catch(...) {
//swallow errors here, if EOS VM OC has gone in to the weeds we shouldn't bail: continue to try and run baseline
//In the future, consider moving bits of EOS VM that can fire exceptions and such out of this call path
static bool once_is_enough;
if(!once_is_enough)
elog("EOS VM OC has encountered an unexpected failure");
once_is_enough = true;
}
if(cd) {
if (!context.is_applying_block())
tlog("${a} speculatively executing ${h} with eos vm oc", ("a", context.get_receiver())("h", code_hash));
my->eosvmoc->exec->execute(*cd, my->eosvmoc->mem, context);
return;
}
else if (context.trx_context.is_read_only()) {
if (failure == chain::eosvmoc::code_cache_base::get_cd_failure::temporary) {
EOS_ASSERT(false, ro_trx_vm_oc_compile_temporary_failure, "get_descriptor_for_code failed with temporary failure");
} else {
EOS_ASSERT(false, ro_trx_vm_oc_compile_permanent_failure, "get_descriptor_for_code failed with permanent failure");
}
}
}
#endif
my->get_instantiated_module(code_hash, vm_type, vm_version, context.trx_context)->apply(context);
}
bool wasm_interface::is_code_cached(const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version) const {
return my->is_code_cached(code_hash, vm_type, vm_version);
}
wasm_instantiated_module_interface::~wasm_instantiated_module_interface() {}
wasm_runtime_interface::~wasm_runtime_interface() {}
#ifdef EOSIO_EOS_VM_OC_RUNTIME_ENABLED
thread_local std::unique_ptr<eosvmoc::executor> wasm_interface_impl::eosvmoc_tier::exec {};
thread_local eosvmoc::memory wasm_interface_impl::eosvmoc_tier::mem{ wasm_constraints::maximum_linear_memory/wasm_constraints::wasm_page_size };
#endif
std::istream& operator>>(std::istream& in, wasm_interface::vm_type& runtime) {
std::string s;
in >> s;
if (s == "eos-vm")
runtime = eosio::chain::wasm_interface::vm_type::eos_vm;
else if (s == "eos-vm-jit")
runtime = eosio::chain::wasm_interface::vm_type::eos_vm_jit;
else if (s == "eos-vm-oc")
runtime = eosio::chain::wasm_interface::vm_type::eos_vm_oc;
else
in.setstate(std::ios_base::failbit);
return in;
}
} } /// eosio::chain