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

read_embedded_version #2141

Merged
merged 8 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions core/injector/calculate_genesis_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
#pragma once

#include "application/chain_spec.hpp"
#include "runtime/common/uncompress_code_if_needed.hpp"
#include "runtime/heap_alloc_strategy_heappages.hpp"
#include "runtime/runtime_api/impl/core.hpp"
#include "runtime/wabt/version.hpp"
#include "storage/predefined_keys.hpp"
#include "storage/trie/polkadot_trie/polkadot_trie_impl.hpp"
#include "storage/trie/serialization/trie_serializer.hpp"
Expand All @@ -30,14 +32,17 @@ namespace kagome::injector {
};
auto top_trie = trie_from(chain_spec.getGenesisTopSection());
OUTCOME_TRY(code, top_trie->get(storage::kRuntimeCodeKey));

runtime::MemoryLimits config;
BOOST_OUTCOME_TRY(config.heap_alloc_strategy,
heapAllocStrategyHeappagesDefault(*top_trie));
OUTCOME_TRY(
runtime_version,
runtime::callCoreVersion(module_factory, code, config, runtime_cache));
auto version = storage::trie::StateVersion{runtime_version.state_version};
BOOST_OUTCOME_TRY(code, runtime::uncompressCodeIfNeeded(code));
OUTCOME_TRY(runtime_version, runtime::readEmbeddedVersion(code));
if (not runtime_version) {
runtime::MemoryLimits config;
BOOST_OUTCOME_TRY(config.heap_alloc_strategy,
heapAllocStrategyHeappagesDefault(*top_trie));
BOOST_OUTCOME_TRY(runtime_version,
runtime::callCoreVersion(
module_factory, code, config, runtime_cache));
}
auto version = storage::trie::StateVersion{runtime_version->state_version};
std::vector<std::shared_ptr<storage::trie::PolkadotTrie>> child_tries;
for (auto &[child, kv] : chain_spec.getGenesisChildrenDefaultSection()) {
child_tries.emplace_back(trie_from(kv));
Expand Down
32 changes: 32 additions & 0 deletions core/primitives/version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,35 @@ namespace kagome::primitives::detail {
}

} // namespace kagome::primitives::detail

namespace kagome::primitives {
outcome::result<Version> Version::decode(
scale::ScaleDecoderStream &s, std::optional<uint32_t> core_version) {
Version v;
auto t = std::tie(v.spec_name,
v.impl_name,
v.authoring_version,
v.spec_version,
v.impl_version,
v.apis);
OUTCOME_TRY(scale::decode(s, t));

if (not core_version) {
core_version = detail::coreVersionFromApis(v.apis);
}
// old Kusama runtimes do not contain transaction_version and
// state_version
// https://github.com/paritytech/substrate/blob/1b3ddae9dec6e7653b5d6ef0179df1af831f46f0/primitives/version/src/lib.rs#L238
if (core_version and *core_version >= 3) {
OUTCOME_TRY(scale::decode(s, v.transaction_version));
} else {
v.transaction_version = 1;
}
if (core_version and *core_version >= 4) {
OUTCOME_TRY(scale::decode(s, v.state_version));
} else {
v.state_version = 0;
}
return v;
}
} // namespace kagome::primitives
37 changes: 16 additions & 21 deletions core/primitives/version.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,20 @@ namespace kagome::primitives {
and state_version == rhs.state_version;
}

bool operator!=(const Version &rhs) const {
return !operator==(rhs);
}
/**
* `Decode` while giving a "version hint"
* There exists multiple versions of [`RuntimeVersion`] and they are
* versioned using the `Core` runtime api:
* - `Core` version < 3 is a runtime version without a transaction version
* and state version.
* - `Core` version 3 is a runtime version without a state version.
* - `Core` version 4 is the latest runtime version.
* `core_version` hint is used by `readEmbeddedVersion`, because
* `Version.apis` is stored separately from other `Version` fields.
* https://github.com/paritytech/polkadot-sdk/blob/aaf0443591b134a0da217d575161872796e75059/substrate/primitives/version/src/lib.rs#L242
*/
static outcome::result<Version> decode(
turuslan marked this conversation as resolved.
Show resolved Hide resolved
scale::ScaleDecoderStream &s, std::optional<uint32_t> core_version);
};

