Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Host API implementation and runtime updates #81

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions app/src/logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ static const std::string simple_config = R"(
- name: core
children:
- name: chain
- name: host
- name: network
- name: runner
- name: runtime
- name: utils
- name: transaction
- name: app
Expand Down
4 changes: 2 additions & 2 deletions app/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ int main(const int count, const char** args) {
connection_manager = std::make_shared<network::PeerManager>(runner, chain_spec->getBootNodes(), stop_handler);
stop_handler->add(connection_manager);

auto service = std::make_shared<plc::core::runtime::Service>(chain_spec, connection_manager, runner);
service->loadGenesisRuntime();
auto runtime_service = std::make_shared<plc::core::runtime::Service>(chain_spec, connection_manager, runner);
stop_handler->add(runtime_service);

runner->run();

Expand Down
1 change: 0 additions & 1 deletion cmake/Conan/binaryen/binaryen_plc.patch
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,3 @@ index 8c1d72085..799e14c58 100644
#ifndef NDEBUG
--
2.32.1 (Apple Git-133)

7 changes: 6 additions & 1 deletion core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ add_library(plc_core
src/utils/string_conversion.cpp
src/runtime/module.cpp
src/runtime/service.cpp
src/runtime/api.cpp)
src/runtime/api.cpp
src/runtime/external_interface.cpp
src/runtime/executor.cpp
src/runtime/memory.cpp
src/runtime/memory_allocator.cpp
src/host/api.cpp)
message(STATUS "dir = ${CMAKE_CURRENT_LIST_DIR}/src")
target_include_directories(plc_core PUBLIC "${CMAKE_CURRENT_LIST_DIR}/src")
target_link_libraries(plc_core
Expand Down
68 changes: 68 additions & 0 deletions core/src/host/api.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include "host/api.h"

#include <wasm-interpreter.h>
#include "runtime/ptr.h"

namespace plc::core::host {

Api::Api() {
m_wasm_log_level_map[soralog::Level::ERROR] = 0;
m_wasm_log_level_map[soralog::Level::WARN] = 1;
m_wasm_log_level_map[soralog::Level::INFO] = 2;
m_wasm_log_level_map[soralog::Level::VERBOSE] = 3;
m_wasm_log_level_map[soralog::Level::DEBUG] = 4;
m_wasm_log_level_map[soralog::Level::TRACE] = 5;
}

wasm::Literals Api::ext_logging_max_level_version_1(const wasm::LiteralList& arguments) {
ensureArgumentsSize(arguments.size(), 0);
return wasm::Literals({wasm::Literal(m_wasm_log_level_map[m_log->level()])});
}

wasm::Literals Api::ext_logging_log_version_1(const wasm::LiteralList& arguments) {
ensureArgumentsSize(arguments.size(), 3);
ensureArgumentsType(arguments, {wasm::Type::i32, wasm::Type::i64, wasm::Type::i64});

auto level = arguments[0].geti32();
plc::core::runtime::Ptr target(arguments[1].geti64());
plc::core::runtime::Ptr message(arguments[2].geti64());

auto it = std::find_if(m_wasm_log_level_map.begin(), m_wasm_log_level_map.end(), [level](auto kv){
return level == kv.second;
});

auto soralog_level = soralog::Level::OFF;
if (it != m_wasm_log_level_map.end()) {
soralog_level = it->first;
}
auto targetStr = m_memory->loadString(target);
auto messageStr = m_memory->loadString(message);

m_log->log(soralog_level, "{}: {}", targetStr, messageStr);

return wasm::Literals();
}

wasm::Literals Api::ext_allocator_malloc_version_1(const wasm::LiteralList& arguments) {
ensureArgumentsSize(arguments.size(), 1);
ensureArgumentsType(arguments, {wasm::Type::i32});

auto size = arguments[0].geti32();

return wasm::Literals({wasm::Literal(m_memory->allocate(size))});
}

wasm::Literals Api::ext_allocator_free_version_1(const wasm::LiteralList& arguments) {
ensureArgumentsSize(arguments.size(), 1);
ensureArgumentsType(arguments, {wasm::Type::i32});

auto ptr = arguments[0].geti32();

auto result = m_memory->deallocate(ptr);
if (!result) {
m_log->warn("Ptr {} does not point to any memory chunk in wasm memory. Nothing deallocated");
}
return wasm::Literals();
}

} //namespace plc::core::host
45 changes: 45 additions & 0 deletions core/src/host/api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include <map>

#include <boost/assert.hpp>
#include <libp2p/log/logger.hpp>
#include <literal.h>

#include "runtime/memory.h"

namespace wasm {
typedef std::vector<Literal> LiteralList;
}

namespace plc::core::host {

class Api final {
public:
Api();

void init(std::shared_ptr<plc::core::runtime::Memory> memory) {
m_memory = memory;
}

wasm::Literals ext_logging_max_level_version_1(const wasm::LiteralList& arguments);
wasm::Literals ext_logging_log_version_1(const wasm::LiteralList& arguments);
wasm::Literals ext_allocator_malloc_version_1(const wasm::LiteralList& arguments);
wasm::Literals ext_allocator_free_version_1(const wasm::LiteralList& arguments);

private:
void ensureArgumentsSize(int argsSize, int size) {
BOOST_ASSERT(argsSize == size);
}
void ensureArgumentsType(const wasm::LiteralList& arguments, const std::vector<wasm::Type> &types) {
for (auto i = 0; i < arguments.size(); ++i) {
BOOST_ASSERT(arguments[i].type == types[i]);
}
}
std::shared_ptr<plc::core::runtime::Memory> m_memory;
std::map<soralog::Level, int> m_wasm_log_level_map;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m_wasm_log_level_map looks like something constant (the map is initialized with const values in constructor in api.cpp file) - it's only searched and retrieved values.
So it could be at least const (or even maybe constexpr).

Well, it could be thought about using unordered_map as it would speed up the looking log level in ext_logging_max_level_version_1 method and possibility of element collision is none. Ordering seems also to not matter.


libp2p::log::Logger m_log = libp2p::log::createLogger("host::Api", "host");
};

} //namespace plc::core::host
14 changes: 4 additions & 10 deletions core/src/network/peer_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,6 @@
#include <libp2p/peer/impl/identity_manager_impl.hpp>
#include <libp2p/peer/impl/peer_repository_impl.hpp>
#include <libp2p/protocol_muxer/multiselect.hpp>
#include <libp2p/protocol/kademlia/impl/content_routing_table_impl.hpp>
#include <libp2p/protocol/kademlia/impl/kademlia_impl.hpp>
#include <libp2p/protocol/kademlia/impl/peer_routing_table_impl.hpp>
#include <libp2p/protocol/kademlia/impl/storage_impl.hpp>
#include <libp2p/protocol/kademlia/impl/storage_backend_default.hpp>
#include <libp2p/protocol/kademlia/impl/validator_default.hpp>
#include <libp2p/protocol/identify/identify.hpp>
#include <libp2p/protocol/ping/ping.hpp>
#include <libp2p/security/noise.hpp>
Expand Down Expand Up @@ -103,8 +97,8 @@ static constexpr size_t max_connections = 20;
PeerManager::PeerManager(std::shared_ptr<runner::ClientRunner> runner,
const std::vector<std::string>& peers,
std::shared_ptr<plc::core::StopHandler> stop_handler)
: m_stop_handler(std::move(stop_handler))
, m_runner(std::move(runner)) {
: m_stop_handler(stop_handler)
, m_runner(runner) {
initProtocols();

m_kademlia->addPeer(m_host->getPeerInfo(), true);
Expand All @@ -121,8 +115,8 @@ PeerManager::PeerManager(std::shared_ptr<runner::ClientRunner> runner,
PeerManager::PeerManager(std::shared_ptr<runner::ClientRunner> runner,
const std::vector<libp2p::multi::Multiaddress> &peers,
std::shared_ptr<plc::core::StopHandler> stop_handler)
: m_stop_handler(std::move(stop_handler))
, m_runner(std::move(runner)) {
: m_stop_handler(stop_handler)
, m_runner(runner) {
initProtocols();

m_kademlia->addPeer(m_host->getPeerInfo(), true);
Expand Down
16 changes: 11 additions & 5 deletions core/src/network/peer_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
#include <libp2p/peer/peer_id.hpp>
#include <libp2p/network/connection_manager.hpp>

#include <libp2p/protocol/kademlia/impl/content_routing_table_impl.hpp>
#include <libp2p/protocol/kademlia/impl/kademlia_impl.hpp>
#include <libp2p/protocol/kademlia/impl/peer_routing_table_impl.hpp>
#include <libp2p/protocol/kademlia/impl/storage_impl.hpp>
#include <libp2p/protocol/kademlia/impl/storage_backend_default.hpp>
#include <libp2p/protocol/kademlia/impl/validator_default.hpp>

#include "runner/client_runner.h"

namespace boost::asio {
Expand All @@ -20,10 +27,6 @@ namespace host {
} // namespace host

namespace protocol {
namespace kademlia {
class Config;
class Kademlia;
} // namespace kademlia
class Identify;
class Ping;
} // namespace protocol
Expand All @@ -43,7 +46,7 @@ namespace light2 {
class Protocol;
} // namespace light2

class PeerManager final : public Stoppable {
class PeerManager : public Stoppable {
public:
struct Config {
size_t max_peers_to_connect;
Expand All @@ -61,6 +64,9 @@ class PeerManager final : public Stoppable {
std::vector<libp2p::peer::PeerId> getPeersInfo() const;
std::shared_ptr<libp2p::host::BasicHost> getHost() const;

protected:
PeerManager() = default;

private:
enum class ConnectionState {
Disconnected,
Expand Down
5 changes: 4 additions & 1 deletion core/src/runner/client_runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

namespace plc::core::runner {

class ClientRunner final : public Stoppable {
class ClientRunner : public Stoppable {
public:
ClientRunner(std::shared_ptr<plc::core::StopHandler> stop_handler) noexcept;

Expand Down Expand Up @@ -41,6 +41,9 @@ class ClientRunner final : public Stoppable {

PeriodicTimer makePeriodicTimer(std::chrono::milliseconds interval, PeriodicTimer::Handler&& handler) const noexcept;

protected:
ClientRunner() = default;

private:
// NOTE: some libp2p methods require shared pointers to service, that's why
// we store it by shared pointer now
Expand Down
4 changes: 2 additions & 2 deletions core/src/runtime/api.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "api.h"

namespace plc::core::runtime {
Result<Ptr> Api::coreVersion() {
return m_executor->call("Core_version");
Result<Version> Api::coreVersion() {
return m_executor->call<Version>("Core_version");
}
} //namespace plc::core::runtime
3 changes: 2 additions & 1 deletion core/src/runtime/api.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#pragma once

#include "runtime/executor.h"
#include "runtime/version.h"

namespace plc::core::runtime {

class Api final {
public:
Api(std::shared_ptr<Executor> executor) : m_executor(executor) {}
Result<Ptr> coreVersion();
Result<Version> coreVersion();

private:
std::shared_ptr<Executor> m_executor;
Expand Down
10 changes: 10 additions & 0 deletions core/src/runtime/executor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "runtime/executor.h"

OUTCOME_CPP_DEFINE_CATEGORY(plc::core::runtime, Executor::Error, e) {
using E = plc::core::runtime::Executor::Error;
switch (e) {
case E::MissingReturnValue:
return "Missing return value from runtime API call!";
}
return "Unknown error";
}
62 changes: 49 additions & 13 deletions core/src/runtime/executor.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#pragma once

#include <libp2p/log/logger.hpp>
#include <scale.hpp>
#include <shell-interface.h>

#include "runtime/memory.h"
#include "runtime/ptr.h"
#include "utils/result.h"

Expand All @@ -12,28 +14,62 @@ class Executor final {
public:
Executor() = default;

void init(std::shared_ptr<wasm::ModuleInstance> module_instance) {
enum class Error {
MissingReturnValue = 1
};

void init(std::shared_ptr<wasm::ModuleInstance> module_instance,
std::shared_ptr<plc::core::runtime::Memory> memory) noexcept {
m_module_instance = module_instance;
m_memory = memory;
}

template<typename... Args>
Result<Ptr> call(std::string_view name, Args &&...args) {
//currently the passed args are ignored
// ByteBuffer encoded_args;
// if constexpr (sizeof...(args) > 0) {
// OUTCOME_TRY(res, scale::encode(std::forward<Args>(args)...));
// encoded_args.push_back(std::move(res));
// }
//store args

wasm::LiteralList arguments = {wasm::Literal{0}, wasm::Literal{0}};
template<typename R, typename... Args>
Result<R> call(std::string_view name, Args &&...args) {
wasm::LiteralList arguments;

if constexpr (sizeof...(args) > 0) {
ByteBuffer encoded_args;
OUTCOME_TRY(res, scale::encode(std::forward<Args>(args)...));
encoded_args.push_back(std::move(res));
//store args
auto ptr = m_memory->storeBytes(encoded_args);
arguments = {wasm::Literal{ptr.m_addr}, wasm::Literal{ptr.m_size}};
} else {
arguments = {wasm::Literal{0}, wasm::Literal{0}};
}
auto result = m_module_instance->callExport(wasm::Name{name.data()}, arguments);

return libp2p::outcome::success(Ptr(result[0].geti64()));
if constexpr (std::is_void_v<R>) {
return libp2p::outcome::success();
} else if (result.size() > 0) {
auto bytes = m_memory->loadBytes(Ptr(result[0].geti64()));
R t;
scale::ScaleDecoderStream s(bytes);
try {
s >> t;
// Check whether the whole byte buffer was consumed
if (s.hasMore(1)) {
m_log->error("Runtime API call result size exceeds the size of the type to initialize {}",
typeid(R).name());
return libp2p::outcome::failure(std::errc::illegal_byte_sequence);
}
return libp2p::outcome::success(std::move(t));
} catch (std::system_error &e) {
return libp2p::outcome::failure(e.code());
}
} else {
return libp2p::outcome::failure(Error::MissingReturnValue);
}
}

private:
std::shared_ptr<wasm::ModuleInstance> m_module_instance;
std::shared_ptr<plc::core::runtime::Memory> m_memory;

libp2p::log::Logger m_log = libp2p::log::createLogger("runtime::Executor", "runtime");
};

} //namespace plc::core::runtime

OUTCOME_HPP_DECLARE_ERROR(plc::core::runtime, Executor::Error);
Loading