Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
abi_serializer.hpp
Go to the documentation of this file.
1#pragma once
6#include <utility>
8#include <fc/scoped_exit.hpp>
9
10namespace sysio { namespace chain {
11
12using std::map;
13using std::string;
14using std::function;
15using std::pair;
16using namespace fc;
17
18namespace impl {
19 struct abi_from_variant;
20 struct abi_to_variant;
21
22 struct abi_traverse_context;
23 struct abi_traverse_context_with_path;
24 struct binary_to_variant_context;
25 struct variant_to_binary_context;
26}
27
33
36
37 abi_serializer(){ configure_built_in_types(); }
38 abi_serializer( const abi_def& abi, const yield_function_t& yield );
39 [[deprecated("use the overload with yield_function_t[=create_yield_function(max_serialization_time)]")]]
40 abi_serializer( const abi_def& abi, const fc::microseconds& max_serialization_time );
41 void set_abi( const abi_def& abi, const yield_function_t& yield );
42 [[deprecated("use the overload with yield_function_t[=create_yield_function(max_serialization_time)]")]]
43 void set_abi(const abi_def& abi, const fc::microseconds& max_serialization_time);
44
46 std::string_view resolve_type(const std::string_view& t)const;
47 bool is_array(const std::string_view& type)const;
48 bool is_optional(const std::string_view& type)const;
49 bool is_type( const std::string_view& type, const yield_function_t& yield )const;
50 [[deprecated("use the overload with yield_function_t[=create_yield_function(max_serialization_time)]")]]
51 bool is_type(const std::string_view& type, const fc::microseconds& max_serialization_time)const;
52 bool is_builtin_type(const std::string_view& type)const;
53 bool is_integer(const std::string_view& type) const;
54 int get_integer_size(const std::string_view& type) const;
55 bool is_struct(const std::string_view& type)const;
56
58 std::string_view fundamental_type(const std::string_view& type)const;
59
60 const struct_def& get_struct(const std::string_view& type)const;
61
64 type_name get_action_result_type(name action_result)const;
65
66 std::optional<string> get_error_message( uint64_t error_code )const;
67
68 fc::variant binary_to_variant( const std::string_view& type, const bytes& binary, const yield_function_t& yield, bool short_path = false )const;
69 [[deprecated("use the overload with yield_function_t[=create_yield_function(max_serialization_time)]")]]
70 fc::variant binary_to_variant( const std::string_view& type, const bytes& binary, const fc::microseconds& max_serialization_time, bool short_path = false )const;
71 fc::variant binary_to_variant( const std::string_view& type, fc::datastream<const char*>& binary, const yield_function_t& yield, bool short_path = false )const;
72 [[deprecated("use the overload with yield_function_t[=create_yield_function(max_serialization_time)]")]]
73 fc::variant binary_to_variant( const std::string_view& type, fc::datastream<const char*>& binary, const fc::microseconds& max_serialization_time, bool short_path = false )const;
74
75 [[deprecated("use the overload with yield_function_t[=create_yield_function(max_serialization_time)]")]]
76 bytes variant_to_binary( const std::string_view& type, const fc::variant& var, const fc::microseconds& max_serialization_time, bool short_path = false )const;
77 bytes variant_to_binary( const std::string_view& type, const fc::variant& var, const yield_function_t& yield, bool short_path = false )const;
78 [[deprecated("use the overload with yield_function_t[=create_yield_function(max_serialization_time)]")]]
79 void variant_to_binary( const std::string_view& type, const fc::variant& var, fc::datastream<char*>& ds, const fc::microseconds& max_serialization_time, bool short_path = false )const;
80 void variant_to_binary( const std::string_view& type, const fc::variant& var, fc::datastream<char*>& ds, const yield_function_t& yield, bool short_path = false )const;
81
82 template<typename T, typename Resolver>
83 static void to_variant( const T& o, fc::variant& vo, Resolver resolver, const yield_function_t& yield );
84 template<typename T, typename Resolver>
85 [[deprecated("use the overload with yield_function_t[=create_yield_function(max_serialization_time)]")]]
86 static void to_variant( const T& o, fc::variant& vo, Resolver resolver, const fc::microseconds& max_serialization_time );
87
88 template<typename T, typename Resolver>
89 static void to_log_variant( const T& o, fc::variant& vo, Resolver resolver, const yield_function_t& yield );
90
91 template<typename T, typename Resolver>
92 static void from_variant( const fc::variant& v, T& o, Resolver resolver, const yield_function_t& yield );
93 template<typename T, typename Resolver>
94 [[deprecated("use the overload with yield_function_t[=create_yield_function(max_serialization_time)]")]]
95 static void from_variant( const fc::variant& v, T& o, Resolver resolver, const fc::microseconds& max_serialization_time );
96
97 template<typename Vec>
98 static bool is_empty_abi(const Vec& abi_vec)
99 {
100 return abi_vec.size() <= 4;
101 }
102
103 template<typename Vec>
104 static bool to_abi(const Vec& abi_vec, abi_def& abi)
105 {
106 if( !is_empty_abi(abi_vec) ) {
107 fc::datastream<const char*> ds( abi_vec.data(), abi_vec.size() );
108 fc::raw::unpack( ds, abi );
109 return true;
110 }
111 return false;
112 }
113
115 typedef std::function<void(const fc::variant&, fc::datastream<char*>&, bool, bool, const abi_serializer::yield_function_t&)> pack_function;
116
117 void add_specialized_unpack_pack( const string& name, std::pair<abi_serializer::unpack_function, abi_serializer::pack_function> unpack_pack );
118
119 static constexpr size_t max_recursion_depth = 32; // arbitrary depth to prevent infinite recursion
120
121 // create standard yield function that checks for max_serialization_time and max_recursion_depth.
122 // now() deadline caputered at time of this call
123 static yield_function_t create_yield_function(const fc::microseconds& max_serialization_time) {
125 if( max_serialization_time > fc::microseconds::maximum() - deadline.time_since_epoch() ) {
126 deadline = fc::time_point::maximum();
127 } else {
128 deadline += max_serialization_time;
129 }
130 return [max_serialization_time, deadline](size_t recursion_depth) {
131 SYS_ASSERT( recursion_depth < max_recursion_depth, abi_recursion_depth_exception,
132 "recursive definition, max_recursion_depth ${r} ", ("r", max_recursion_depth) );
133
134 SYS_ASSERT( fc::time_point::now() < deadline, abi_serialization_deadline_exception,
135 "serialization time limit ${t}us exceeded", ("t", max_serialization_time) );
136 };
137 }
138
139private:
140
141 map<type_name, type_name, std::less<>> typedefs;
142 map<type_name, struct_def, std::less<>> structs;
143 map<name,type_name> actions;
144 map<name,type_name> tables;
145 map<uint64_t, string> error_messages;
146 map<type_name, variant_def, std::less<>> variants;
147 map<name,type_name> action_results;
148
149 map<type_name, pair<unpack_function, pack_function>, std::less<>> built_in_types;
150 void configure_built_in_types();
151
152 fc::variant _binary_to_variant( const std::string_view& type, const bytes& binary, impl::binary_to_variant_context& ctx )const;
153 fc::variant _binary_to_variant( const std::string_view& type, fc::datastream<const char*>& binary, impl::binary_to_variant_context& ctx )const;
154 void _binary_to_variant( const std::string_view& type, fc::datastream<const char*>& stream,
156
157 bytes _variant_to_binary( const std::string_view& type, const fc::variant& var, impl::variant_to_binary_context& ctx )const;
158 void _variant_to_binary( const std::string_view& type, const fc::variant& var,
160
161 static std::string_view _remove_bin_extension(const std::string_view& type);
162 bool _is_type( const std::string_view& type, impl::abi_traverse_context& ctx )const;
163
164 void validate( impl::abi_traverse_context& ctx )const;
165
167 friend struct impl::abi_to_variant;
169};
170
171namespace impl {
172 const static size_t hex_log_max_size = 64;
178
179 void logging() { log = true; } // generate variant for logging
180 bool is_logging() const { return log; }
181
184
185 fc::scoped_exit<std::function<void()>> enter_scope();
186
187 protected:
189 size_t recursion_depth = 0;
190 bool log = false;
191 };
192
194
196 };
197
199 map<type_name, struct_def>::const_iterator struct_itr;
200 };
201
203 map<type_name, variant_def>::const_iterator variant_itr;
204 };
205
206 using path_root = std::variant<empty_path_root, array_type_path_root, struct_type_path_root, variant_type_path_root>;
207
209
214
216 map<type_name, struct_def>::const_iterator parent_struct_itr;
218 };
219
221 map<type_name, variant_def>::const_iterator variant_itr;
223 };
224
225 using path_item = std::variant<empty_path_item, array_index_path_item, field_path_item, variant_path_item>;
226
229 : abi_traverse_context( std::move( yield ) ), abis(abis)
230 {
231 set_path_root(type);
232 }
233
234 abi_traverse_context_with_path( const abi_serializer& abis, const abi_traverse_context& ctx, const std::string_view& type )
236 {
237 set_path_root(type);
238 }
239
240 void set_path_root( const std::string_view& type );
241
242 fc::scoped_exit<std::function<void()>> push_to_path( const path_item& item );
243
246 void hint_struct_type_if_in_array( const map<type_name, struct_def>::const_iterator& itr );
247 void hint_variant_type_if_in_array( const map<type_name, variant_def>::const_iterator& itr );
248
249 string get_path_string()const;
250
251 string maybe_shorten( const std::string_view& str );
252
253 protected:
257 public:
258 bool short_path = false;
259 };
260
264
267
268 fc::scoped_exit<std::function<void()>> disallow_extensions_unless( bool condition );
269
270 bool extensions_allowed()const { return allow_extensions; }
271
272 protected:
273 bool allow_extensions = true;
274 };
275
277 string limit_size( const std::string_view& str );
278
283 template<typename T>
284 constexpr bool single_type_requires_abi_v() {
285 return std::is_base_of<transaction, T>::value ||
286 std::is_same<T, packed_transaction>::value ||
287 std::is_same<T, transaction_trace>::value ||
288 std::is_same<T, transaction_receipt>::value ||
289 std::is_same<T, action_trace>::value ||
290 std::is_same<T, signed_transaction>::value ||
291 std::is_same<T, signed_block>::value ||
292 std::is_same<T, action>::value;
293 }
294
299 template<typename T>
301 static constexpr bool value() {
303 }
304 };
305
310 template<template<typename ...> class Container, typename T, typename ...Args >
311 struct type_requires_abi<Container<T, Args...>> {
312 static constexpr bool value() {
314 }
315 };
316
317 template<typename T>
318 constexpr bool type_requires_abi_v() {
320 }
321
325 template<typename T>
326 using not_require_abi_t = std::enable_if_t<!type_requires_abi_v<T>(), int>;
327
328 template<typename T>
329 using require_abi_t = std::enable_if_t<type_requires_abi_v<T>(), int>;
330
336 template<typename M, typename Resolver, not_require_abi_t<M> = 1>
337 static void add( mutable_variant_object &mvo, const char* name, const M& v, Resolver, abi_traverse_context& ctx )
338 {
339 auto h = ctx.enter_scope();
340 mvo(name,v);
341 }
342
347 template<typename M, typename Resolver, require_abi_t<M> = 1>
348 static void add( mutable_variant_object &mvo, const char* name, const M& v, Resolver resolver, abi_traverse_context& ctx );
349
354 template<typename M, typename Resolver, require_abi_t<M> = 1>
355 static void add( mutable_variant_object &mvo, const char* name, const vector<M>& v, Resolver resolver, abi_traverse_context& ctx )
356 {
357 auto h = ctx.enter_scope();
359 array.reserve(v.size());
360
361 for (const auto& iter: v) {
362 mutable_variant_object elem_mvo;
363 add(elem_mvo, "_", iter, resolver, ctx);
364 array.emplace_back(std::move(elem_mvo["_"]));
365 }
366 mvo(name, std::move(array));
367 }
368
373 template<typename M, typename Resolver, require_abi_t<M> = 1>
374 static void add( mutable_variant_object &mvo, const char* name, const std::shared_ptr<M>& v, Resolver resolver, abi_traverse_context& ctx )
375 {
376 auto h = ctx.enter_scope();
377 if( !v ) return;
379 add(obj_mvo, "_", *v, resolver, ctx);
380 mvo(name, std::move(obj_mvo["_"]));
381 }
382
383 template<typename Resolver>
385 {
387 Resolver& resolver;
389
392
393 typedef void result_type;
394 template<typename T> void operator()( T& v )const
395 {
396 add(obj_mvo, "_", v, resolver, ctx);
397 }
398 };
399
400 template<typename Resolver, typename... Args>
401 static void add( mutable_variant_object &mvo, const char* name, const std::variant<Args...>& v, Resolver resolver, abi_traverse_context& ctx )
402 {
403 auto h = ctx.enter_scope();
405 add_static_variant<Resolver> adder(obj_mvo, resolver, ctx);
406 std::visit(adder, v);
407 mvo(name, std::move(obj_mvo["_"]));
408 }
409
410 template<typename Resolver>
411 static bool add_special_logging( mutable_variant_object& mvo, const char* name, const action& act, Resolver& resolver, abi_traverse_context& ctx ) {
412 if( !ctx.is_logging() ) return false;
413
414 try {
415
416 if( act.account == config::system_account_name && act.name == "setcode"_n ) {
417 auto setcode_act = act.data_as<setcode>();
418 if( setcode_act.code.size() > 0 ) {
419 fc::sha256 code_hash = fc::sha256::hash(setcode_act.code.data(), (uint32_t) setcode_act.code.size());
420 mvo("code_hash", code_hash);
421 }
422 return false; // still want the hex data included
423 }
424
425 } catch(...) {} // return false
426
427 return false;
428 }
429
439 template<typename Resolver>
440 static void add( mutable_variant_object &out, const char* name, const action& act, Resolver resolver, abi_traverse_context& ctx )
441 {
443 auto h = ctx.enter_scope();
445 mvo("account", act.account);
446 mvo("name", act.name);
447 mvo("authorization", act.authorization);
448
449 if( add_special_logging(mvo, name, act, resolver, ctx) ) {
450 out(name, std::move(mvo));
451 return;
452 }
453
454 auto set_hex_data = [&](mutable_variant_object& mvo, const char* name, const bytes& data) {
455 if( !ctx.is_logging() ) {
456 mvo(name, data);
457 } else {
459 sub_obj( "size", data.size() );
460 if( data.size() > impl::hex_log_max_size ) {
461 sub_obj( "trimmed_hex", std::vector<char>(&data[0], &data[0] + impl::hex_log_max_size) );
462 } else {
463 sub_obj( "hex", data );
464 }
465 mvo(name, std::move(sub_obj));
466 }
467 };
468
469 try {
470 auto abi = resolver(act.account);
471 if (abi) {
472 auto type = abi->get_action_type(act.name);
473 if (!type.empty()) {
474 try {
475 binary_to_variant_context _ctx(*abi, ctx, type);
476 _ctx.short_path = true; // Just to be safe while avoiding the complexity of threading an override boolean all over the place
477 mvo( "data", abi->_binary_to_variant( type, act.data, _ctx ));
478 set_hex_data(mvo, "hex_data", act.data);
479 } catch(...) {
480 // any failure to serialize data, then leave as not serailzed
481 set_hex_data(mvo, "data", act.data);
482 }
483 } else {
484 set_hex_data(mvo, "data", act.data);
485 }
486 } else {
487 set_hex_data(mvo, "data", act.data);
488 }
489 } catch(...) {
490 set_hex_data(mvo, "data", act.data);
491 }
492 out(name, std::move(mvo));
493 }
494
504 template<typename Resolver>
505 static void add( mutable_variant_object& out, const char* name, const action_trace& act_trace, Resolver resolver, abi_traverse_context& ctx )
506 {
508 auto h = ctx.enter_scope();
510
511 mvo("action_ordinal", act_trace.action_ordinal);
512 mvo("creator_action_ordinal", act_trace.creator_action_ordinal);
513 mvo("closest_unnotified_ancestor_action_ordinal", act_trace.closest_unnotified_ancestor_action_ordinal);
514 mvo("receipt", act_trace.receipt);
515 mvo("receiver", act_trace.receiver);
516 add(mvo, "act", act_trace.act, resolver, ctx);
517 mvo("context_free", act_trace.context_free);
518 mvo("elapsed", act_trace.elapsed);
519 mvo("console", act_trace.console);
520 mvo("trx_id", act_trace.trx_id);
521 mvo("block_num", act_trace.block_num);
522 mvo("block_time", act_trace.block_time);
523 mvo("producer_block_id", act_trace.producer_block_id);
524 mvo("account_ram_deltas", act_trace.account_ram_deltas);
525 mvo("except", act_trace.except);
526 mvo("error_code", act_trace.error_code);
527
528 mvo("return_value_hex_data", act_trace.return_value);
529 auto act = act_trace.act;
530 try {
531 auto abi = resolver(act.account);
532 if (abi) {
533 auto type = abi->get_action_result_type(act.name);
534 if (!type.empty()) {
535 binary_to_variant_context _ctx(*abi, ctx, type);
536 _ctx.short_path = true; // Just to be safe while avoiding the complexity of threading an override boolean all over the place
537 mvo( "return_value_data", abi->_binary_to_variant( type, act_trace.return_value, _ctx ));
538 }
539 }
540 } catch(...) {}
541 out(name, std::move(mvo));
542 }
543
553 template<typename Resolver>
554 static void add( mutable_variant_object &out, const char* name, const packed_transaction& ptrx, Resolver resolver, abi_traverse_context& ctx )
555 {
557 auto h = ctx.enter_scope();
559 auto trx = ptrx.get_transaction();
560 mvo("id", trx.id());
561 mvo("signatures", ptrx.get_signatures());
562 mvo("compression", ptrx.get_compression());
563 mvo("packed_context_free_data", ptrx.get_packed_context_free_data());
564 mvo("context_free_data", ptrx.get_context_free_data());
565 if( !ctx.is_logging() )
566 mvo("packed_trx", ptrx.get_packed_transaction());
567 add(mvo, "transaction", trx, resolver, ctx);
568
569 out(name, std::move(mvo));
570 }
571
577 template<typename Resolver>
578 static void add( mutable_variant_object &out, const char* name, const transaction& trx, Resolver resolver, abi_traverse_context& ctx )
579 {
581 auto h = ctx.enter_scope();
583 mvo("expiration", trx.expiration);
584 mvo("ref_block_num", trx.ref_block_num);
585 mvo("ref_block_prefix", trx.ref_block_prefix);
586 mvo("max_net_usage_words", trx.max_net_usage_words);
587 mvo("max_cpu_usage_ms", trx.max_cpu_usage_ms);
588 mvo("delay_sec", trx.delay_sec);
589 add(mvo, "context_free_actions", trx.context_free_actions, resolver, ctx);
590 add(mvo, "actions", trx.actions, resolver, ctx);
591
592 // process contents of block.transaction_extensions
593 auto exts = trx.validate_and_extract_extensions();
595 const auto& deferred_transaction_generation = std::get<deferred_transaction_generation_context>(exts.lower_bound(deferred_transaction_generation_context::extension_id())->second);
596 mvo("deferred_transaction_generation", deferred_transaction_generation);
597 }
598
599 out(name, std::move(mvo));
600 }
601
608 template<typename Resolver>
609 static void add( mutable_variant_object &out, const char* name, const signed_block& block, Resolver resolver, abi_traverse_context& ctx )
610 {
612 auto h = ctx.enter_scope();
614 mvo("timestamp", block.timestamp);
615 mvo("producer", block.producer);
616 mvo("confirmed", block.confirmed);
617 mvo("previous", block.previous);
618 mvo("transaction_mroot", block.transaction_mroot);
619 mvo("action_mroot", block.action_mroot);
620 mvo("schedule_version", block.schedule_version);
621 mvo("new_producers", block.new_producers);
622
623 // process contents of block.header_extensions
624 flat_multimap<uint16_t, block_header_extension> header_exts = block.validate_and_extract_header_extensions();
625 if ( header_exts.count(protocol_feature_activation::extension_id() > 0) ) {
626 const auto& new_protocol_features =
627 std::get<protocol_feature_activation>(header_exts.lower_bound(protocol_feature_activation::extension_id())->second).protocol_features;
628 vector<fc::variant> pf_array;
629 pf_array.reserve(new_protocol_features.size());
630 for (auto feature : new_protocol_features) {
631 mutable_variant_object feature_mvo;
632 add(feature_mvo, "feature_digest", feature, resolver, ctx);
633 pf_array.push_back(feature_mvo);
634 }
635 mvo("new_protocol_features", pf_array);
636 }
637 if ( header_exts.count(producer_schedule_change_extension::extension_id())) {
638 const auto& new_producer_schedule =
639 std::get<producer_schedule_change_extension>(header_exts.lower_bound(producer_schedule_change_extension::extension_id())->second);
640 mvo("new_producer_schedule", new_producer_schedule);
641 }
642
643 mvo("producer_signature", block.producer_signature);
644 add(mvo, "transactions", block.transactions, resolver, ctx);
645
646 // process contents of block.block_extensions
647 auto block_exts = block.validate_and_extract_extensions();
648 if ( block_exts.count(additional_block_signatures_extension::extension_id()) > 0) {
649 const auto& additional_signatures =
650 std::get<additional_block_signatures_extension>(block_exts.lower_bound(additional_block_signatures_extension::extension_id())->second);
651 mvo("additional_signatures", additional_signatures);
652 }
653
654 out(name, std::move(mvo));
655 }
656 };
657
665 template<typename T, typename Resolver>
667 {
668 public:
669 abi_to_variant_visitor( mutable_variant_object& _mvo, const T& _val, Resolver _resolver, abi_traverse_context& _ctx )
670 :_vo(_mvo)
671 ,_val(_val)
672 ,_resolver(_resolver)
673 ,_ctx(_ctx)
674 {}
675
683 template<typename Member, class Class, Member (Class::*member) >
684 void operator()( const char* name )const
685 {
686 abi_to_variant::add( _vo, name, (_val.*member), _resolver, _ctx );
687 }
688
689 private:
691 const T& _val;
692 Resolver _resolver;
694 };
695
701 template<typename M, typename Resolver, not_require_abi_t<M> = 1>
702 static void extract( const fc::variant& v, M& o, Resolver, abi_traverse_context& ctx )
703 {
704 auto h = ctx.enter_scope();
705 from_variant(v, o);
706 }
707
712 template<typename M, typename Resolver, require_abi_t<M> = 1>
713 static void extract( const fc::variant& v, M& o, Resolver resolver, abi_traverse_context& ctx );
714
719 template<typename M, typename Resolver, require_abi_t<M> = 1>
720 static void extract( const fc::variant& v, vector<M>& o, Resolver resolver, abi_traverse_context& ctx )
721 {
722 auto h = ctx.enter_scope();
723 const variants& array = v.get_array();
724 o.clear();
725 o.reserve( array.size() );
726 for( auto itr = array.begin(); itr != array.end(); ++itr ) {
727 M o_iter;
728 extract(*itr, o_iter, resolver, ctx);
729 o.emplace_back(std::move(o_iter));
730 }
731 }
732
737 template<typename M, typename Resolver, require_abi_t<M> = 1>
738 static void extract( const fc::variant& v, std::shared_ptr<M>& o, Resolver resolver, abi_traverse_context& ctx )
739 {
740 auto h = ctx.enter_scope();
741 const variant_object& vo = v.get_object();
742 M obj;
743 extract(vo, obj, resolver, ctx);
744 o = std::make_shared<M>(obj);
745 }
746
752 template<typename Resolver>
753 static void extract( const fc::variant& v, action& act, Resolver resolver, abi_traverse_context& ctx )
754 {
755 auto h = ctx.enter_scope();
756 const variant_object& vo = v.get_object();
757 SYS_ASSERT(vo.contains("account"), packed_transaction_type_exception, "Missing account");
758 SYS_ASSERT(vo.contains("name"), packed_transaction_type_exception, "Missing name");
759 from_variant(vo["account"], act.account);
760 from_variant(vo["name"], act.name);
761
762 if (vo.contains("authorization")) {
763 from_variant(vo["authorization"], act.authorization);
764 }
765
766 bool valid_empty_data = false;
767 if( vo.contains( "data" ) ) {
768 const auto& data = vo["data"];
769 if( data.is_string() ) {
770 from_variant(data, act.data);
771 valid_empty_data = act.data.empty();
772 } else if ( data.is_object() ) {
773 auto abi = resolver(act.account);
774 if (abi) {
775 auto type = abi->get_action_type(act.name);
776 if (!type.empty()) {
777 variant_to_binary_context _ctx(*abi, ctx, type);
778 _ctx.short_path = true; // Just to be safe while avoiding the complexity of threading an override boolean all over the place
779 act.data = std::move( abi->_variant_to_binary( type, data, _ctx ));
780 valid_empty_data = act.data.empty();
781 }
782 }
783 }
784 }
785
786 if( !valid_empty_data && act.data.empty() ) {
787 if( vo.contains( "hex_data" ) ) {
788 const auto& data = vo["hex_data"];
789 if( data.is_string() ) {
790 from_variant(data, act.data);
791 }
792 }
793 }
794
795 SYS_ASSERT(valid_empty_data || !act.data.empty(), packed_transaction_type_exception,
796 "Failed to deserialize data for ${account}:${name}", ("account", act.account)("name", act.name));
797 }
798
799 template<typename Resolver>
800 static void extract( const fc::variant& v, packed_transaction& ptrx, Resolver resolver, abi_traverse_context& ctx )
801 {
802 auto h = ctx.enter_scope();
803 const variant_object& vo = v.get_object();
804 SYS_ASSERT(vo.contains("signatures"), packed_transaction_type_exception, "Missing signatures");
805 SYS_ASSERT(vo.contains("compression"), packed_transaction_type_exception, "Missing compression");
806 std::vector<signature_type> signatures;
808 from_variant(vo["signatures"], signatures);
809 from_variant(vo["compression"], compression);
810
811 bytes packed_cfd;
812 std::vector<bytes> cfd;
813 bool use_packed_cfd = false;
814 if( vo.contains("packed_context_free_data") && vo["packed_context_free_data"].is_string() && !vo["packed_context_free_data"].as_string().empty() ) {
815 from_variant(vo["packed_context_free_data"], packed_cfd );
816 use_packed_cfd = true;
817 } else if( vo.contains("context_free_data") ) {
818 from_variant(vo["context_free_data"], cfd);
819 }
820
821 if( vo.contains("packed_trx") && vo["packed_trx"].is_string() && !vo["packed_trx"].as_string().empty() ) {
822 bytes packed_trx;
823 from_variant(vo["packed_trx"], packed_trx);
824 if( use_packed_cfd ) {
825 ptrx = packed_transaction( std::move( packed_trx ), std::move( signatures ), std::move( packed_cfd ), compression );
826 } else {
827 ptrx = packed_transaction( std::move( packed_trx ), std::move( signatures ), std::move( cfd ), compression );
828 }
829 } else {
830 SYS_ASSERT(vo.contains("transaction"), packed_transaction_type_exception, "Missing transaction");
831 if( use_packed_cfd ) {
832 transaction trx;
833 extract( vo["transaction"], trx, resolver, ctx );
834 ptrx = packed_transaction( std::move(trx), std::move(signatures), std::move(packed_cfd), compression );
835 } else {
837 extract( vo["transaction"], trx, resolver, ctx );
838 trx.signatures = std::move( signatures );
839 trx.context_free_data = std::move(cfd);
840 ptrx = packed_transaction( std::move( trx ), compression );
841 }
842 }
843 }
844 };
845
853 template<typename T, typename Resolver>
855 {
856 public:
857 abi_from_variant_visitor( const variant_object& _vo, T& v, Resolver _resolver, abi_traverse_context& _ctx )
859 ,_vo(_vo)
860 ,_resolver(_resolver)
861 ,_ctx(_ctx)
862 {}
863
871 template<typename Member, class Class, Member (Class::*member)>
872 void operator()( const char* name )const
873 {
874 auto itr = _vo.find(name);
875 if( itr != _vo.end() )
876 abi_from_variant::extract( itr->value(), this->obj.*member, _resolver, _ctx );
877 }
878
879 private:
880 const variant_object& _vo;
881 Resolver _resolver;
883 };
884
885 template<typename M, typename Resolver, require_abi_t<M>>
886 void abi_to_variant::add( mutable_variant_object &mvo, const char* name, const M& v, Resolver resolver, abi_traverse_context& ctx )
887 {
888 auto h = ctx.enter_scope();
889 mutable_variant_object member_mvo;
891 mvo(name, std::move(member_mvo));
892 }
893
894 template<typename M, typename Resolver, require_abi_t<M>>
895 void abi_from_variant::extract( const fc::variant& v, M& o, Resolver resolver, abi_traverse_context& ctx )
896 {
897 auto h = ctx.enter_scope();
898 const variant_object& vo = v.get_object();
899 fc::reflector<M>::visit( abi_from_variant_visitor<M, decltype(resolver)>( vo, o, resolver, ctx ) );
900 }
901}
902
903template<typename T, typename Resolver>
904void abi_serializer::to_variant( const T& o, fc::variant& vo, Resolver resolver, const yield_function_t& yield ) try {
906 impl::abi_traverse_context ctx( yield );
907 impl::abi_to_variant::add(mvo, "_", o, resolver, ctx);
908 vo = std::move(mvo["_"]);
909} FC_RETHROW_EXCEPTIONS(error, "Failed to serialize: ${type}", ("type", boost::core::demangle( typeid(o).name() ) ))
910
911template<typename T, typename Resolver>
912void abi_serializer::to_variant( const T& o, fc::variant& vo, Resolver resolver, const fc::microseconds& max_serialization_time ) {
913 to_variant( o, vo, resolver, create_yield_function(max_serialization_time) );
914}
915
916template<typename T, typename Resolver>
917void abi_serializer::to_log_variant( const T& o, fc::variant& vo, Resolver resolver, const yield_function_t& yield ) try {
919 impl::abi_traverse_context ctx( yield );
920 ctx.logging();
921 impl::abi_to_variant::add(mvo, "_", o, resolver, ctx);
922 vo = std::move(mvo["_"]);
923} FC_RETHROW_EXCEPTIONS(error, "Failed to serialize: ${type}", ("type", boost::core::demangle( typeid(o).name() ) ))
924
925
926template<typename T, typename Resolver>
927void abi_serializer::from_variant( const fc::variant& v, T& o, Resolver resolver, const yield_function_t& yield ) try {
928 impl::abi_traverse_context ctx( yield );
929 impl::abi_from_variant::extract(v, o, resolver, ctx);
930} FC_RETHROW_EXCEPTIONS(error, "Failed to deserialize variant", ("variant",v))
931
932template<typename T, typename Resolver>
933void abi_serializer::from_variant( const fc::variant& v, T& o, Resolver resolver, const fc::microseconds& max_serialization_time ) {
934 from_variant( v, o, resolver, create_yield_function(max_serialization_time) );
935}
936
937
938} } // sysio::chain
const mie::Vuint & r
Definition bn.cpp:28
std::string name
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
Definition exceptions.hpp:7
size_t size() const
Definition array.hpp:35
const T * begin() const
Definition array.hpp:29
const T * end() const
Definition array.hpp:30
static constexpr microseconds maximum()
Definition time.hpp:14
An order-preserving dictionary of variants.
static sha256 hash(const char *d, uint32_t dlen)
Definition sha256.cpp:44
static time_point now()
Definition time.cpp:14
static constexpr time_point maximum()
Definition time.hpp:46
An order-preserving dictionary of variants.
iterator end() const
iterator find(const string &key) const
bool contains(const char *key) const
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
Definition variant.hpp:191
variant_object & get_object()
Definition variant.cpp:554
variants & get_array()
Definition variant.cpp:496
abi_from_variant_visitor(const variant_object &_vo, T &v, Resolver _resolver, abi_traverse_context &_ctx)
abi_to_variant_visitor(mutable_variant_object &_mvo, const T &_val, Resolver _resolver, abi_traverse_context &_ctx)
#define FC_RETHROW_EXCEPTIONS(LOG_LEVEL, FORMAT,...)
Catchs all exception's, std::exceptions, and ... and rethrows them after appending the provided log m...
void unpack(Stream &s, std::deque< T > &value)
Definition raw.hpp:540
namespace sysio::chain
Definition authority.cpp:3
std::vector< fc::variant > variants
Definition variant.hpp:173
void from_variant(const fc::variant &v, sysio::chain::chain_id_type &cid)
void to_variant(const sysio::chain::shared_public_key &var, fc::variant &vo)
Definition authority.cpp:4
Definition name.hpp:106
std::variant< empty_path_root, array_type_path_root, struct_type_path_root, variant_type_path_root > path_root
constexpr bool type_requires_abi_v()
std::enable_if_t<!type_requires_abi_v< T >(), int > not_require_abi_t
std::enable_if_t< type_requires_abi_v< T >(), int > require_abi_t
string limit_size(const std::string_view &str)
limits the string size to default max_length of output_name
std::variant< empty_path_item, array_index_path_item, field_path_item, variant_path_item > path_item
constexpr bool single_type_requires_abi_v()
string type_name
Definition abi_def.hpp:7
#define T(meth, val, expected)
#define extract(n)
unsigned int uint32_t
Definition stdint.h:126
unsigned __int64 uint64_t
Definition stdint.h:136
defines visit functions for T Unless this is specialized, visit() will not be defined for T.
Definition reflect.hpp:33
static constexpr size_t max_recursion_depth
type_name get_action_result_type(name action_result) const
static yield_function_t create_yield_function(const fc::microseconds &max_serialization_time)
void set_abi(const abi_def &abi, const yield_function_t &yield)
type_name get_table_type(name action) const
static void to_log_variant(const T &o, fc::variant &vo, Resolver resolver, const yield_function_t &yield)
const struct_def & get_struct(const std::string_view &type) const
static bool to_abi(const Vec &abi_vec, abi_def &abi)
int get_integer_size(const std::string_view &type) const
bytes variant_to_binary(const std::string_view &type, const fc::variant &var, const fc::microseconds &max_serialization_time, bool short_path=false) const
std::string_view fundamental_type(const std::string_view &type) const
type_name get_action_type(name action) const
static void to_variant(const T &o, fc::variant &vo, Resolver resolver, const yield_function_t &yield)
namespace sysio::chain::impl
std::optional< string > get_error_message(uint64_t error_code) const
bool is_integer(const std::string_view &type) const
static bool is_empty_abi(const Vec &abi_vec)
std::function< void(const fc::variant &, fc::datastream< char * > &, bool, bool, const abi_serializer::yield_function_t &)> pack_function
void add_specialized_unpack_pack(const string &name, std::pair< abi_serializer::unpack_function, abi_serializer::pack_function > unpack_pack)
std::function< fc::variant(fc::datastream< const char * > &, bool, bool, const abi_serializer::yield_function_t &)> unpack_function
fc::variant binary_to_variant(const std::string_view &type, const bytes &binary, const yield_function_t &yield, bool short_path=false) const
bool is_optional(const std::string_view &type) const
bool is_struct(const std::string_view &type) const
bool is_builtin_type(const std::string_view &type) const
bool is_type(const std::string_view &type, const yield_function_t &yield) const
std::string_view resolve_type(const std::string_view &t) const
static void from_variant(const fc::variant &v, T &o, Resolver resolver, const yield_function_t &yield)
bool is_array(const std::string_view &type) const
vector< permission_level > authorization
Definition action.hpp:59
std::optional< block_id_type > producer_block_id
Definition trace.hpp:43
fc::microseconds elapsed
Definition trace.hpp:38
block_timestamp_type block_time
Definition trace.hpp:42
fc::unsigned_int creator_action_ordinal
Definition trace.hpp:32
std::optional< fc::exception > except
Definition trace.hpp:45
fc::unsigned_int closest_unnotified_ancestor_action_ordinal
Definition trace.hpp:33
flat_set< account_delta > account_ram_deltas
Definition trace.hpp:44
fc::unsigned_int action_ordinal
Definition trace.hpp:31
transaction_id_type trx_id
the transaction that generated this action
Definition trace.hpp:40
std::vector< char > return_value
Definition trace.hpp:47
std::optional< action_receipt > receipt
Definition trace.hpp:34
std::optional< uint64_t > error_code
Definition trace.hpp:46
T data_as() const
Definition action.hpp:91
static void extract(const fc::variant &v, vector< M > &o, Resolver resolver, abi_traverse_context &ctx)
static void extract(const fc::variant &v, packed_transaction &ptrx, Resolver resolver, abi_traverse_context &ctx)
static void extract(const fc::variant &v, M &o, Resolver, abi_traverse_context &ctx)
static void extract(const fc::variant &v, std::shared_ptr< M > &o, Resolver resolver, abi_traverse_context &ctx)
static void extract(const fc::variant &v, M &o, Resolver resolver, abi_traverse_context &ctx)
static void extract(const fc::variant &v, action &act, Resolver resolver, abi_traverse_context &ctx)
add_static_variant(mutable_variant_object &o, Resolver &r, abi_traverse_context &ctx)
static void add(mutable_variant_object &out, const char *name, const packed_transaction &ptrx, Resolver resolver, abi_traverse_context &ctx)
static void add(mutable_variant_object &mvo, const char *name, const M &v, Resolver resolver, abi_traverse_context &ctx)
static void add(mutable_variant_object &mvo, const char *name, const std::shared_ptr< M > &v, Resolver resolver, abi_traverse_context &ctx)
static void add(mutable_variant_object &out, const char *name, const action_trace &act_trace, Resolver resolver, abi_traverse_context &ctx)
static void add(mutable_variant_object &out, const char *name, const transaction &trx, Resolver resolver, abi_traverse_context &ctx)
static bool add_special_logging(mutable_variant_object &mvo, const char *name, const action &act, Resolver &resolver, abi_traverse_context &ctx)
static void add(mutable_variant_object &mvo, const char *name, const std::variant< Args... > &v, Resolver resolver, abi_traverse_context &ctx)
static void add(mutable_variant_object &mvo, const char *name, const vector< M > &v, Resolver resolver, abi_traverse_context &ctx)
static void add(mutable_variant_object &mvo, const char *name, const M &v, Resolver, abi_traverse_context &ctx)
static void add(mutable_variant_object &out, const char *name, const signed_block &block, Resolver resolver, abi_traverse_context &ctx)
static void add(mutable_variant_object &out, const char *name, const action &act, Resolver resolver, abi_traverse_context &ctx)
abi_traverse_context_with_path(const abi_serializer &abis, abi_serializer::yield_function_t yield, const std::string_view &type)
fc::scoped_exit< std::function< void()> > push_to_path(const path_item &item)
void set_path_root(const std::string_view &type)
void hint_variant_type_if_in_array(const map< type_name, variant_def >::const_iterator &itr)
string maybe_shorten(const std::string_view &str)
void hint_struct_type_if_in_array(const map< type_name, struct_def >::const_iterator &itr)
abi_traverse_context_with_path(const abi_serializer &abis, const abi_traverse_context &ctx, const std::string_view &type)
abi_traverse_context(abi_serializer::yield_function_t yield)
abi_serializer::yield_function_t yield
abi_serializer::yield_function_t get_yield_function()
fc::scoped_exit< std::function< void()> > enter_scope()
map< type_name, struct_def >::const_iterator parent_struct_itr
map< type_name, struct_def >::const_iterator struct_itr
map< type_name, variant_def >::const_iterator variant_itr
fc::scoped_exit< std::function< void()> > disallow_extensions_unless(bool condition)
map< type_name, variant_def >::const_iterator variant_itr
Immutable except for fc::from_variant.
Definition name.hpp:43
const bytes & get_packed_context_free_data() const
const vector< signature_type > & get_signatures() const
const fc::enum_type< uint8_t, compression_type > & get_compression() const
const vector< bytes > & get_context_free_data() const
const transaction & get_transaction() const
const bytes & get_packed_transaction() const
vector< bytes > context_free_data
for each context-free action, there is an entry here
vector< signature_type > signatures
fc::unsigned_int delay_sec
upper limit on the total CPU time billed for this transaction
uint16_t ref_block_num
specifies a block num in the last 2^16 blocks.
uint32_t ref_block_prefix
specifies the lower 32 bits of the blockid at get_ref_blocknum
uint8_t max_cpu_usage_ms
upper limit on total network bandwidth (in 8 byte words) billed for this transaction
time_point_sec expiration
the time at which a transaction expires
vector< action > actions
vector< action > context_free_actions
flat_multimap< uint16_t, transaction_extension > validate_and_extract_extensions() const
yubihsm_pkcs11_object_template template