Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
preconditions.hpp
Go to the documentation of this file.
1#pragma once
2
6
7#include <sysio/vm/backend.hpp>
8#include <sysio/vm/host_function.hpp>
9
10namespace sysio { namespace chain { namespace webassembly {
11 namespace detail {
12 template <typename T, std::size_t A>
13 constexpr std::integral_constant<bool, A != 0> is_legacy_ptr(legacy_ptr<T, A>);
14 template <typename T>
15 constexpr std::false_type is_legacy_ptr(T);
16 template <typename T, std::size_t A>
17 constexpr std::integral_constant<bool, A != 0> is_legacy_span(legacy_span<T, A>);
18 template <typename T>
19 constexpr std::false_type is_legacy_span(T);
20
21 template<typename T>
22 inline constexpr bool is_softfloat_type_v =
23 std::is_same_v<T, float32_t> || std::is_same_v<T, float64_t> || std::is_same_v<T, float128_t>;
24
25 template<typename T>
26 inline constexpr bool is_wasm_arithmetic_type_v =
27 is_softfloat_type_v<T> || std::is_integral_v<T>;
28
29 template <typename T>
31 static constexpr bool value = std::is_same_v<float128_t, T> ||
32 std::is_same_v<null_terminated_ptr, T> ||
33 std::is_same_v<memcpy_params, T> ||
34 std::is_same_v<memcmp_params, T> ||
35 std::is_same_v<memset_params, T> ||
36 std::is_same_v<decltype(is_legacy_ptr(std::declval<T>())), std::true_type> ||
37 std::is_same_v<decltype(is_legacy_span(std::declval<T>())), std::true_type> ||
38 std::is_same_v<name, T> ||
39 std::is_arithmetic_v<T>;
40 };
41
42 template <typename T>
44 static constexpr bool value = (is_wasm_arithmetic_type_v<T> || std::is_same_v<name, T>) &&
45 !(std::is_pointer_v<T> || std::is_reference_v<T>);
46 };
47 template <typename T>
48 struct is_whitelisted_type<vm::span<T>> {
49 // Currently only a span of [const] char is allowed so there are no alignment concerns.
50 // If we wish to expand to general span<T> in the future, changes are needed in SYS VM
51 // to check proper alignment of the void* within from_wasm before constructing the span.
52 static constexpr bool value = std::is_same_v<std::remove_const_t<T>, char>;
53 };
54 template <typename T>
55 struct is_whitelisted_type<vm::argument_proxy<T*, 0>> {
57 };
58 }
59
60 template <typename T>
61 inline static constexpr bool is_whitelisted_type_v = detail::is_whitelisted_type<T>::value;
62
63 template <typename T>
64 inline static constexpr bool is_whitelisted_legacy_type_v = detail::is_whitelisted_legacy_type<T>::value;
65
66 template <typename... Ts>
67 inline static constexpr bool are_whitelisted_legacy_types_v = (... && detail::is_whitelisted_legacy_type<Ts>::value);
68
69 template <typename T, typename U>
70 inline static bool is_aliasing(const T& s1, const U& s2) {
71 std::uintptr_t a_begin = reinterpret_cast<std::uintptr_t>(s1.data());
72 std::uintptr_t a_end = a_begin + s1.size_bytes();
73
74 std::uintptr_t b_begin = reinterpret_cast<std::uintptr_t>(s2.data());
75 std::uintptr_t b_end = b_begin + s2.size_bytes();
76
77 // Aliasing iff the intersection of intervals [a_begin, a_end) and [b_begin, b_end) has non-zero size.
78
79 if (a_begin > b_begin) {
80 std::swap(a_begin, b_begin);
81 std::swap(a_end, b_end);
82 }
83
84 if (a_end <= b_begin) // intersection interval with non-zero size does not exist
85 return false;
86
87 // Intersection interval is [b_begin, std::min(a_end, b_end)).
88
89 if (std::min(a_end, b_end) == b_begin) // intersection interval has zero size
90 return false;
91
92 return true;
93 }
94
95 inline static bool is_nan( const float32_t f ) {
96 return f32_is_nan( f );
97 }
98 inline static bool is_nan( const float64_t f ) {
99 return f64_is_nan( f );
100 }
101 inline static bool is_nan( const float128_t& f ) {
102 return f128_is_nan( f );
103 }
104
105 SYS_VM_PRECONDITION(context_free_check,
106 SYS_VM_INVOKE_ONCE([&](auto&&...) {
107 SYS_ASSERT(ctx.get_host().get_context().is_context_free(), unaccessible_api, "this API may only be called from context_free apply");
108 }));
109
110 SYS_VM_PRECONDITION(context_aware_check,
111 SYS_VM_INVOKE_ONCE([&](auto&&...) {
112 SYS_ASSERT(!ctx.get_host().get_context().is_context_free(), unaccessible_api, "only context free api's can be used in this context");
113 }));
114
115 SYS_VM_PRECONDITION(privileged_check,
116 SYS_VM_INVOKE_ONCE([&](auto&&...) {
117 SYS_ASSERT(ctx.get_host().get_context().is_privileged(), unaccessible_api,
118 "${code} does not have permission to call this API", ("code", ctx.get_host().get_context().get_receiver()));
119 }));
120
121 namespace detail {
122 template<typename T>
124 return {static_cast<const char*>(val.get_original_pointer()), sizeof(T)};
125 }
126
127 template<typename T>
128 vm::span<T> to_span(const vm::span<T>& val) { return val; }
129 }
130
131 SYS_VM_PRECONDITION(core_precondition,
132 SYS_VM_INVOKE_ON_ALL(([&](auto&& arg, auto&&... rest) {
133 using namespace sysio::vm;
134 using arg_t = std::decay_t<decltype(arg)>;
135 static_assert( is_whitelisted_type_v<arg_t>, "whitelisted type violation");
136 if constexpr (is_span_type_v<arg_t> || vm::is_argument_proxy_type_v<arg_t>) {
137 sysio::vm::invoke_on<false, sysio::vm::invoke_on_all_t>([&arg](auto&& narg, auto&&... nrest) {
138 using nested_arg_t = std::decay_t<decltype(narg)>;
139 if constexpr (sysio::vm::is_span_type_v<nested_arg_t> || vm::is_argument_proxy_type_v<nested_arg_t>)
140 SYS_ASSERT(!is_aliasing(detail::to_span(arg), detail::to_span(narg)), wasm_exception, "pointers not allowed to alias");
141 }, rest...);
142 }
143 })));
144
145 template<typename T>
146 inline constexpr bool should_check_nan_v =
147 std::is_same_v<T, float32_t> || std::is_same_v<T, float64_t> || std::is_same_v<T, float128_t>;
148
149 template<typename T>
151 using type = T;
152 };
153 template<typename T, std::size_t A>
155 using type = T;
156 };
157
159 SYS_VM_INVOKE_ON_ALL([&](auto&& arg, auto&&... rest) {
160 if constexpr (should_check_nan_v<std::remove_cv_t<typename remove_argument_proxy<std::decay_t<decltype(arg)>>::type>>) {
161 SYS_ASSERT(!webassembly::is_nan(*arg), transaction_exception, "NaN is not an allowed value for a secondary key");
162 }
163 }));
164
165 SYS_VM_PRECONDITION(legacy_static_check_wl_args,
166 SYS_VM_INVOKE_ONCE([&](auto&&... args) {
167 static_assert( are_whitelisted_legacy_types_v<std::decay_t<decltype(args)>...>, "legacy whitelisted type violation");
168 }));
169
170}}} // ns sysio::chain::webassembly
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
Definition exceptions.hpp:7
void swap(picojson::value &x, picojson::value &y)
constexpr std::integral_constant< bool, A !=0 > is_legacy_ptr(legacy_ptr< T, A >)
constexpr std::integral_constant< bool, A !=0 > is_legacy_span(legacy_span< T, A >)
vm::span< const char > to_span(const vm::argument_proxy< T * > &val)
constexpr bool should_check_nan_v
key Invalid authority Invalid transaction Invalid block ID Invalid packed transaction Invalid chain ID Invalid symbol Signature type is not a currently activated type Block can not be found Unlinkable block Block does not guarantee concurrent execution without conflicts Block exhausted allowed resources Block is from the future Block is not signed by expected producer Block includes an ill formed protocol feature activation extension Block includes an ill formed additional block signature extension Error decompressing transaction Transaction should have at least one required authority Expired Transaction Invalid Reference Block Duplicate deferred transaction The transaction can not be found Transaction is too big Invalid transaction extension Transaction includes disallowed Transaction exceeded transient resource limit Account name already exists sysio_assert_message assertion failure Action can not be found Attempt to use unaccessible API Inline Action exceeds maximum size limit sysio_assert_code assertion failure uses restricted error code value action return value size too big Permission Query Exception Contract Table Query Exception Database is an unknown or unsupported version Database usage is at unsafe levels wasm_exception
key Invalid authority Invalid transaction Invalid block ID Invalid packed transaction Invalid chain ID Invalid symbol Signature type is not a currently activated type Block can not be found Unlinkable block Block does not guarantee concurrent execution without conflicts Block exhausted allowed resources Block is from the future Block is not signed by expected producer Block includes an ill formed protocol feature activation extension Block includes an ill formed additional block signature extension transaction_exception
void invoke_on(F &&func, const Args &... args)
#define T(meth, val, expected)
bool f128_is_nan(const float128_t &f)
bool f64_is_nan(const float64_t f)
bool f32_is_nan(const float32_t f)
#define SYS_VM_PRECONDITION(NAME,...)
#define SYS_VM_INVOKE_ONCE(CONDITION)
#define SYS_VM_INVOKE_ON_ALL(CONDITION)
Definition dtoa.c:306