Kagome
Polkadot Runtime Engine in C++17
runtime_external_interface.cpp
Go to the documentation of this file.
1 
7 
9 #include "runtime/memory.hpp"
10 
11 namespace {
16  template <typename T>
17  auto literalMemFun() {
18  return nullptr;
19  }
20 
21  template <>
22  auto literalMemFun<int32_t>() {
23  return &wasm::Literal::geti32;
24  }
25 
26  template <>
27  auto literalMemFun<uint64_t>() {
28  return &wasm::Literal::geti64;
29  }
30 
31  template <>
32  auto literalMemFun<uint32_t>() {
33  return &wasm::Literal::geti32;
34  }
35 
40  template <typename T, typename R, auto mf, typename... Args, size_t... I>
41  wasm::Literal callInternal(T *host_api,
42  const wasm::LiteralList &arguments,
43  std::index_sequence<I...>) {
44  if constexpr (not std::is_same_v<void, R>) {
45  // invokes literalMemFun method for every literal in a list to convert
46  // wasm value into C++ value and pass it as argument
47  return wasm::Literal(
48  (host_api->*mf)((arguments.at(I).*literalMemFun<Args>())()...));
49  } else {
50  (host_api->*mf)((arguments.at(I).*literalMemFun<Args>())()...);
51  return wasm::Literal();
52  }
53  }
54 
60  template <typename T, T>
61  struct HostApiFunc;
62  template <typename T, typename R, typename... Args, R (T::*mf)(Args...)>
63  struct HostApiFunc<R (T::*)(Args...), mf> {
64  using Ret = R;
65  static const size_t size = sizeof...(Args);
66  static wasm::Literal call(T *host_api, const wasm::LiteralList &arguments) {
67  // set index for every argument
68  auto indices = std::index_sequence_for<Args...>{};
69  return callInternal<T, R, mf, Args...>(host_api, arguments, indices);
70  }
71  };
72  template <typename T, typename R, typename... Args, R (T::*mf)(Args...) const>
73  struct HostApiFunc<R (T::*)(Args...) const, mf> {
74  using Ret = R;
75  static const size_t size = sizeof...(Args);
76  static wasm::Literal call(T *host_api, const wasm::LiteralList &arguments) {
77  // set index for every argument
78  auto indices = std::index_sequence_for<Args...>{};
79  return callInternal<T, R, mf, Args...>(host_api, arguments, indices);
80  }
81  };
82 
88  template <auto mf>
89  constexpr size_t hostApiFuncArgSize() {
90  return HostApiFunc<decltype(mf), mf>::size;
91  }
92 
100  template <auto mf>
101  wasm::Literal callHostApiFunc(kagome::host_api::HostApi *host_api,
102  const wasm::LiteralList &arguments) {
103  return HostApiFunc<decltype(mf), mf>::call(host_api, arguments);
104  }
105 } // namespace
106 
114 #define REGISTER_HOST_API_FUNC(name) \
115  imports_[#name] = \
116  &importCall<&host_api::HostApi ::name> // hack to make macro call look
117  // natural by ending with ';'
118 
119 namespace kagome::runtime {
120  class TrieStorageProvider;
121 }
122 
123 namespace kagome::runtime::binaryen {
124 
125  const static wasm::Name env = "env";
131  void RuntimeExternalInterface::methodsRegistration() {
133  REGISTER_HOST_API_FUNC(ext_default_child_storage_root_version_1);
134  REGISTER_HOST_API_FUNC(ext_default_child_storage_set_version_1);
135  REGISTER_HOST_API_FUNC(ext_default_child_storage_get_version_1);
136  REGISTER_HOST_API_FUNC(ext_default_child_storage_clear_version_1);
137  REGISTER_HOST_API_FUNC(ext_default_child_storage_clear_prefix_version_1);
138  REGISTER_HOST_API_FUNC(ext_default_child_storage_next_key_version_1);
139  REGISTER_HOST_API_FUNC(ext_default_child_storage_storage_kill_version_1);
140  REGISTER_HOST_API_FUNC(ext_default_child_storage_read_version_1);
141  REGISTER_HOST_API_FUNC(ext_default_child_storage_exists_version_1);
142  REGISTER_HOST_API_FUNC(ext_logging_log_version_1);
143  REGISTER_HOST_API_FUNC(ext_logging_max_level_version_1);
144 
145  // -------------------------- crypto functions ---------------------------
146 
147  REGISTER_HOST_API_FUNC(ext_crypto_start_batch_verify_version_1);
148  REGISTER_HOST_API_FUNC(ext_crypto_finish_batch_verify_version_1);
149  REGISTER_HOST_API_FUNC(ext_crypto_ed25519_public_keys_version_1);
150  REGISTER_HOST_API_FUNC(ext_crypto_ed25519_generate_version_1);
151  REGISTER_HOST_API_FUNC(ext_crypto_ed25519_sign_version_1);
152  REGISTER_HOST_API_FUNC(ext_crypto_ed25519_verify_version_1);
153  REGISTER_HOST_API_FUNC(ext_crypto_sr25519_public_keys_version_1);
154  REGISTER_HOST_API_FUNC(ext_crypto_sr25519_generate_version_1);
155  REGISTER_HOST_API_FUNC(ext_crypto_sr25519_sign_version_1);
156  REGISTER_HOST_API_FUNC(ext_crypto_sr25519_verify_version_1);
157  REGISTER_HOST_API_FUNC(ext_crypto_sr25519_verify_version_2);
158  REGISTER_HOST_API_FUNC(ext_crypto_ecdsa_public_keys_version_1);
159  REGISTER_HOST_API_FUNC(ext_crypto_ecdsa_sign_version_1);
160  REGISTER_HOST_API_FUNC(ext_crypto_ecdsa_sign_prehashed_version_1);
161  REGISTER_HOST_API_FUNC(ext_crypto_ecdsa_generate_version_1);
162  REGISTER_HOST_API_FUNC(ext_crypto_ecdsa_verify_version_1);
163  REGISTER_HOST_API_FUNC(ext_crypto_ecdsa_verify_prehashed_version_1);
175  REGISTER_HOST_API_FUNC(ext_crypto_secp256k1_ecdsa_recover_version_1);
176  REGISTER_HOST_API_FUNC(ext_crypto_secp256k1_ecdsa_recover_version_2);
178  ext_crypto_secp256k1_ecdsa_recover_compressed_version_1);
180  ext_crypto_secp256k1_ecdsa_recover_compressed_version_2);
181 
182  // -------------------------- hashing functions --------------------------
183 
184  REGISTER_HOST_API_FUNC(ext_hashing_keccak_256_version_1);
185  REGISTER_HOST_API_FUNC(ext_hashing_sha2_256_version_1);
186  REGISTER_HOST_API_FUNC(ext_hashing_blake2_128_version_1);
187  REGISTER_HOST_API_FUNC(ext_hashing_blake2_256_version_1);
188  REGISTER_HOST_API_FUNC(ext_hashing_twox_256_version_1);
189  REGISTER_HOST_API_FUNC(ext_hashing_twox_128_version_1);
190  REGISTER_HOST_API_FUNC(ext_hashing_twox_64_version_1);
191 
192  // -------------------------- memory functions ---------------------------
193 
194  REGISTER_HOST_API_FUNC(ext_allocator_malloc_version_1);
195  REGISTER_HOST_API_FUNC(ext_allocator_free_version_1);
196 
197  // -------------------------- storage functions --------------------------
198 
199  REGISTER_HOST_API_FUNC(ext_storage_set_version_1);
200  REGISTER_HOST_API_FUNC(ext_storage_get_version_1);
201  REGISTER_HOST_API_FUNC(ext_storage_clear_version_1);
202  REGISTER_HOST_API_FUNC(ext_storage_exists_version_1);
203  REGISTER_HOST_API_FUNC(ext_storage_read_version_1);
204  REGISTER_HOST_API_FUNC(ext_storage_clear_prefix_version_1);
205  REGISTER_HOST_API_FUNC(ext_storage_clear_prefix_version_2);
206  REGISTER_HOST_API_FUNC(ext_storage_root_version_1);
207  REGISTER_HOST_API_FUNC(ext_storage_root_version_2);
208  REGISTER_HOST_API_FUNC(ext_storage_changes_root_version_1);
209  REGISTER_HOST_API_FUNC(ext_storage_next_key_version_1);
210  REGISTER_HOST_API_FUNC(ext_storage_append_version_1);
211  REGISTER_HOST_API_FUNC(ext_storage_start_transaction_version_1);
212  REGISTER_HOST_API_FUNC(ext_storage_commit_transaction_version_1);
213  REGISTER_HOST_API_FUNC(ext_storage_rollback_transaction_version_1);
214  REGISTER_HOST_API_FUNC(ext_trie_blake2_256_root_version_1);
215  REGISTER_HOST_API_FUNC(ext_trie_blake2_256_ordered_root_version_1);
216  REGISTER_HOST_API_FUNC(ext_trie_blake2_256_ordered_root_version_2);
217  REGISTER_HOST_API_FUNC(ext_misc_print_hex_version_1);
218  REGISTER_HOST_API_FUNC(ext_misc_print_num_version_1);
219  REGISTER_HOST_API_FUNC(ext_misc_print_utf8_version_1);
220  REGISTER_HOST_API_FUNC(ext_misc_runtime_version_version_1);
221 
222  // ------------------------- Offchain extension --------------------------
223 
224  REGISTER_HOST_API_FUNC(ext_offchain_is_validator_version_1);
225  REGISTER_HOST_API_FUNC(ext_offchain_submit_transaction_version_1);
226  REGISTER_HOST_API_FUNC(ext_offchain_network_state_version_1);
227  REGISTER_HOST_API_FUNC(ext_offchain_timestamp_version_1);
228  REGISTER_HOST_API_FUNC(ext_offchain_sleep_until_version_1);
229  REGISTER_HOST_API_FUNC(ext_offchain_random_seed_version_1);
230  REGISTER_HOST_API_FUNC(ext_offchain_local_storage_set_version_1);
231  REGISTER_HOST_API_FUNC(ext_offchain_local_storage_clear_version_1);
233  ext_offchain_local_storage_compare_and_set_version_1);
234  REGISTER_HOST_API_FUNC(ext_offchain_local_storage_get_version_1);
235  REGISTER_HOST_API_FUNC(ext_offchain_http_request_start_version_1);
236  REGISTER_HOST_API_FUNC(ext_offchain_http_request_add_header_version_1);
237  REGISTER_HOST_API_FUNC(ext_offchain_http_request_write_body_version_1);
238  REGISTER_HOST_API_FUNC(ext_offchain_http_response_wait_version_1);
239  REGISTER_HOST_API_FUNC(ext_offchain_http_response_headers_version_1);
240  REGISTER_HOST_API_FUNC(ext_offchain_http_response_read_body_version_1);
241  REGISTER_HOST_API_FUNC(ext_offchain_set_authorized_nodes_version_1);
242  REGISTER_HOST_API_FUNC(ext_offchain_index_set_version_1);
243  REGISTER_HOST_API_FUNC(ext_offchain_index_clear_version_1);
244  }
245 
246  RuntimeExternalInterface::RuntimeExternalInterface(
247  std::shared_ptr<host_api::HostApi> host_api)
248  : host_api_{std::move(host_api)},
249  logger_{log::createLogger("RuntimeExternalInterface", "binaryen")} {
250  memory.resize(kInitialMemorySize);
251  BOOST_ASSERT(host_api_);
253  }
254 
255  wasm::ShellExternalInterface::Memory *RuntimeExternalInterface::getMemory() {
256  return &memory;
257  }
258 
260  wasm::Function *import, wasm::LiteralList &arguments) {
261  SL_TRACE(logger_, "Call import {}", import->base);
262  if (import->module == env) {
263  auto it = imports_.find(
264  import->base.c_str(), imports_.hash_function(), imports_.key_eq());
265  if (it != imports_.end()) {
266  return it->second(*this, import, arguments);
267  }
268  }
269 
270  wasm::Fatal() << "callImport: unknown import: " << import->module.str << "."
271  << import->name.str;
272  return wasm::Literal();
273  }
274 
275  void RuntimeExternalInterface::checkArguments(std::string_view extern_name,
276  size_t expected,
277  size_t actual) {
278  if (expected != actual) {
279  logger_->error(
280  "Wrong number of arguments in {}. Expected: {}. Actual: {}",
281  extern_name,
282  expected,
283  actual);
284  throw std::runtime_error(
285  "Invocation of a Host API method with wrong number of arguments");
286  }
287  }
288 
289  template <auto mf>
292  wasm::Function *import,
293  wasm::LiteralList &arguments) {
294  this_.checkArguments(
295  import->base.c_str(), hostApiFuncArgSize<mf>(), arguments.size());
296  return callHostApiFunc<mf>(this_.host_api_.get(), arguments);
297  }
298 
299 } // namespace kagome::runtime::binaryen
wasm::Literal callImport(wasm::Function *import, wasm::LiteralList &arguments) override
#define REGISTER_HOST_API_FUNC(name)
check arg num and call HostApi method macro Aims to reduce boiler plate code and method name mentions...
void checkArguments(std::string_view extern_name, size_t expected, size_t actual)
constexpr size_t kInitialMemorySize
Definition: memory.hpp:20
boost::unordered_map< std::string, ImportFuncPtr > imports_
Logger createLogger(const std::string &tag)
Definition: logger.cpp:112
static wasm::Literal importCall(RuntimeExternalInterface &this_, wasm::Function *import, wasm::LiteralList &arguments)