diff --git a/libraries/chain/include/eosio/chain/abi_serializer.hpp b/libraries/chain/include/eosio/chain/abi_serializer.hpp
index 62a034ca859..75cc8a51ee4 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<bytes> 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<bytes> 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 5aa49438acf..60ac50d0413 100644
--- a/libraries/chain/include/eosio/chain/transaction.hpp
+++ b/libraries/chain/include/eosio/chain/transaction.hpp
@@ -117,21 +117,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<signature_type>&& sigs,
-                                   bytes&& packed_cfd, vector<bytes>&& cfd, compression_type _compression );
-      explicit packed_transaction( signed_transaction&& t, bytes&& packed_cfd, compression_type _compression );
+      packed_transaction( bytes&& packed_txn, vector<signature_type>&& sigs, bytes&& packed_cfd, compression_type _compression );
+      packed_transaction( bytes&& packed_txn, vector<signature_type>&& sigs, vector<bytes>&& cfd, compression_type _compression );
+      packed_transaction( transaction&& t, vector<signature_type>&& sigs, bytes&& packed_cfd, compression_type _compression );
 
       uint32_t get_unprunable_size()const;
       uint32_t get_prunable_size()const;
@@ -151,10 +151,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<bytes>&& context_free_data);
-      void set_packed_transaction(const transaction& t);
-      void set_packed_context_free_data(const vector<bytes>& cfd);
+      void local_unpack_context_free_data();
+      void local_pack_transaction();
+      void local_pack_context_free_data();
 
       friend struct fc::reflector<packed_transaction>;
       friend struct fc::reflector_verifier_visitor<packed_transaction>;
diff --git a/libraries/chain/transaction.cpp b/libraries/chain/transaction.cpp
index ff3083fef04..d185e693ed1 100644
--- a/libraries/chain/transaction.cpp
+++ b/libraries/chain/transaction.cpp
@@ -289,31 +289,36 @@ bytes packed_transaction::get_raw_transaction() const
    } FC_CAPTURE_AND_RETHROW((compression)(packed_trx))
 }
 
-packed_transaction::packed_transaction( bytes&& packed_txn, vector<signature_type>&& sigs,
-                                        bytes&& packed_cfd, vector<bytes>&& cfd, compression_type _compression )
+packed_transaction::packed_transaction( bytes&& packed_txn, vector<signature_type>&& 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<bytes>() : 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<signature_type>&& sigs, vector<bytes>&& 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<signature_type>&& 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();
    }
@@ -363,31 +368,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<bytes>& 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");