Skip to content

Commit

Permalink
Payment api v2 (#1468)
Browse files Browse the repository at this point in the history
* Add support of payment api v2

* Fix runtime dispatch info encoding

* Add wrappers to specify integer encoding - Fixed and Compact
  • Loading branch information
Harrm authored Jan 27, 2023
1 parent 5b40254 commit aa34f26
Show file tree
Hide file tree
Showing 33 changed files with 482 additions and 114 deletions.
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

0 comments on commit aa34f26

Please sign in to comment.