namespace detail {
Expand Down Expand Up @@ -130,24 +141,8 @@ namespace kagome::primitives {
template <class Stream,
typename = std::enable_if_t<Stream::is_decoder_stream>>
Stream &operator>>(Stream &s, Version &v) {
s >> v.spec_name >> v.impl_name >> v.authoring_version >> v.spec_version
>> v.impl_version >> v.apis;

auto core_version = detail::coreVersionFromApis(v.apis);
// old Kusama runtimes do not contain transaction_version and state_version
// https://github.com/paritytech/substrate/blob/1b3ddae9dec6e7653b5d6ef0179df1af831f46f0/primitives/version/src/lib.rs#L238
if (core_version.has_value() and core_version.value() >= 3
and s.hasMore(sizeof(v.transaction_version))) {
s >> v.transaction_version;
} else {
v.transaction_version = 1;
}
if (core_version.has_value() and core_version.value() >= 4
and s.hasMore(sizeof(v.state_version))) {
s >> v.state_version;
} else {
v.state_version = 0;
}
// `.value()` may throw, `scale::decode` will catch that
v = Version::decode(s, std::nullopt).value();
turuslan marked this conversation as resolved.
Show resolved Hide resolved
return s;
}
} // namespace kagome::primitives
Empty file.
2 changes: 2 additions & 0 deletions core/runtime/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,7 @@ add_library(core_api_factory core_api_factory_impl.cpp)
target_link_libraries(core_api_factory
core_api
outcome
uncompress_if_needed
wasm_instrument
)
kagome_install(core_api_factory)
19 changes: 19 additions & 0 deletions core/runtime/common/core_api_factory_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,25 @@

#include "runtime/common/runtime_properties_cache_impl.hpp"
#include "runtime/common/trie_storage_provider_impl.hpp"
#include "runtime/common/uncompress_code_if_needed.hpp"
#include "runtime/module_repository.hpp"
#include "runtime/runtime_api/impl/core.hpp"
#include "runtime/runtime_context.hpp"
#include "runtime/wabt/version.hpp"

namespace kagome::runtime {
using primitives::Version;
class GetVersion : public RestrictedCore {
public:
GetVersion(const Version &version) : version_{version} {}

outcome::result<Version> version() {
return version_;
}

private:
Version version_;
};

CoreApiFactoryImpl::CoreApiFactoryImpl(
std::shared_ptr<const ModuleFactory> module_factory)
Expand All @@ -23,6 +37,11 @@ namespace kagome::runtime {
outcome::result<std::unique_ptr<RestrictedCore>> CoreApiFactoryImpl::make(
std::shared_ptr<const crypto::Hasher> hasher,
const std::vector<uint8_t> &runtime_code) const {
OUTCOME_TRY(code, uncompressCodeIfNeeded(runtime_code));
OUTCOME_TRY(version, readEmbeddedVersion(code));
if (version) {
return std::make_unique<GetVersion>(*version);
}
OUTCOME_TRY(
ctx,
RuntimeContextFactory::fromCode(*module_factory_, runtime_code, {}));
Expand Down
42 changes: 31 additions & 11 deletions core/runtime/common/module_repository_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@

#include "runtime/common/module_repository_impl.hpp"

#include "blockchain/block_header_repository.hpp"
#include "log/profiling_logger.hpp"
#include "runtime/common/runtime_instances_pool.hpp"
#include "runtime/common/uncompress_code_if_needed.hpp"
#include "runtime/heap_alloc_strategy_heappages.hpp"
#include "runtime/instance_environment.hpp"
#include "runtime/module.hpp"
#include "runtime/module_factory.hpp"
#include "runtime/module_instance.hpp"
#include "runtime/runtime_code_provider.hpp"
#include "runtime/runtime_upgrade_tracker.hpp"
#include "runtime/wabt/version.hpp"
#include "storage/trie/trie_storage.hpp"

namespace kagome::runtime {
Expand All @@ -24,12 +27,15 @@ namespace kagome::runtime {
ModuleRepositoryImpl::ModuleRepositoryImpl(
std::shared_ptr<RuntimeInstancesPool> runtime_instances_pool,
std::shared_ptr<crypto::Hasher> hasher,
std::shared_ptr<blockchain::BlockHeaderRepository>
block_header_repository,
std::shared_ptr<RuntimeUpgradeTracker> runtime_upgrade_tracker,
std::shared_ptr<storage::trie::TrieStorage> trie_storage,
std::shared_ptr<const ModuleFactory> module_factory,
std::shared_ptr<const RuntimeCodeProvider> code_provider)
: runtime_instances_pool_{std::move(runtime_instances_pool)},
hasher_{std::move(hasher)},
block_header_repository_{std::move(block_header_repository)},
runtime_upgrade_tracker_{std::move(runtime_upgrade_tracker)},
trie_storage_{std::move(trie_storage)},
module_factory_{std::move(module_factory)},
Expand All @@ -45,6 +51,22 @@ namespace kagome::runtime {
ModuleRepositoryImpl::getInstanceAt(
const primitives::BlockInfo &block,
const storage::trie::RootHash &storage_state) {
OUTCOME_TRY(item, codeAt(block, storage_state));
return runtime_instances_pool_->instantiateFromCode(
item.hash, *item.code, {item.config});
}

outcome::result<std::optional<primitives::Version>>
ModuleRepositoryImpl::embeddedVersion(
const primitives::BlockHash &block_hash) {
OUTCOME_TRY(header, block_header_repository_->getBlockHeader(block_hash));
OUTCOME_TRY(item, codeAt(header.blockInfo(), header.state_root));
return item.version;
}

outcome::result<ModuleRepositoryImpl::Item> ModuleRepositoryImpl::codeAt(
const primitives::BlockInfo &block,
const storage::trie::RootHash &storage_state) {
KAGOME_PROFILE_START(code_retrieval)
OUTCOME_TRY(state, runtime_upgrade_tracker_->getLastCodeUpdateState(block));
KAGOME_PROFILE_END(code_retrieval)
Expand All @@ -55,24 +77,22 @@ namespace kagome::runtime {
if (auto r = cache_.get(state)) {
item = r->get();
} else {
auto code = code_provider_->getCodeAt(state);
if (not code.has_value()) {
code = code_provider_->getCodeAt(storage_state);
auto code_res = code_provider_->getCodeAt(state);
if (not code_res) {
code_res = code_provider_->getCodeAt(storage_state);
}
BOOST_OUTCOME_TRY(item.code, std::move(code));
item.hash = hasher_->blake2b_256(*item.code);
auto &code_zstd = *code_res.value();
item.hash = hasher_->blake2b_256(code_zstd);
OUTCOME_TRY(code, uncompressCodeIfNeeded(code_zstd));
item.code = std::make_shared<Buffer>(code);
BOOST_OUTCOME_TRY(item.version, readEmbeddedVersion(code));
OUTCOME_TRY(batch, trie_storage_->getEphemeralBatchAt(storage_state));
BOOST_OUTCOME_TRY(item.config.heap_alloc_strategy,
heapAllocStrategyHeappagesDefault(*batch));
cache_.put(state, item);
}
return outcome::success();
});
OUTCOME_TRY(runtime_instance,
runtime_instances_pool_->instantiateFromCode(
item.hash, *item.code, {item.config}));
KAGOME_PROFILE_END(module_retrieval)

return runtime_instance;
return item;
}
} // namespace kagome::runtime
15 changes: 15 additions & 0 deletions core/runtime/common/module_repository_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
#include "utils/lru.hpp"
#include "utils/safe_object.hpp"

namespace kagome::blockchain {
class BlockHeaderRepository;
} // namespace kagome::blockchain

namespace kagome::crypto {
class Hasher;
} // namespace kagome::crypto
Expand All @@ -34,6 +38,8 @@ namespace kagome::runtime {
ModuleRepositoryImpl(
std::shared_ptr<RuntimeInstancesPool> runtime_instances_pool,
std::shared_ptr<crypto::Hasher> hasher,
std::shared_ptr<blockchain::BlockHeaderRepository>
block_header_repository,
std::shared_ptr<RuntimeUpgradeTracker> runtime_upgrade_tracker,
std::shared_ptr<storage::trie::TrieStorage> trie_storage,
std::shared_ptr<const ModuleFactory> module_factory,
Expand All @@ -43,14 +49,23 @@ namespace kagome::runtime {
const primitives::BlockInfo &block,
const storage::trie::RootHash &state) override;

outcome::result<std::optional<primitives::Version>> embeddedVersion(
const primitives::BlockHash &block_hash) override;

private:
struct Item {
common::Hash256 hash;
std::shared_ptr<const common::Buffer> code;
std::optional<primitives::Version> version;
MemoryLimits config;
};

outcome::result<Item> codeAt(const primitives::BlockInfo &block,
const storage::trie::RootHash &storage_state);

std::shared_ptr<RuntimeInstancesPool> runtime_instances_pool_;
std::shared_ptr<crypto::Hasher> hasher_;
std::shared_ptr<blockchain::BlockHeaderRepository> block_header_repository_;
std::shared_ptr<RuntimeUpgradeTracker> runtime_upgrade_tracker_;
std::shared_ptr<storage::trie::TrieStorage> trie_storage_;
std::shared_ptr<const ModuleFactory> module_factory_;
Expand Down
7 changes: 7 additions & 0 deletions core/runtime/common/uncompress_code_if_needed.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,11 @@ namespace kagome::runtime {

UncompressOutcome<void> uncompressCodeIfNeeded(common::BufferView buf,
common::Buffer &res);

inline UncompressOutcome<Buffer> uncompressCodeIfNeeded(
BufferView data_zstd) {
Buffer data;
OUTCOME_TRY(uncompressCodeIfNeeded(data_zstd, data));
return data;
}
} // namespace kagome::runtime
7 changes: 7 additions & 0 deletions core/runtime/module_repository.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "host_api/host_api.hpp"
#include "outcome/outcome.hpp"
#include "primitives/block_data.hpp"
#include "primitives/version.hpp"

namespace kagome::runtime {

Expand Down Expand Up @@ -41,6 +42,12 @@ namespace kagome::runtime {
virtual outcome::result<std::shared_ptr<ModuleInstance>> getInstanceAt(
const primitives::BlockInfo &block,
const storage::trie::RootHash &state_hash) = 0;

/**
* Return cached `readEmbeddedVersion` result.
*/
virtual outcome::result<std::optional<primitives::Version>> embeddedVersion(
const primitives::BlockHash &block_hash) = 0;
};

} // namespace kagome::runtime
7 changes: 7 additions & 0 deletions core/runtime/runtime_api/impl/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "log/logger.hpp"
#include "runtime/executor.hpp"
#include "runtime/module_instance.hpp"
#include "runtime/module_repository.hpp"
#include "runtime/runtime_properties_cache.hpp"

namespace kagome::runtime {
Expand Down Expand Up @@ -44,9 +45,11 @@ namespace kagome::runtime {

CoreImpl::CoreImpl(
std::shared_ptr<Executor> executor,
std::shared_ptr<ModuleRepository> module_repository,
std::shared_ptr<const blockchain::BlockHeaderRepository> header_repo,
std::shared_ptr<RuntimeUpgradeTracker> runtime_upgrade_tracker)
: executor_{std::move(executor)},
module_repository_{std::move(module_repository)},
header_repo_{std::move(header_repo)},
runtime_upgrade_tracker_{std::move(runtime_upgrade_tracker)} {
BOOST_ASSERT(executor_ != nullptr);
Expand All @@ -56,6 +59,10 @@ namespace kagome::runtime {

outcome::result<primitives::Version> CoreImpl::version(
const primitives::BlockHash &block) {
OUTCOME_TRY(version, module_repository_->embeddedVersion(block));
if (version) {
return *version;
}
return version_.call(*header_repo_,
*runtime_upgrade_tracker_,
*executor_,
Expand Down
2 changes: 2 additions & 0 deletions core/runtime/runtime_api/impl/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace kagome::runtime {
public:
CoreImpl(
std::shared_ptr<Executor> executor,
std::shared_ptr<ModuleRepository> module_repository,
std::shared_ptr<const blockchain::BlockHeaderRepository> header_repo,
std::shared_ptr<RuntimeUpgradeTracker> runtime_upgrade_tracker);

Expand All @@ -55,6 +56,7 @@ namespace kagome::runtime {

private:
std::shared_ptr<Executor> executor_;
std::shared_ptr<ModuleRepository> module_repository_;
std::shared_ptr<const blockchain::BlockHeaderRepository> header_repo_;
std::shared_ptr<RuntimeUpgradeTracker> runtime_upgrade_tracker_;

Expand Down
2 changes: 2 additions & 0 deletions core/runtime/wabt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
add_library(wasm_instrument
instrument.cpp
stack_limiter.cpp
version.cpp
)
target_link_libraries(wasm_instrument
logger
outcome
primitives
wabt::wabt
)
kagome_install(wasm_instrument)
Loading
Loading