diff --git a/libraries/chain/include/eosio/chain/abi_serializer.hpp b/libraries/chain/include/eosio/chain/abi_serializer.hpp index 8577c1de972..c02e6c46aef 100644 --- a/libraries/chain/include/eosio/chain/abi_serializer.hpp +++ b/libraries/chain/include/eosio/chain/abi_serializer.hpp @@ -583,27 +583,36 @@ namespace impl { from_variant(vo["compression"], compression); bytes packed_cfd; + std::vector cfd; + bool use_packed_cfd = false; + if( vo.contains("packed_context_free_data") && vo["packed_context_free_data"].is_string() && !vo["packed_context_free_data"].as_string().empty() ) { + from_variant(vo["packed_context_free_data"], packed_cfd ); + use_packed_cfd = true; + } else if( vo.contains("context_free_data") ) { + from_variant(vo["context_free_data"], cfd); + } + if( vo.contains("packed_trx") && vo["packed_trx"].is_string() && !vo["packed_trx"].as_string().empty() ) { bytes packed_trx; - std::vector cfd; from_variant(vo["packed_trx"], packed_trx); - if( vo.contains("packed_context_free_data") && vo["packed_context_free_data"].is_string() && !vo["packed_context_free_data"].as_string().empty() ) { - from_variant(vo["packed_context_free_data"], packed_cfd ); - } else if( vo.contains("context_free_data") ) { - from_variant(vo["context_free_data"], cfd); + if( use_packed_cfd ) { + ptrx = packed_transaction( std::move( packed_trx ), std::move( signatures ), std::move( packed_cfd ), compression ); + } else { + ptrx = packed_transaction( std::move( packed_trx ), std::move( signatures ), std::move( cfd ), compression ); } - ptrx = packed_transaction( std::move(packed_trx), std::move(signatures), std::move(packed_cfd), std::move(cfd), compression ); } else { EOS_ASSERT(vo.contains("transaction"), packed_transaction_type_exception, "Missing transaction"); - signed_transaction trx; - trx.signatures = std::move(signatures); - extract(vo["transaction"], trx, resolver, ctx); - if( vo.contains("packed_context_free_data") && vo["packed_context_free_data"].is_string() && !vo["packed_context_free_data"].as_string().empty() ) { - from_variant(vo["packed_context_free_data"], packed_cfd ); - } else if( vo.contains("context_free_data") ) { - from_variant(vo["context_free_data"], trx.context_free_data ); + if( use_packed_cfd ) { + transaction trx; + extract( vo["transaction"], trx, resolver, ctx ); + ptrx = packed_transaction( std::move(trx), std::move(signatures), std::move(packed_cfd), compression ); + } else { + signed_transaction trx; + extract( vo["transaction"], trx, resolver, ctx ); + trx.signatures = std::move( signatures ); + trx.context_free_data = std::move(cfd); + ptrx = packed_transaction( std::move( trx ), compression ); } - ptrx = packed_transaction( std::move(trx), std::move(packed_cfd), compression ); } } }; diff --git a/libraries/chain/include/eosio/chain/transaction.hpp b/libraries/chain/include/eosio/chain/transaction.hpp index 6fbc21a5f43..81112d543f7 100644 --- a/libraries/chain/include/eosio/chain/transaction.hpp +++ b/libraries/chain/include/eosio/chain/transaction.hpp @@ -114,21 +114,21 @@ namespace eosio { namespace chain { explicit packed_transaction(const signed_transaction& t, compression_type _compression = none) :signatures(t.signatures), compression(_compression), unpacked_trx(t) { - set_packed_transaction(unpacked_trx); - set_packed_context_free_data(unpacked_trx.context_free_data); + local_pack_transaction(); + local_pack_context_free_data(); } explicit packed_transaction(signed_transaction&& t, compression_type _compression = none) :signatures(t.signatures), compression(_compression), unpacked_trx(std::move(t)) { - set_packed_transaction(unpacked_trx); - set_packed_context_free_data(unpacked_trx.context_free_data); + local_pack_transaction(); + local_pack_context_free_data(); } // used by abi_serializer - explicit packed_transaction( bytes&& packed_txn, vector&& sigs, - bytes&& packed_cfd, vector&& cfd, compression_type _compression ); - explicit packed_transaction( signed_transaction&& t, bytes&& packed_cfd, compression_type _compression ); + packed_transaction( bytes&& packed_txn, vector&& sigs, bytes&& packed_cfd, compression_type _compression ); + packed_transaction( bytes&& packed_txn, vector&& sigs, vector&& cfd, compression_type _compression ); + packed_transaction( transaction&& t, vector&& sigs, bytes&& packed_cfd, compression_type _compression ); uint32_t get_unprunable_size()const; uint32_t get_prunable_size()const; @@ -148,10 +148,10 @@ namespace eosio { namespace chain { const bytes& get_packed_transaction()const { return packed_trx; } private: - void local_unpack_context_free_data(); void local_unpack_transaction(vector&& context_free_data); - void set_packed_transaction(const transaction& t); - void set_packed_context_free_data(const vector& cfd); + void local_unpack_context_free_data(); + void local_pack_transaction(); + void local_pack_context_free_data(); friend struct fc::reflector; friend struct fc::reflector_verifier_visitor; diff --git a/libraries/chain/transaction.cpp b/libraries/chain/transaction.cpp index 614f400f807..684c6b173d4 100644 --- a/libraries/chain/transaction.cpp +++ b/libraries/chain/transaction.cpp @@ -273,31 +273,36 @@ bytes packed_transaction::get_raw_transaction() const } FC_CAPTURE_AND_RETHROW((compression)(packed_trx)) } -packed_transaction::packed_transaction( bytes&& packed_txn, vector&& sigs, - bytes&& packed_cfd, vector&& cfd, compression_type _compression ) +packed_transaction::packed_transaction( bytes&& packed_txn, vector&& sigs, bytes&& packed_cfd, compression_type _compression ) :signatures(std::move(sigs)) ,compression(_compression) ,packed_context_free_data(std::move(packed_cfd)) ,packed_trx(std::move(packed_txn)) { - const bool cfd_empty = cfd.empty(); - EOS_ASSERT( cfd_empty || packed_cfd.empty(), tx_decompression_error, "Invalid packed_transaction" ); - local_unpack_transaction( cfd_empty ? vector() : std::move( cfd ) ); - if( !cfd_empty ) { - set_packed_context_free_data( unpacked_trx.context_free_data ); - } else if( !packed_context_free_data.empty() ) { + local_unpack_transaction({}); + if( !packed_context_free_data.empty() ) { local_unpack_context_free_data(); } } -packed_transaction::packed_transaction( signed_transaction&& t, bytes&& packed_cfd, compression_type _compression ) -:signatures(t.signatures) +packed_transaction::packed_transaction( bytes&& packed_txn, vector&& sigs, vector&& cfd, compression_type _compression ) +:signatures(std::move(sigs)) +,compression(_compression) +,packed_trx(std::move(packed_txn)) +{ + local_unpack_transaction( std::move( cfd ) ); + if( !unpacked_trx.context_free_data.empty() ) { + local_pack_context_free_data(); + } +} + +packed_transaction::packed_transaction( transaction&& t, vector&& sigs, bytes&& packed_cfd, compression_type _compression ) +:signatures(std::move(sigs)) ,compression(_compression) ,packed_context_free_data(std::move(packed_cfd)) -,unpacked_trx(std::move(t)) +,unpacked_trx(std::move(t), signatures, {}) { - EOS_ASSERT( packed_cfd.empty() || unpacked_trx.context_free_data.empty(), tx_decompression_error, "Invalid packed_transaction" ); - set_packed_transaction( unpacked_trx ); + local_pack_transaction(); if( !packed_context_free_data.empty() ) { local_unpack_context_free_data(); } @@ -347,31 +352,31 @@ void packed_transaction::local_unpack_context_free_data() } FC_CAPTURE_AND_RETHROW( (compression) ) } -void packed_transaction::set_packed_transaction(const transaction& t) +void packed_transaction::local_pack_transaction() { try { switch(compression) { case none: - packed_trx = pack_transaction(t); + packed_trx = pack_transaction(unpacked_trx); break; case zlib: - packed_trx = zlib_compress_transaction(t); + packed_trx = zlib_compress_transaction(unpacked_trx); break; default: EOS_THROW(unknown_transaction_compression, "Unknown transaction compression algorithm"); } - } FC_CAPTURE_AND_RETHROW((compression)(t)) + } FC_CAPTURE_AND_RETHROW((compression)) } -void packed_transaction::set_packed_context_free_data(const vector& cfd) +void packed_transaction::local_pack_context_free_data() { try { switch(compression) { case none: - packed_context_free_data = pack_context_free_data(cfd); + packed_context_free_data = pack_context_free_data(unpacked_trx.context_free_data); break; case zlib: - packed_context_free_data = zlib_compress_context_free_data(cfd); + packed_context_free_data = zlib_compress_context_free_data(unpacked_trx.context_free_data); break; default: EOS_THROW(unknown_transaction_compression, "Unknown transaction compression algorithm");