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

Payment api v2 #1468

Merged
merged 10 commits into from
Jan 27, 2023
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: 18 additions & 3 deletions core/api/jrpc/value_converter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ namespace kagome::api {
inline jsonrpc::Value makeValue(const common::Buffer &);
inline jsonrpc::Value makeValue(common::BufferView);
inline jsonrpc::Value makeValue(const primitives::Extrinsic &);
inline jsonrpc::Value makeValue(const primitives::RuntimeDispatchInfo &v);
template <typename Weight>
inline jsonrpc::Value makeValue(
const primitives::RuntimeDispatchInfo<Weight> &v);
inline jsonrpc::Value makeValue(const primitives::DigestItem &);
inline jsonrpc::Value makeValue(const primitives::BlockData &);
inline jsonrpc::Value makeValue(const primitives::BlockHeader &);
Expand Down Expand Up @@ -90,6 +92,17 @@ namespace kagome::api {
return ret;
}

// TODO(Harrm): refactor to work specifically with Balance type
inline jsonrpc::Value makeValue(const primitives::Balance &val) {
jsonrpc::Value ret((*val).str());
return ret;
}

inline jsonrpc::Value makeValue(const primitives::OldWeight &val) {
jsonrpc::Value ret(static_cast<int64_t>(*val));
return ret;
}

template <typename T>
inline jsonrpc::Value makeValue(std::remove_reference_t<T> &&val) {
return makeValue(val);
Expand Down Expand Up @@ -233,11 +246,13 @@ namespace kagome::api {
return data;
}

inline jsonrpc::Value makeValue(const primitives::RuntimeDispatchInfo &v) {
template <typename Weight>
inline jsonrpc::Value makeValue(
const primitives::RuntimeDispatchInfo<Weight> &v) {
jStruct res;
res["weight"] = makeValue(v.weight);
res["partialFee"] = makeValue(v.partial_fee);
using Class = primitives::RuntimeDispatchInfo::DispatchClass;
using Class = primitives::DispatchClass;
switch (v.dispatch_class) {
case Class::Normal:
res["class"] = "normal";
Expand Down
1 change: 0 additions & 1 deletion core/api/service/author/author_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ namespace kagome::api {
using Hash256 = common::Hash256;
using Buffer = common::Buffer;
using Extrinsic = primitives::Extrinsic;
using Metadata = primitives::Metadata;
using SubscriptionId = primitives::SubscriptionId;
using ExtrinsicKey = primitives::ExtrinsicKey;
using TransactionSource = primitives::TransactionSource;
Expand Down
8 changes: 4 additions & 4 deletions core/api/service/payment/impl/payment_api_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ namespace kagome::api {
BOOST_ASSERT(block_tree_);
}

outcome::result<primitives::RuntimeDispatchInfo> PaymentApiImpl::queryInfo(
const primitives::Extrinsic &extrinsic,
uint32_t len,
OptionalHashRef at) const {
outcome::result<primitives::RuntimeDispatchInfo<primitives::OldWeight>>
PaymentApiImpl::queryInfo(const primitives::Extrinsic &extrinsic,
uint32_t len,
OptionalHashRef at) const {
if (at.has_value()) {
return api_->query_info(at.value(), extrinsic, len);
}
Expand Down
8 changes: 4 additions & 4 deletions core/api/service/payment/impl/payment_api_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ namespace kagome::api {
std::shared_ptr<const blockchain::BlockTree> block_tree);
~PaymentApiImpl() override = default;

outcome::result<primitives::RuntimeDispatchInfo> queryInfo(
const primitives::Extrinsic &extrinsic,
uint32_t len,
OptionalHashRef at) const override;
outcome::result<primitives::RuntimeDispatchInfo<primitives::OldWeight>>
queryInfo(const primitives::Extrinsic &extrinsic,
uint32_t len,
OptionalHashRef at) const override;

private:
std::shared_ptr<runtime::TransactionPaymentApi> api_;
Expand Down
9 changes: 5 additions & 4 deletions core/api/service/payment/payment_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ namespace kagome::api {

virtual ~PaymentApi() = default;

virtual outcome::result<primitives::RuntimeDispatchInfo> queryInfo(
const primitives::Extrinsic &extrinsic,
uint32_t len,
OptionalHashRef at) const = 0;
virtual outcome::result<
primitives::RuntimeDispatchInfo<primitives::OldWeight>>
queryInfo(const primitives::Extrinsic &extrinsic,
uint32_t len,
OptionalHashRef at) const = 0;
};

} // namespace kagome::api
Expand Down
16 changes: 9 additions & 7 deletions core/api/service/payment/requests/query_info.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,31 @@
namespace kagome::api::payment::request {

class QueryInfo final
: public details::RequestType<primitives::RuntimeDispatchInfo,
std::string,
std::string> {
: public details::RequestType<
primitives::RuntimeDispatchInfo<primitives::OldWeight>,
std::string,
std::string> {
public:
explicit QueryInfo(std::shared_ptr<PaymentApi> api) : api_(std::move(api)) {
BOOST_ASSERT(api_);
};

outcome::result<primitives::RuntimeDispatchInfo> execute() override {
outcome::result<primitives::RuntimeDispatchInfo<primitives::OldWeight>>
execute() override {
auto ext_hex = getParam<0>();
OUTCOME_TRY(ext_bytes, common::unhexWith0x(ext_hex));
auto len = ext_bytes.size();

OUTCOME_TRY(extrinsic, scale::decode<primitives::Extrinsic>(ext_bytes));

auto at_hex = getParam<1>();
if (at_hex.empty()) {
return api_->queryInfo(extrinsic, len, std::nullopt);
return api_->queryInfo(extrinsic, ext_bytes.size(), std::nullopt);
}
common::Hash256 at_hash;
OUTCOME_TRY(at, common::unhexWith0x(at_hex));
BOOST_ASSERT(at.size() == common::Hash256::size());
std::copy_n(at.cbegin(), common::Hash256::size(), at_hash.begin());
return api_->queryInfo(extrinsic, len, std::cref(at_hash));
return api_->queryInfo(extrinsic, ext_bytes.size(), std::cref(at_hash));
}

private:
Expand Down
4 changes: 2 additions & 2 deletions core/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ target_link_libraries(fd_limit
)

add_library(mp_utils
mp_utils.cpp
mp_utils.hpp
int_serialization.cpp
int_serialization.hpp
)
target_link_libraries(mp_utils
Boost::boost
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include "common/mp_utils.hpp"
#include "common/int_serialization.hpp"

#include <gsl/gsl_util>

Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion core/crypto/sr25519_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extern "C" {
#include <gsl/span>

#include "common/blob.hpp"
#include "common/mp_utils.hpp"
#include "common/int_serialization.hpp"
#include "scale/tie.hpp"

namespace kagome::crypto {
Expand Down
2 changes: 1 addition & 1 deletion core/crypto/vrf/vrf_provider_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include <gsl/span>

#include "common/mp_utils.hpp"
#include "common/int_serialization.hpp"

namespace kagome::crypto {
namespace vrf_constants = constants::sr25519::vrf;
Expand Down
5 changes: 0 additions & 5 deletions core/primitives/author_api_primitives.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ namespace kagome::primitives {
};
// TODO(yuraz): PRE-221 investigate and implement Session primitive

/**
* @brief Metadata primitive
*/
using Metadata = std::optional<std::shared_ptr<Session>>;

/**
* @brief ExtrinsicKey is used as a key to search extrinsic
*/
Expand Down
2 changes: 1 addition & 1 deletion core/primitives/inherent_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::primitives, InherentDataError, e) {
case E::IDENTIFIER_DOES_NOT_EXIST:
return "This identifier does not exist";
}
return "Unknow error";
return "Unknown error";
}

namespace kagome::primitives {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
#include <vector>

namespace kagome::primitives {

/**
* Polkadot primitive, which is opaque representation of RuntimeMetadata
*/
using OpaqueMetadata = std::vector<uint8_t>;

} // namespace kagome::primitives

#endif // KAGOME_CORE_PRIMITIVES_OPAQUE_METADATA_HPP
111 changes: 69 additions & 42 deletions core/primitives/runtime_dispatch_info.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,82 @@
#ifndef KAGOME_RUNTIME_DISPATCH_INFO_HPP
#define KAGOME_RUNTIME_DISPATCH_INFO_HPP

#include <scale/scale.hpp>
#include "common/unused.hpp"
#include "scale/big_fixed_integers.hpp"

namespace kagome::primitives {

/** Information related to a dispatchable's class, weight, and fee that can be
// obsolete weight format used in TransactionPayment API versions less than 2
using OldWeight = scale::Compact<uint64_t>;

struct Weight {
SCALE_TIE(2);
Weight() = default;

explicit Weight(OldWeight w) : ref_time{w}, proof_size{0} {}

Weight(uint64_t ref_time, uint64_t proof_size)
: ref_time{ref_time}, proof_size{proof_size} {}

// The weight of computational time used based on some reference hardware.
scale::Compact<uint64_t> ref_time;
// The weight of storage space used by proof of validity.
scale::Compact<uint64_t> proof_size;
};

// for some reason encoded as variant in substrate, thus custom encode/decode
// operators
enum class DispatchClass : uint8_t {
Normal,
Operational,
/* A mandatory dispatch. These kinds of dispatch are always included
* regardless of their weight, therefore it is critical that they are
* separately validated to ensure that a malicious validator cannot craft
* a valid but impossibly heavy block. Usually this just means ensuring
* that the extrinsic can only be included once and that it is always very
* light.
*
* Do *NOT* use it for extrinsics that can be heavy.
*
* The only real use case for this is inherent extrinsics that are
* required to execute in a block for the block to be valid, and it solves
* the issue in the case that the block initialization is sufficiently
* heavy to mean that those inherents do not fit into the block.
* Essentially, we assume that in these exceptional circumstances, it is
* better to allow an overweight block to be created than to not allow any
* block at all to be created.
*/
Mandatory
};

template <typename Stream,
typename = std::enable_if_t<Stream::is_decoder_stream>>
Stream &operator>>(Stream &stream, DispatchClass &dispatch_class) {
std::ignore = stream.nextByte();
uint8_t dispatch_class_byte;
stream >> dispatch_class_byte;
dispatch_class = static_cast<DispatchClass>(dispatch_class_byte);
return stream;
}

template <typename Stream,
typename = std::enable_if_t<Stream::is_decoder_stream>>
Stream &operator<<(Stream &stream, DispatchClass dispatch_class) {
return stream << uint8_t{0} << dispatch_class;
}

struct Balance : public scale::Fixed<scale::uint128_t> {};

/** Information related to a dispatchable class, weight, and fee that can be
* queried from the runtime.
*/
template <typename Weight>
struct RuntimeDispatchInfo {
using Weight = uint64_t;
using Balance = uint32_t;
SCALE_TIE(3)

Weight weight;

enum class DispatchClass {
Normal,
Operational,
/* A mandatory dispatch. These kinds of dispatch are always included
* regardless of their weight, therefore it is critical that they are
* separately validated to ensure that a malicious validator cannot craft
* a valid but impossibly heavy block. Usually this just means ensuring
* that the extrinsic can only be included once and that it is always very
* light.
*
* Do *NOT* use it for extrinsics that can be heavy.
*
* The only real use case for this is inherent extrinsics that are
* required to execute in a block for the block to be valid, and it solves
* the issue in the case that the block initialization is sufficiently
* heavy to mean that those inherents do not fit into the block.
* Essentially, we assume that in these exceptional circumstances, it is
* better to allow an overweight block to be created than to not allow any
* block at all to be created.
*/
Mandatory
} dispatch_class;
DispatchClass dispatch_class;

/** The inclusion fee of this dispatch. This does not include a tip or
* anything else that depends on the signature (i.e. depends on a
Expand All @@ -47,22 +90,6 @@ namespace kagome::primitives {
Balance partial_fee;
};

template <class Stream,
typename = std::enable_if_t<Stream::is_encoder_stream>>
Stream &operator<<(Stream &s, const RuntimeDispatchInfo &v) {
return s << v.weight << v.dispatch_class << v.partial_fee;
}

template <class Stream,
typename = std::enable_if_t<Stream::is_decoder_stream>>
Stream &operator>>(Stream &s, RuntimeDispatchInfo &v) {
uint8_t dispatch_class;
s >> v.weight >> dispatch_class >> v.partial_fee;
v.dispatch_class =
static_cast<RuntimeDispatchInfo::DispatchClass>(dispatch_class);
return s;
}

} // namespace kagome::primitives

#endif // KAGOME_RUNTIME_DISPATCH_INFO_HPP
2 changes: 1 addition & 1 deletion core/runtime/binaryen/module/module_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <binaryen/wasm-binary.h>
#include <binaryen/wasm-interpreter.h>

#include "common/mp_utils.hpp"
#include "common/int_serialization.hpp"
#include "runtime/binaryen/binaryen_memory_provider.hpp"
#include "runtime/binaryen/instance_environment_factory.hpp"
#include "runtime/binaryen/module/module_instance_impl.hpp"
Expand Down
6 changes: 4 additions & 2 deletions core/runtime/common/executor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,10 @@ namespace kagome::runtime {
if (s.hasMore(1)) {
SL_ERROR(logger_,
"Runtime API call result size exceeds the size of the "
"type to initialize {}",
typeid(Result).name());
"type to initialize {} (read {}, total size {})",
typeid(Result).name(),
s.currentIndex(),
s.span().size_bytes());
return outcome::failure(std::errc::illegal_byte_sequence);
}
return outcome::success(std::move(t));
Expand Down
Loading