CDT  v4.2.0
инструменты разработчика
action.hpp
См. документацию.
1
5#pragma once
6#include <cstdlib>
7#include <type_traits>
8
9#include "../../core/eosio/serialize.hpp"
10#include "../../core/eosio/datastream.hpp"
11#include "../../core/eosio/name.hpp"
12#include "../../core/eosio/fixed_bytes.hpp"
13#include "../../core/eosio/ignore.hpp"
14#include "../../core/eosio/time.hpp"
15
16namespace eosio {
17
18 namespace internal_use_do_not_use {
19 extern "C" {
20 __attribute__((eosio_wasm_import))
22
23 __attribute__((eosio_wasm_import))
25
26 __attribute__((eosio_wasm_import))
28
29 __attribute__((eosio_wasm_import))
31
32 __attribute__((eosio_wasm_import))
33 bool has_auth( uint64_t name );
34
35 __attribute__((eosio_wasm_import))
36 void require_auth2( uint64_t name, uint64_t permission );
37
38 __attribute__((eosio_wasm_import))
39 bool is_account( uint64_t name );
40
41 __attribute__((eosio_wasm_import))
42 void send_inline(char *serialized_action, size_t size);
43
44 __attribute__((eosio_wasm_import))
45 void send_context_free_inline(char *serialized_action, size_t size);
46
47 __attribute__((eosio_wasm_import))
49
50 __attribute__((eosio_wasm_import))
52
53 __attribute__((eosio_wasm_import))
55 }
56 };
57
61 checksum256 code_hash;
62 uint8_t vm_type;
63 uint8_t vm_version;
64
65 CDT_REFLECT(struct_version, code_sequence, code_hash, vm_type, vm_version);
66 EOSLIB_SERIALIZE(code_hash_result, (struct_version)(code_sequence)(code_hash)(vm_type)(vm_version));
67 };
68
93 template<typename T>
95 constexpr size_t max_stack_buffer_size = 512;
97 char* buffer = (char*)( max_stack_buffer_size < size ? malloc(size) : alloca(size) );
99 return unpack<T>( buffer, size );
100 }
101
109 inline void require_recipient( name notify_account ){
111 }
112
130 template<typename... accounts>
131 void require_recipient( name notify_account, accounts... remaining_accounts ){
133 require_recipient( remaining_accounts... );
134 }
135
142 inline void require_auth( name n ) {
144 }
145
154 }
155
162 }
163
170 inline checksum256 get_code_hash( name account, code_hash_result* full_result = nullptr ) {
171 if (full_result == nullptr)
172 full_result = (code_hash_result*)alloca(sizeof(code_hash_result));
173 constexpr size_t max_stack_buffer_size = 50;
174
175 // Packed size of this struct will virtually always be less than the struct size; always less after padding
176 auto struct_buffer_size = sizeof(code_hash_result);
177 char* struct_buffer = (char*)alloca(struct_buffer_size);
178
179 using VersionType = decltype(code_hash_result::struct_version);
180 const VersionType STRUCT_VERSION = 0;
181 auto response_size =
182 internal_use_do_not_use::get_code_hash(account.value, STRUCT_VERSION, struct_buffer, struct_buffer_size);
183 // Safety check: in this case, response size should never exceed our buffer, but just in case...
184 bool buffer_on_heap = false;
185 if (response_size > struct_buffer_size) {
186 // Slow path: allocate an adequate buffer and try again
187 // No need to deallocate struct_buffer since it was alloca'd
188 if (response_size > max_stack_buffer_size) {
189 struct_buffer = (char*)malloc(response_size);
190 buffer_on_heap = true;
191 } else {
192 struct_buffer = (char*)alloca(response_size);
193 }
194 internal_use_do_not_use::get_code_hash(account.value, STRUCT_VERSION, struct_buffer, struct_buffer_size);
195 }
196
197 check(unpack<VersionType>(struct_buffer, struct_buffer_size) == STRUCT_VERSION,
198 "Hypervisor returned unexpected code hash struct version");
199 unpack(*full_result, struct_buffer, struct_buffer_size);
200
201 // If struct_buffer is heap allocated, we must free it
202 if (buffer_on_heap)
203 free(struct_buffer);
204
205 return full_result->code_hash;
206 }
207
220 }
221
229 }
242 permission_level( name a, name p ):actor(a),permission(p){}
243
249
258
267 friend constexpr bool operator == ( const permission_level& a, const permission_level& b ) {
268 return std::tie( a.actor, a.permission ) == std::tie( b.actor, b.permission );
269 }
270
279 friend constexpr bool operator < ( const permission_level& a, const permission_level& b ) {
280 return std::tie( a.actor, a.permission ) < std::tie( b.actor, b.permission );
281 }
282
284 };
285
292 inline void require_auth( const permission_level& level ) {
293 internal_use_do_not_use::require_auth2( level.actor.value, level.permission.value );
294 }
295
302 inline bool has_auth( name n ) {
304 }
305
312 inline bool is_account( name n ) {
314 }
315
322 struct action {
327
332
336 std::vector<permission_level> authorization;
337
341 std::vector<char> data;
342
346 action() = default;
347
357 template<typename T>
358 action( const permission_level& auth, struct name a, struct name n, T&& value )
359 :account(a), name(n), authorization(1,auth), data(pack(std::forward<T>(value))) {}
360
370 template<typename T>
371 action( std::vector<permission_level> auths, struct name a, struct name n, T&& value )
372 :account(a), name(n), authorization(std::move(auths)), data(pack(std::forward<T>(value))) {}
373
375
376 EOSLIB_SERIALIZE( action, (account)(name)(authorization)(data) )
377
378
379
380
383 void send() const {
384 auto serialize = pack(*this);
385 internal_use_do_not_use::send_inline(serialize.data(), serialize.size());
386 }
387
393 void send_context_free() const {
394 eosio::check( authorization.size() == 0, "context free actions cannot have authorizations");
395 auto serialize = pack(*this);
396 internal_use_do_not_use::send_context_free_inline(serialize.data(), serialize.size());
397 }
398
405 template<typename T>
407 return unpack<T>( &data[0], data.size() );
408 }
409
410 };
411
412
413
414 namespace detail {
415
417
418 template <typename T>
419 struct unwrap { typedef T type; };
420
421 template <typename T>
422 struct unwrap<ignore<T>> { typedef T type; };
423
424 template <typename R, typename Act, typename... Args>
425 auto get_args(R(Act::*p)(Args...)) {
426 return std::tuple<std::decay_t<typename unwrap<Args>::type>...>{};
427 }
428
429 template <typename R, typename Act, typename... Args>
430 auto get_args_nounwrap(R(Act::*p)(Args...)) {
431 return std::tuple<std::decay_t<Args>...>{};
432 }
433
434 template <auto Action>
435 using deduced = decltype(get_args(Action));
436
437 template <auto Action>
438 using deduced_nounwrap = decltype(get_args_nounwrap(Action));
439
440 template <typename T>
441 struct convert { typedef T type; };
442
443 template <>
444 struct convert<const char*> { typedef std::string type; };
445
446 template <>
447 struct convert<char*> { typedef std::string type; };
448
449 template <typename T, typename U>
450 struct is_same { static constexpr bool value = std::is_convertible<T,U>::value; };
451
452 template <typename U>
453 struct is_same<bool,U> { static constexpr bool value = std::is_integral<U>::value; };
454
455 template <typename T>
456 struct is_same<T,bool> { static constexpr bool value = std::is_integral<T>::value; };
457
458 template <size_t N, size_t I, auto Arg, auto... Args>
459 struct get_nth_impl { static constexpr auto value = get_nth_impl<N,I+1,Args...>::value; };
460
461 template <size_t N, auto Arg, auto... Args>
462 struct get_nth_impl<N, N, Arg, Args...> { static constexpr auto value = Arg; };
463
464 template <size_t N, auto... Args>
465 struct get_nth { static constexpr auto value = get_nth_impl<N,0,Args...>::value; };
466
467 template <auto Action, size_t I, typename T, typename... Rest>
468 struct check_types {
469 static_assert(detail::is_same<typename convert<T>::type, typename convert<typename std::tuple_element<I, deduced<Action>>::type>::type>::value);
470 using type = check_types<Action, I+1, Rest...>;
471 static constexpr bool value = true;
472 };
473 template <auto Action, size_t I, typename T>
474 struct check_types<Action, I, T> {
475 static_assert(detail::is_same<typename convert<T>::type, typename convert<typename std::tuple_element<I, deduced<Action>>::type>::type>::value);
476 static constexpr bool value = true;
477 };
478
479 template <auto Action, typename... Ts>
480 constexpr bool type_check() {
481 static_assert(sizeof...(Ts) == std::tuple_size<deduced<Action>>::value);
482 if constexpr (sizeof...(Ts) != 0)
483 return check_types<Action, 0, Ts...>::value;
484 return true;
485 }
486
488 }
489
505 template <eosio::name::raw Name, auto Action>
507 template <typename Code>
508 constexpr action_wrapper(Code&& code, std::vector<eosio::permission_level>&& perms)
509 : code_name(std::forward<Code>(code)), permissions(std::move(perms)) {}
510
511 template <typename Code>
512 constexpr action_wrapper(Code&& code, const std::vector<eosio::permission_level>& perms)
513 : code_name(std::forward<Code>(code)), permissions(perms) {}
514
515 template <typename Code>
517 : code_name(std::forward<Code>(code)), permissions({1, std::move(perm)}) {}
518
519 template <typename Code>
520 constexpr action_wrapper(Code&& code, const eosio::permission_level& perm)
521 : code_name(std::forward<Code>(code)), permissions({1, perm}) {}
522
523 template <typename Code>
524 constexpr action_wrapper(Code&& code)
525 : code_name(std::forward<Code>(code)) {}
526
527 static constexpr eosio::name action_name = eosio::name(Name);
529 std::vector<eosio::permission_level> permissions;
530
531 static constexpr auto get_mem_ptr() {
532 return Action;
533 }
534
535 template <typename... Args>
536 action to_action(Args&&... args)const {
537 static_assert(detail::type_check<Action, Args...>());
538 return action(permissions, code_name, action_name, detail::deduced<Action>{std::forward<Args>(args)...});
539 }
540 template <typename... Args>
541 void send(Args&&... args)const {
542 to_action(std::forward<Args>(args)...).send();
543 }
544
545 template <typename... Args>
546 void send_context_free(Args&&... args)const {
547 to_action(std::forward<Args>(args)...).send_context_free();
548 }
549
550 };
551
552 template <eosio::name::raw Name, auto... Actions>
554 template <typename Code>
555 constexpr variant_action_wrapper(Code&& code, std::vector<eosio::permission_level>&& perms)
556 : code_name(std::forward<Code>(code)), permissions(std::move(perms)) {}
557
558 template <typename Code>
559 constexpr variant_action_wrapper(Code&& code, const std::vector<eosio::permission_level>& perms)
560 : code_name(std::forward<Code>(code)), permissions(perms) {}
561
562 template <typename Code>
564 : code_name(std::forward<Code>(code)), permissions({1, std::move(perm)}) {}
565
566 template <typename Code>
568 : code_name(std::forward<Code>(code)), permissions({1, perm}) {}
569
570 static constexpr eosio::name action_name = eosio::name(Name);
572 std::vector<eosio::permission_level> permissions;
573
574 template <size_t Variant>
575 static constexpr auto get_mem_ptr() {
576 return detail::get_nth<Variant, Actions...>::value;
577 }
578
579 template <size_t Variant, typename... Args>
580 action to_action(Args&&... args)const {
581 static_assert(detail::type_check<detail::get_nth<Variant, Actions...>::value, Args...>());
582 unsigned_int var = Variant;
583 return action(permissions, code_name, action_name, std::tuple_cat(std::make_tuple(var), detail::deduced<detail::get_nth<Variant, Actions...>::value>{std::forward<Args>(args)...}));
584 }
585
586
587 template <size_t Variant, typename... Args>
588 void send(Args&&... args)const {
589 to_action<Variant>(std::forward<Args>(args)...).send();
590 }
591
592 template <size_t Variant, typename... Args>
593 void send_context_free(Args&&... args) const {
594 to_action<Variant>(std::forward<Args>(args)...).send_context_free();
595 }
596
597 };
598
599 template<typename... Args>
601 std::vector<permission_level> perms,
602 std::tuple<Args...> args ) {
603 action( perms, code, act, std::move(args) ).send();
604 }
605
606 template<typename, name::raw>
608
609
610 template<typename T, name::raw Name, typename... Args>
611 struct inline_dispatcher<void(T::*)(Args...), Name> {
612 static void call(name code, const permission_level& perm, std::tuple<Args...> args) {
613 dispatch_inline(code, name(Name), std::vector<permission_level>(1, perm), std::move(args));
614 }
615 static void call(name code, std::vector<permission_level> perms, std::tuple<Args...> args) {
616 dispatch_inline(code, name(Name), std::move(perms), std::move(args));
617 }
618 };
619
620} // namespace eosio
621
622#define INLINE_ACTION_SENDER3( CONTRACT_CLASS, FUNCTION_NAME, ACTION_NAME )\
623::eosio::inline_dispatcher<decltype(&CONTRACT_CLASS::FUNCTION_NAME), ACTION_NAME>::call
624
625#define INLINE_ACTION_SENDER2( CONTRACT_CLASS, NAME )\
626INLINE_ACTION_SENDER3( CONTRACT_CLASS, NAME, ::eosio::name(#NAME) )
627
628#define INLINE_ACTION_SENDER(...) BLUEGRASS_META_OVERLOAD(INLINE_ACTION_SENDER,__VA_ARGS__)(__VA_ARGS__)
629
656#define SEND_INLINE_ACTION( CONTRACT, NAME, ... )\
657INLINE_ACTION_SENDER(std::decay_t<decltype(CONTRACT)>, NAME)( (CONTRACT).get_self(),__VA_ARGS__)