Skip to content

Commit

Permalink
Feature/rdb burrow storage (#2065)
Browse files Browse the repository at this point in the history
* rdb burrow schema

Signed-off-by: iceseer <[email protected]>
Signed-off-by: Alexander Lednev <[email protected]>

* burrow storage

Signed-off-by: iceseer <[email protected]>
Signed-off-by: Alexander Lednev <[email protected]>

* rdb command executor

Signed-off-by: iceseer <[email protected]>
Signed-off-by: Alexander Lednev <[email protected]>

* rdb burrow spec query executor

Signed-off-by: iceseer <[email protected]>
Signed-off-by: Alexander Lednev <[email protected]>

* tests

Signed-off-by: iceseer <[email protected]>
Signed-off-by: Alexander Lednev <[email protected]>
  • Loading branch information
iceseer committed Apr 8, 2022
1 parent 7b90ec3 commit 15f54d9
Show file tree
Hide file tree
Showing 15 changed files with 895 additions and 24 deletions.
21 changes: 19 additions & 2 deletions irohad/ametsuchi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,31 @@ target_link_libraries(rocksdb_indexer
RocksDB::rocksdb
)

add_library(common_burrow_storage
impl/burrow_storage.cpp
)
target_link_libraries(common_burrow_storage
common
)

add_library(rocksdb_burrow_storage
impl/rocksdb_burrow_storage.cpp
)
target_link_libraries(rocksdb_burrow_storage
common_burrow_storage
RocksDB::rocksdb
)

target_compile_definitions(postgres_indexer
PRIVATE SOCI_USE_BOOST HAVE_BOOST
)

add_library(postgres_burrow_storage
impl/burrow_storage.cpp
impl/postgres_burrow_storage.cpp
)
target_link_libraries(postgres_burrow_storage common)
target_link_libraries(postgres_burrow_storage
common_burrow_storage
)

add_library(default_vm_call INTERFACE)
if(USE_BURROW)
Expand Down Expand Up @@ -222,6 +238,7 @@ target_link_libraries(ametsuchi
libs_files
common
postgres_burrow_storage
rocksdb_burrow_storage
postgres_options
shared_model_interfaces
shared_model_plain_backend
Expand Down
165 changes: 165 additions & 0 deletions irohad/ametsuchi/impl/rocksdb_burrow_storage.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#include "ametsuchi/impl/rocksdb_burrow_storage.hpp"

#include <cassert>
#include <optional>

#include "ametsuchi/impl/rocksdb_common.hpp"
#include "common/obj_utils.hpp"
#include "common/result.hpp"
#include "common/to_lower.hpp"

using namespace iroha::ametsuchi;
using namespace iroha::expected;

#define MAKE_LOWER_ON_STACK(name, source, sz) \
static_assert(sz > 0ull, "Unexpected size " #sz); \
assert(source.size() <= sz); \
char name##_buffer[sz]; \
auto name = toLower(source, name##_buffer);

RocksdbBurrowStorage::RocksdbBurrowStorage(
RocksDbCommon &common,
std::string_view tx_hash,
shared_model::interface::types::CommandIndexType cmd_index)
: common_(common), tx_hash_(tx_hash), cmd_index_(cmd_index) {}

Result<std::optional<std::string>, std::string>
RocksdbBurrowStorage::getAccount(std::string_view address) {
MAKE_LOWER_ON_STACK(address_lc, address, 128);
RDB_TRY_GET_VALUE_OR_STR_ERR(
opt_data,
forCallEngineAccount<kDbOperation::kGet, kDbEntry::kCanExist>(
common_, address_lc));
if (opt_data)
return expected::makeValue(std::string(opt_data->data(), opt_data->size()));

return std::nullopt;
}

Result<void, std::string> RocksdbBurrowStorage::updateAccount(
std::string_view address, std::string_view account) {
MAKE_LOWER_ON_STACK(address_lc, address, 128);
common_.valueBuffer().assign(account.data(), account.size());
RDB_ERROR_CHECK_TO_STR(
forCallEngineAccount<kDbOperation::kPut>(common_, address_lc));
return {};
}

Result<void, std::string> RocksdbBurrowStorage::removeAccount(
std::string_view address) {
MAKE_LOWER_ON_STACK(address_lc, address, 128);
RDB_ERROR_CHECK_TO_STR(
forCallEngineAccount<kDbOperation::kDel, kDbEntry::kCanExist>(
common_, address_lc));

auto const &[_, status] =
common_.filterDelete(std::numeric_limits<uint64_t>::max(),
RocksDBPort::ColumnFamilyType::kWsv,
fmtstrings::kPathEngineStorage,
address_lc);

if (!status.ok() && !status.IsNotFound())
return expected::makeError(fmt::format(
"Delete CallEngine storage with address '{}' failed.", address_lc));

return {};
}

Result<std::optional<std::string>, std::string>
RocksdbBurrowStorage::getStorage(std::string_view address,
std::string_view key) {
MAKE_LOWER_ON_STACK(address_lc, address, 128);

std::string key_lc;
toLowerAppend(key, key_lc);

RDB_TRY_GET_VALUE_OR_STR_ERR(
opt_value,
forCallEngineStorage<kDbOperation::kGet, kDbEntry::kCanExist>(
common_, address_lc, key_lc));
if (opt_value)
return expected::makeValue(
std::string(opt_value->data(), opt_value->size()));

return std::nullopt;
}

Result<void, std::string> RocksdbBurrowStorage::setStorage(
std::string_view address, std::string_view key, std::string_view value) {
MAKE_LOWER_ON_STACK(address_lc, address, 128);

std::string key_lc;
toLowerAppend(key, key_lc);

common_.valueBuffer().assign(value.data(), value.size());
RDB_ERROR_CHECK_TO_STR(
forCallEngineStorage<kDbOperation::kPut>(common_, address_lc, key_lc));
return {};
}

Result<void, std::string> RocksdbBurrowStorage::initCallId() {
if (!call_id_cache_) {
RDB_ERROR_CHECK_TO_STR(
forCallEngineCallIds<kDbOperation::kCheck, kDbEntry::kMustNotExist>(
common_, tx_hash_, cmd_index_));
RDB_TRY_GET_VALUE_OR_STR_ERR(
opt_call_id,
forCallEngineNextCallIds<kDbOperation::kGet, kDbEntry::kCanExist>(
common_));
if (opt_call_id)
call_id_cache_ = std::make_pair(*opt_call_id, 0ull);
else
call_id_cache_ = std::make_pair(0ull, 0ull);

common_.encode(call_id_cache_->first);
RDB_ERROR_CHECK_TO_STR(forCallEngineCallIds<kDbOperation::kPut>(
common_, tx_hash_, cmd_index_));

common_.encode(call_id_cache_->first + 1ull);
RDB_ERROR_CHECK_TO_STR(
forCallEngineNextCallIds<kDbOperation::kPut>(common_));
}
return {};
}

Result<void, std::string> RocksdbBurrowStorage::storeLog(
std::string_view address,
std::string_view data,
std::vector<std::string_view> topics) {
if (!call_id_cache_) {
RDB_ERROR_CHECK(initCallId());
}

uint64_t log_idx = 0ull;
RDB_TRY_GET_VALUE_OR_STR_ERR(
opt_log_idx,
forCallEngineNextLogIx<kDbOperation::kGet, kDbEntry::kCanExist>(common_));
if (opt_log_idx)
log_idx = *opt_log_idx;

common_.encode(log_idx + 1ull);
RDB_ERROR_CHECK_TO_STR(forCallEngineNextLogIx<kDbOperation::kPut>(common_));

MAKE_LOWER_ON_STACK(address_lc, address, 128);
common_.valueBuffer() = std::to_string(log_idx);
common_.valueBuffer() += '#';
common_.valueBuffer() += address_lc;
common_.valueBuffer() += '#';
common_.valueBuffer() += data;
RDB_ERROR_CHECK_TO_STR(forCallEngineLogs<kDbOperation::kPut>(
common_, call_id_cache_->first, call_id_cache_->second++));

for (uint64_t ix = 0; ix < topics.size(); ++ix) {
auto const &topic = topics[ix];
common_.valueBuffer().assign(topic.data(), topic.size());
RDB_ERROR_CHECK_TO_STR(
forCallEngineTopics<kDbOperation::kPut>(common_, log_idx, ix));
}

return {};
}
65 changes: 65 additions & 0 deletions irohad/ametsuchi/impl/rocksdb_burrow_storage.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef IROHA_RDB_BURROW_STORAGE_HPP
#define IROHA_RDB_BURROW_STORAGE_HPP

#include "ametsuchi/burrow_storage.hpp"

#include <string_view>
#include <utility>

#include "interfaces/common_objects/types.hpp"

namespace iroha::ametsuchi {
class RocksDbCommon;

class RocksdbBurrowStorage : public BurrowStorage {
public:
RocksdbBurrowStorage(
RocksDbCommon &common,
std::string_view tx_hash,
shared_model::interface::types::CommandIndexType cmd_index);

expected::Result<std::optional<std::string>, std::string> getAccount(
std::string_view address) override;

expected::Result<void, std::string> updateAccount(
std::string_view address, std::string_view account) override;

expected::Result<void, std::string> removeAccount(
std::string_view address) override;

expected::Result<std::optional<std::string>, std::string> getStorage(
std::string_view address, std::string_view key) override;

expected::Result<void, std::string> setStorage(
std::string_view address,
std::string_view key,
std::string_view value) override;

expected::Result<void, std::string> storeLog(
std::string_view address,
std::string_view data,
std::vector<std::string_view> topics) override;

std::optional<size_t> getCallId() const {
if (call_id_cache_)
return call_id_cache_->first;
return std::nullopt;
}

expected::Result<void, std::string> initCallId();

private:
RocksDbCommon &common_;
std::string_view tx_hash_;
shared_model::interface::types::CommandIndexType cmd_index_;
std::optional<std::pair<size_t, size_t>> call_id_cache_;
};

} // namespace iroha::ametsuchi

#endif // IROHA_RDB_BURROW_STORAGE_HPP
86 changes: 83 additions & 3 deletions irohad/ametsuchi/impl/rocksdb_command_executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <boost/algorithm/string.hpp>
#include <boost/variant/apply_visitor.hpp>
#include "ametsuchi/impl/executor_common.hpp"
#include "ametsuchi/impl/rocksdb_burrow_storage.hpp"
#include "ametsuchi/impl/rocksdb_specific_query_executor.hpp"
#include "ametsuchi/setting_query.hpp"
#include "ametsuchi/vm_caller.hpp"
#include "common/to_lower.hpp"
Expand All @@ -34,6 +36,7 @@
#include "interfaces/commands/set_setting_value.hpp"
#include "interfaces/commands/subtract_asset_quantity.hpp"
#include "interfaces/commands/transfer_asset.hpp"
#include "interfaces/common_objects/string_view_types.hpp"
#include "main/rdb_status.hpp"
#include "main/subscription.hpp"

Expand All @@ -49,9 +52,11 @@ using shared_model::interface::RolePermissionSet;
RocksDbCommandExecutor::RocksDbCommandExecutor(
std::shared_ptr<RocksDBContext> db_context,
std::shared_ptr<shared_model::interface::PermissionToString> perm_converter,
std::shared_ptr<RocksDbSpecificQueryExecutor> specific_query_executor,
std::optional<std::reference_wrapper<const VmCaller>> vm_caller)
: db_context_(std::move(db_context)),
perm_converter_{std::move(perm_converter)},
specific_query_executor_{std::move(specific_query_executor)},
vm_caller_{vm_caller},
db_transaction_(db_context_) {
assert(db_context_);
Expand Down Expand Up @@ -342,10 +347,85 @@ RocksDbCommandExecutor::ExecutionResult RocksDbCommandExecutor::operator()(
const shared_model::interface::CallEngine &command,
const shared_model::interface::types::AccountIdType &creator_account_id,
const std::string &tx_hash,
shared_model::interface::types::CommandIndexType /*cmd_index*/,
bool /*do_validation*/,
shared_model::interface::types::CommandIndexType cmd_index,
bool do_validation,
shared_model::interface::RolePermissionSet const &creator_permissions) {
return makeError<void>(ErrorCodes::kNoImplementation, "Not implemented");
if (!vm_caller_)
return makeError<void>(ErrorCodes::kNotConfigured,
"Engine is not configured.");

auto const &[creator_account_name, creator_domain_id] =
staticSplitId<2>(creator_account_id);

GrantablePermissionSet granted_account_permissions;
RDB_TRY_GET_VALUE(
opt_permissions,
forGrantablePermissions<kDbOperation::kGet, kDbEntry::kCanExist>(
common, creator_account_name, creator_domain_id, command.caller()));
if (opt_permissions)
granted_account_permissions = *opt_permissions;

if (do_validation)
RDB_ERROR_CHECK(checkPermissions(creator_permissions,
granted_account_permissions,
Role::kCallEngine,
Grantable::kCallEngineOnMyBehalf));

RocksdbBurrowStorage burrow_storage(common, tx_hash, cmd_index);
return vm_caller_->get()
.call(
tx_hash,
cmd_index,
shared_model::interface::types::EvmCodeHexStringView{command.input()},
command.caller(),
command.callee()
? std::optional<shared_model::interface::types::
EvmCalleeHexStringView>{command.callee()
->get()}
: std::optional<shared_model::interface::types::
EvmCalleeHexStringView>{std::nullopt},
burrow_storage,
*this,
*specific_query_executor_)
.match(
[&](const auto &value) -> RocksDbCommandExecutor::ExecutionResult {
if (!burrow_storage.getCallId())
if (auto result = burrow_storage.initCallId();
expected::hasError(result))
return makeError<void>(ErrorCodes::kNotConfigured,
"initCallId error: {}",
result.assumeError());

assert(burrow_storage.getCallId());
if (command.callee()) {
common.valueBuffer() = *command.callee();
common.valueBuffer() += '|';
if (value.value)
common.valueBuffer() += *value.value;
if (auto result = forCallEngineCallResponse<kDbOperation::kPut>(
common, *burrow_storage.getCallId());
expected::hasError(result))
return makeError<void>(
result.template assumeError().code,
"CallEngineResponse: {}",
result.template assumeError().description);
} else {
if (value.value)
common.valueBuffer() = *value.value;
if (auto result = forCallEngineDeploy<kDbOperation::kPut>(
common, *burrow_storage.getCallId());
expected::hasError(result))
return makeError<void>(
result.template assumeError().code,
"CallEngineDeploy: {}",
result.template assumeError().description);
}

return {};
},
[](auto &&error) -> RocksDbCommandExecutor::ExecutionResult {
return makeError<void>(3, "CallEngine: {}", std::move(error.error));
});
}

RocksDbCommandExecutor::ExecutionResult RocksDbCommandExecutor::operator()(
Expand Down
Loading

0 comments on commit 15f54d9

Please sign in to comment.