Skip to content

Commit aa34f26

Browse files
authored
Payment api v2 (#1468)
* Add support of payment api v2 * Fix runtime dispatch info encoding * Add wrappers to specify integer encoding - Fixed and Compact
1 parent 5b40254 commit aa34f26

33 files changed

+482
-114
lines changed

core/api/jrpc/value_converter.hpp

+18-3
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ namespace kagome::api {
6060
inline jsonrpc::Value makeValue(const common::Buffer &);
6161
inline jsonrpc::Value makeValue(common::BufferView);
6262
inline jsonrpc::Value makeValue(const primitives::Extrinsic &);
63-
inline jsonrpc::Value makeValue(const primitives::RuntimeDispatchInfo &v);
63+
template <typename Weight>
64+
inline jsonrpc::Value makeValue(
65+
const primitives::RuntimeDispatchInfo<Weight> &v);
6466
inline jsonrpc::Value makeValue(const primitives::DigestItem &);
6567
inline jsonrpc::Value makeValue(const primitives::BlockData &);
6668
inline jsonrpc::Value makeValue(const primitives::BlockHeader &);
@@ -90,6 +92,17 @@ namespace kagome::api {
9092
return ret;
9193
}
9294

95+
// TODO(Harrm): refactor to work specifically with Balance type
96+
inline jsonrpc::Value makeValue(const primitives::Balance &val) {
97+
jsonrpc::Value ret((*val).str());
98+
return ret;
99+
}
100+
101+
inline jsonrpc::Value makeValue(const primitives::OldWeight &val) {
102+
jsonrpc::Value ret(static_cast<int64_t>(*val));
103+
return ret;
104+
}
105+
93106
template <typename T>
94107
inline jsonrpc::Value makeValue(std::remove_reference_t<T> &&val) {
95108
return makeValue(val);
@@ -233,11 +246,13 @@ namespace kagome::api {
233246
return data;
234247
}
235248

236-
inline jsonrpc::Value makeValue(const primitives::RuntimeDispatchInfo &v) {
249+
template <typename Weight>
250+
inline jsonrpc::Value makeValue(
251+
const primitives::RuntimeDispatchInfo<Weight> &v) {
237252
jStruct res;
238253
res["weight"] = makeValue(v.weight);
239254
res["partialFee"] = makeValue(v.partial_fee);
240-
using Class = primitives::RuntimeDispatchInfo::DispatchClass;
255+
using Class = primitives::DispatchClass;
241256
switch (v.dispatch_class) {
242257
case Class::Normal:
243258
res["class"] = "normal";

core/api/service/author/author_api.hpp

-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ namespace kagome::api {
2626
using Hash256 = common::Hash256;
2727
using Buffer = common::Buffer;
2828
using Extrinsic = primitives::Extrinsic;
29-
using Metadata = primitives::Metadata;
3029
using SubscriptionId = primitives::SubscriptionId;
3130
using ExtrinsicKey = primitives::ExtrinsicKey;
3231
using TransactionSource = primitives::TransactionSource;

core/api/service/payment/impl/payment_api_impl.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ namespace kagome::api {
1919
BOOST_ASSERT(block_tree_);
2020
}
2121

22-
outcome::result<primitives::RuntimeDispatchInfo> PaymentApiImpl::queryInfo(
23-
const primitives::Extrinsic &extrinsic,
24-
uint32_t len,
25-
OptionalHashRef at) const {
22+
outcome::result<primitives::RuntimeDispatchInfo<primitives::OldWeight>>
23+
PaymentApiImpl::queryInfo(const primitives::Extrinsic &extrinsic,
24+
uint32_t len,
25+
OptionalHashRef at) const {
2626
if (at.has_value()) {
2727
return api_->query_info(at.value(), extrinsic, len);
2828
}

core/api/service/payment/impl/payment_api_impl.hpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ namespace kagome::api {
2424
std::shared_ptr<const blockchain::BlockTree> block_tree);
2525
~PaymentApiImpl() override = default;
2626

27-
outcome::result<primitives::RuntimeDispatchInfo> queryInfo(
28-
const primitives::Extrinsic &extrinsic,
29-
uint32_t len,
30-
OptionalHashRef at) const override;
27+
outcome::result<primitives::RuntimeDispatchInfo<primitives::OldWeight>>
28+
queryInfo(const primitives::Extrinsic &extrinsic,
29+
uint32_t len,
30+
OptionalHashRef at) const override;
3131

3232
private:
3333
std::shared_ptr<runtime::TransactionPaymentApi> api_;

core/api/service/payment/payment_api.hpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ namespace kagome::api {
2222

2323
virtual ~PaymentApi() = default;
2424

25-
virtual outcome::result<primitives::RuntimeDispatchInfo> queryInfo(
26-
const primitives::Extrinsic &extrinsic,
27-
uint32_t len,
28-
OptionalHashRef at) const = 0;
25+
virtual outcome::result<
26+
primitives::RuntimeDispatchInfo<primitives::OldWeight>>
27+
queryInfo(const primitives::Extrinsic &extrinsic,
28+
uint32_t len,
29+
OptionalHashRef at) const = 0;
2930
};
3031

3132
} // namespace kagome::api

core/api/service/payment/requests/query_info.hpp

+9-7
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,31 @@
1616
namespace kagome::api::payment::request {
1717

1818
class QueryInfo final
19-
: public details::RequestType<primitives::RuntimeDispatchInfo,
20-
std::string,
21-
std::string> {
19+
: public details::RequestType<
20+
primitives::RuntimeDispatchInfo<primitives::OldWeight>,
21+
std::string,
22+
std::string> {
2223
public:
2324
explicit QueryInfo(std::shared_ptr<PaymentApi> api) : api_(std::move(api)) {
2425
BOOST_ASSERT(api_);
2526
};
2627

27-
outcome::result<primitives::RuntimeDispatchInfo> execute() override {
28+
outcome::result<primitives::RuntimeDispatchInfo<primitives::OldWeight>>
29+
execute() override {
2830
auto ext_hex = getParam<0>();
2931
OUTCOME_TRY(ext_bytes, common::unhexWith0x(ext_hex));
30-
auto len = ext_bytes.size();
32+
3133
OUTCOME_TRY(extrinsic, scale::decode<primitives::Extrinsic>(ext_bytes));
3234

3335
auto at_hex = getParam<1>();
3436
if (at_hex.empty()) {
35-
return api_->queryInfo(extrinsic, len, std::nullopt);
37+
return api_->queryInfo(extrinsic, ext_bytes.size(), std::nullopt);
3638
}
3739
common::Hash256 at_hash;
3840
OUTCOME_TRY(at, common::unhexWith0x(at_hex));
3941
BOOST_ASSERT(at.size() == common::Hash256::size());
4042
std::copy_n(at.cbegin(), common::Hash256::size(), at_hash.begin());
41-
return api_->queryInfo(extrinsic, len, std::cref(at_hash));
43+
return api_->queryInfo(extrinsic, ext_bytes.size(), std::cref(at_hash));
4244
}
4345

4446
private:

core/common/CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ target_link_libraries(fd_limit
3232
)
3333

3434
add_library(mp_utils
35-
mp_utils.cpp
36-
mp_utils.hpp
35+
int_serialization.cpp
36+
int_serialization.hpp
3737
)
3838
target_link_libraries(mp_utils
3939
Boost::boost

core/common/mp_utils.cpp core/common/int_serialization.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
#include "common/mp_utils.hpp"
6+
#include "common/int_serialization.hpp"
77

88
#include <gsl/gsl_util>
99

File renamed without changes.

core/crypto/sr25519_types.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ extern "C" {
1313
#include <gsl/span>
1414

1515
#include "common/blob.hpp"
16-
#include "common/mp_utils.hpp"
16+
#include "common/int_serialization.hpp"
1717
#include "scale/tie.hpp"
1818

1919
namespace kagome::crypto {

core/crypto/vrf/vrf_provider_impl.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
#include <gsl/span>
99

10-
#include "common/mp_utils.hpp"
10+
#include "common/int_serialization.hpp"
1111

1212
namespace kagome::crypto {
1313
namespace vrf_constants = constants::sr25519::vrf;

core/primitives/author_api_primitives.hpp

-5
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ namespace kagome::primitives {
2929
};
3030
// TODO(yuraz): PRE-221 investigate and implement Session primitive
3131

32-
/**
33-
* @brief Metadata primitive
34-
*/
35-
using Metadata = std::optional<std::shared_ptr<Session>>;
36-
3732
/**
3833
* @brief ExtrinsicKey is used as a key to search extrinsic
3934
*/

core/primitives/inherent_data.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::primitives, InherentDataError, e) {
1313
case E::IDENTIFIER_DOES_NOT_EXIST:
1414
return "This identifier does not exist";
1515
}
16-
return "Unknow error";
16+
return "Unknown error";
1717
}
1818

1919
namespace kagome::primitives {

core/primitives/opaque_metadata.hpp core/primitives/metadata.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
#include <vector>
1111

1212
namespace kagome::primitives {
13+
1314
/**
1415
* Polkadot primitive, which is opaque representation of RuntimeMetadata
1516
*/
1617
using OpaqueMetadata = std::vector<uint8_t>;
18+
1719
} // namespace kagome::primitives
1820

1921
#endif // KAGOME_CORE_PRIMITIVES_OPAQUE_METADATA_HPP

core/primitives/runtime_dispatch_info.hpp

+69-42
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,82 @@
66
#ifndef KAGOME_RUNTIME_DISPATCH_INFO_HPP
77
#define KAGOME_RUNTIME_DISPATCH_INFO_HPP
88

9+
#include <scale/scale.hpp>
10+
#include "common/unused.hpp"
11+
#include "scale/big_fixed_integers.hpp"
12+
913
namespace kagome::primitives {
1014

11-
/** Information related to a dispatchable's class, weight, and fee that can be
15+
// obsolete weight format used in TransactionPayment API versions less than 2
16+
using OldWeight = scale::Compact<uint64_t>;
17+
18+
struct Weight {
19+
SCALE_TIE(2);
20+
Weight() = default;
21+
22+
explicit Weight(OldWeight w) : ref_time{w}, proof_size{0} {}
23+
24+
Weight(uint64_t ref_time, uint64_t proof_size)
25+
: ref_time{ref_time}, proof_size{proof_size} {}
26+
27+
// The weight of computational time used based on some reference hardware.
28+
scale::Compact<uint64_t> ref_time;
29+
// The weight of storage space used by proof of validity.
30+
scale::Compact<uint64_t> proof_size;
31+
};
32+
33+
// for some reason encoded as variant in substrate, thus custom encode/decode
34+
// operators
35+
enum class DispatchClass : uint8_t {
36+
Normal,
37+
Operational,
38+
/* A mandatory dispatch. These kinds of dispatch are always included
39+
* regardless of their weight, therefore it is critical that they are
40+
* separately validated to ensure that a malicious validator cannot craft
41+
* a valid but impossibly heavy block. Usually this just means ensuring
42+
* that the extrinsic can only be included once and that it is always very
43+
* light.
44+
*
45+
* Do *NOT* use it for extrinsics that can be heavy.
46+
*
47+
* The only real use case for this is inherent extrinsics that are
48+
* required to execute in a block for the block to be valid, and it solves
49+
* the issue in the case that the block initialization is sufficiently
50+
* heavy to mean that those inherents do not fit into the block.
51+
* Essentially, we assume that in these exceptional circumstances, it is
52+
* better to allow an overweight block to be created than to not allow any
53+
* block at all to be created.
54+
*/
55+
Mandatory
56+
};
57+
58+
template <typename Stream,
59+
typename = std::enable_if_t<Stream::is_decoder_stream>>
60+
Stream &operator>>(Stream &stream, DispatchClass &dispatch_class) {
61+
std::ignore = stream.nextByte();
62+
uint8_t dispatch_class_byte;
63+
stream >> dispatch_class_byte;
64+
dispatch_class = static_cast<DispatchClass>(dispatch_class_byte);
65+
return stream;
66+
}
67+
68+
template <typename Stream,
69+
typename = std::enable_if_t<Stream::is_decoder_stream>>
70+
Stream &operator<<(Stream &stream, DispatchClass dispatch_class) {
71+
return stream << uint8_t{0} << dispatch_class;
72+
}
73+
74+
struct Balance : public scale::Fixed<scale::uint128_t> {};
75+
76+
/** Information related to a dispatchable class, weight, and fee that can be
1277
* queried from the runtime.
1378
*/
79+
template <typename Weight>
1480
struct RuntimeDispatchInfo {
15-
using Weight = uint64_t;
16-
using Balance = uint32_t;
81+
SCALE_TIE(3)
1782

1883
Weight weight;
19-
20-
enum class DispatchClass {
21-
Normal,
22-
Operational,
23-
/* A mandatory dispatch. These kinds of dispatch are always included
24-
* regardless of their weight, therefore it is critical that they are
25-
* separately validated to ensure that a malicious validator cannot craft
26-
* a valid but impossibly heavy block. Usually this just means ensuring
27-
* that the extrinsic can only be included once and that it is always very
28-
* light.
29-
*
30-
* Do *NOT* use it for extrinsics that can be heavy.
31-
*
32-
* The only real use case for this is inherent extrinsics that are
33-
* required to execute in a block for the block to be valid, and it solves
34-
* the issue in the case that the block initialization is sufficiently
35-
* heavy to mean that those inherents do not fit into the block.
36-
* Essentially, we assume that in these exceptional circumstances, it is
37-
* better to allow an overweight block to be created than to not allow any
38-
* block at all to be created.
39-
*/
40-
Mandatory
41-
} dispatch_class;
84+
DispatchClass dispatch_class;
4285

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

50-
template <class Stream,
51-
typename = std::enable_if_t<Stream::is_encoder_stream>>
52-
Stream &operator<<(Stream &s, const RuntimeDispatchInfo &v) {
53-
return s << v.weight << v.dispatch_class << v.partial_fee;
54-
}
55-
56-
template <class Stream,
57-
typename = std::enable_if_t<Stream::is_decoder_stream>>
58-
Stream &operator>>(Stream &s, RuntimeDispatchInfo &v) {
59-
uint8_t dispatch_class;
60-
s >> v.weight >> dispatch_class >> v.partial_fee;
61-
v.dispatch_class =
62-
static_cast<RuntimeDispatchInfo::DispatchClass>(dispatch_class);
63-
return s;
64-
}
65-
6693
} // namespace kagome::primitives
6794

6895
#endif // KAGOME_RUNTIME_DISPATCH_INFO_HPP

core/runtime/binaryen/module/module_impl.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <binaryen/wasm-binary.h>
1111
#include <binaryen/wasm-interpreter.h>
1212

13-
#include "common/mp_utils.hpp"
13+
#include "common/int_serialization.hpp"
1414
#include "runtime/binaryen/binaryen_memory_provider.hpp"
1515
#include "runtime/binaryen/instance_environment_factory.hpp"
1616
#include "runtime/binaryen/module/module_instance_impl.hpp"

core/runtime/common/executor.hpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,10 @@ namespace kagome::runtime {
204204
if (s.hasMore(1)) {
205205
SL_ERROR(logger_,
206206
"Runtime API call result size exceeds the size of the "
207-
"type to initialize {}",
208-
typeid(Result).name());
207+
"type to initialize {} (read {}, total size {})",
208+
typeid(Result).name(),
209+
s.currentIndex(),
210+
s.span().size_bytes());
209211
return outcome::failure(std::errc::illegal_byte_sequence);
210212
}
211213
return outcome::success(std::move(t));

0 commit comments

Comments
 (0)