portable serializer: make signerd/unsigned tx portable, ignore archive version checking

This commit is contained in:
kenshi84 2016-12-30 22:51:43 +09:00
parent dd580d7bc7
commit f390a0e2dc
5 changed files with 117 additions and 61 deletions

View File

@ -321,6 +321,8 @@ portable_binary_iarchive::init(unsigned int flags){
boost::archive::library_version_type input_library_version; boost::archive::library_version_type input_library_version;
* this >> input_library_version; * this >> input_library_version;
// ignore archive version checking
/*
// extra little .t is to get around borland quirk // extra little .t is to get around borland quirk
if(boost::archive::BOOST_ARCHIVE_VERSION() < input_library_version) if(boost::archive::BOOST_ARCHIVE_VERSION() < input_library_version)
boost::serialization::throw_exception( boost::serialization::throw_exception(
@ -328,6 +330,7 @@ portable_binary_iarchive::init(unsigned int flags){
boost::archive::archive_exception::unsupported_version boost::archive::archive_exception::unsupported_version
) )
); );
*/
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
this->set_library_version(input_library_version); this->set_library_version(input_library_version);

View File

@ -277,10 +277,14 @@ portable_binary_oarchive::init(unsigned int flags) {
boost::archive::BOOST_ARCHIVE_SIGNATURE() boost::archive::BOOST_ARCHIVE_SIGNATURE()
); );
* this << file_signature; * this << file_signature;
// ignore archive version checking
const boost::archive::library_version_type v{};
/*
// write library version // write library version
const boost::archive::library_version_type v( const boost::archive::library_version_type v(
boost::archive::BOOST_ARCHIVE_VERSION() boost::archive::BOOST_ARCHIVE_VERSION()
); );
*/
* this << v; * this << v;
} }
save(static_cast<unsigned char>(m_flags >> CHAR_BIT)); save(static_cast<unsigned char>(m_flags >> CHAR_BIT));

View File

@ -36,7 +36,8 @@
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "crypto/hash.h" #include "crypto/hash.h"
#include "ringct/rctOps.h" #include "ringct/rctOps.h"
#include <boost/serialization/vector.hpp>
#include <boost/serialization/utility.hpp>
namespace cryptonote namespace cryptonote
{ {
@ -62,16 +63,6 @@ namespace cryptonote
rct::key mask; //ringct amount mask rct::key mask; //ringct amount mask
void push_output(uint64_t idx, const crypto::public_key &k, uint64_t amount) { outputs.push_back(std::make_pair(idx, rct::ctkey({rct::pk2rct(k), rct::zeroCommit(amount)}))); } void push_output(uint64_t idx, const crypto::public_key &k, uint64_t amount) { outputs.push_back(std::make_pair(idx, rct::ctkey({rct::pk2rct(k), rct::zeroCommit(amount)}))); }
BEGIN_SERIALIZE_OBJECT()
FIELD(outputs)
VARINT_FIELD(real_output)
FIELD(real_out_tx_key)
VARINT_FIELD(real_output_in_tx_index)
VARINT_FIELD(amount)
FIELD(rct)
FIELD(mask)
END_SERIALIZE()
}; };
struct tx_destination_entry struct tx_destination_entry
@ -261,3 +252,23 @@ namespace cryptonote
specific_type& variable_name = boost::get<specific_type>(variant_var); specific_type& variable_name = boost::get<specific_type>(variant_var);
} }
BOOST_CLASS_VERSION(cryptonote::tx_source_entry, 0)
namespace boost
{
namespace serialization
{
template <class Archive>
inline void serialize(Archive &a, cryptonote::tx_source_entry &x, const boost::serialization::version_type ver)
{
a & x.outputs;
a & x.real_output;
a & x.real_out_tx_key;
a & x.real_output_in_tx_index;
a & x.amount;
a & x.rct;
a & x.mask;
}
}
}

View File

@ -77,8 +77,8 @@ using namespace cryptonote;
// arbitrary, used to generate different hashes from the same input // arbitrary, used to generate different hashes from the same input
#define CHACHA8_KEY_TAIL 0x8c #define CHACHA8_KEY_TAIL 0x8c
#define UNSIGNED_TX_PREFIX "Monero unsigned tx set\002" #define UNSIGNED_TX_PREFIX "Monero unsigned tx set\003"
#define SIGNED_TX_PREFIX "Monero signed tx set\002" #define SIGNED_TX_PREFIX "Monero signed tx set\003"
#define RECENT_OUTPUT_RATIO (0.25) // 25% of outputs are from the recent zone #define RECENT_OUTPUT_RATIO (0.25) // 25% of outputs are from the recent zone
#define RECENT_OUTPUT_ZONE (5 * 86400) // last 5 days are the recent zone #define RECENT_OUTPUT_ZONE (5 * 86400) // last 5 days are the recent zone
@ -3018,14 +3018,19 @@ bool wallet2::save_tx(const std::vector<pending_tx>& ptx_vector, const std::stri
for (auto &tx: ptx_vector) for (auto &tx: ptx_vector)
txs.txes.push_back(tx.construction_data); txs.txes.push_back(tx.construction_data);
txs.transfers = m_transfers; txs.transfers = m_transfers;
std::string s = obj_to_json_str(txs); // save as binary
if (s.empty()) std::ostringstream oss;
boost::archive::portable_binary_oarchive ar(oss);
try
{
ar << txs;
}
catch (...)
{
return false; return false;
LOG_PRINT_L2("Saving unsigned tx data: " << s); }
// save as binary as there's no implementation of loading a json_archive LOG_PRINT_L2("Saving unsigned tx data: " << oss.str());
if (!::serialization::dump_binary(txs, s)) return epee::file_io_utils::save_string_to_file(filename, std::string(UNSIGNED_TX_PREFIX) + oss.str());
return false;
return epee::file_io_utils::save_string_to_file(filename, std::string(UNSIGNED_TX_PREFIX) + s);
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
bool wallet2::sign_tx(const std::string &unsigned_filename, const std::string &signed_filename, std::vector<wallet2::pending_tx> &txs, std::function<bool(const unsigned_tx_set&)> accept_func) bool wallet2::sign_tx(const std::string &unsigned_filename, const std::string &signed_filename, std::vector<wallet2::pending_tx> &txs, std::function<bool(const unsigned_tx_set&)> accept_func)
@ -3050,7 +3055,14 @@ bool wallet2::sign_tx(const std::string &unsigned_filename, const std::string &s
return false; return false;
} }
unsigned_tx_set exported_txs; unsigned_tx_set exported_txs;
if (!::serialization::parse_binary(std::string(s.c_str() + magiclen, s.size() - magiclen), exported_txs)) s = s.substr(magiclen);
try
{
std::istringstream iss(s);
boost::archive::portable_binary_iarchive ar(iss);
ar >> exported_txs;
}
catch (...)
{ {
LOG_PRINT_L0("Failed to parse data from " << unsigned_filename); LOG_PRINT_L0("Failed to parse data from " << unsigned_filename);
return false; return false;
@ -3123,14 +3135,19 @@ bool wallet2::sign_tx(const std::string &unsigned_filename, const std::string &s
signed_txes.key_images[i] = m_transfers[i].m_key_image; signed_txes.key_images[i] = m_transfers[i].m_key_image;
} }
s = obj_to_json_str(signed_txes); // save as binary
if (s.empty()) std::ostringstream oss;
boost::archive::portable_binary_oarchive ar(oss);
try
{
ar << signed_txes;
}
catch(...)
{
return false; return false;
LOG_PRINT_L2("Saving signed tx data: " << s); }
// save as binary as there's no implementation of loading a json_archive LOG_PRINT_L2("Saving signed tx data: " << oss.str());
if (!::serialization::dump_binary(signed_txes, s)) return epee::file_io_utils::save_string_to_file(signed_filename, std::string(SIGNED_TX_PREFIX) + oss.str());
return false;
return epee::file_io_utils::save_string_to_file(signed_filename, std::string(SIGNED_TX_PREFIX) + s);
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
bool wallet2::load_tx(const std::string &signed_filename, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set&)> accept_func) bool wallet2::load_tx(const std::string &signed_filename, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set&)> accept_func)
@ -3156,7 +3173,14 @@ bool wallet2::load_tx(const std::string &signed_filename, std::vector<tools::wal
LOG_PRINT_L0("Bad magic from " << signed_filename); LOG_PRINT_L0("Bad magic from " << signed_filename);
return false; return false;
} }
if (!::serialization::parse_binary(std::string(s.c_str() + magiclen, s.size() - magiclen), signed_txs)) s = s.substr(magiclen);
try
{
std::istringstream iss(s);
boost::archive::portable_binary_iarchive ar(iss);
ar >> signed_txs;
}
catch (...)
{ {
LOG_PRINT_L0("Failed to parse data from " << signed_filename); LOG_PRINT_L0("Failed to parse data from " << signed_filename);
return false; return false;

View File

@ -201,17 +201,6 @@ namespace tools
uint64_t unlock_time; uint64_t unlock_time;
bool use_rct; bool use_rct;
std::vector<cryptonote::tx_destination_entry> dests; // original setup, does not include change std::vector<cryptonote::tx_destination_entry> dests; // original setup, does not include change
BEGIN_SERIALIZE_OBJECT()
FIELD(sources)
FIELD(change_dts)
FIELD(splitted_dsts)
FIELD(selected_transfers)
FIELD(extra)
VARINT_FIELD(unlock_time)
FIELD(use_rct)
FIELD(dests)
END_SERIALIZE()
}; };
typedef std::vector<transfer_details> transfer_container; typedef std::vector<transfer_details> transfer_container;
@ -232,39 +221,18 @@ namespace tools
std::vector<cryptonote::tx_destination_entry> dests; std::vector<cryptonote::tx_destination_entry> dests;
tx_construction_data construction_data; tx_construction_data construction_data;
BEGIN_SERIALIZE_OBJECT()
FIELD(tx)
VARINT_FIELD(dust)
VARINT_FIELD(fee)
FIELD(dust_added_to_fee)
FIELD(change_dts)
FIELD(selected_transfers)
FIELD(key_images)
FIELD(tx_key)
FIELD(dests)
FIELD(construction_data)
END_SERIALIZE()
}; };
struct unsigned_tx_set struct unsigned_tx_set
{ {
std::vector<tx_construction_data> txes; std::vector<tx_construction_data> txes;
wallet2::transfer_container transfers; wallet2::transfer_container transfers;
BEGIN_SERIALIZE_OBJECT()
FIELD(txes)
FIELD(transfers)
END_SERIALIZE()
}; };
struct signed_tx_set struct signed_tx_set
{ {
std::vector<pending_tx> ptx; std::vector<pending_tx> ptx;
std::vector<crypto::key_image> key_images; std::vector<crypto::key_image> key_images;
BEGIN_SERIALIZE_OBJECT()
FIELD(ptx)
FIELD(key_images)
END_SERIALIZE()
}; };
struct keys_file_data struct keys_file_data
@ -672,6 +640,10 @@ BOOST_CLASS_VERSION(tools::wallet2::payment_details, 1)
BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 6) BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 6)
BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 3) BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 3)
BOOST_CLASS_VERSION(tools::wallet2::address_book_row, 16) BOOST_CLASS_VERSION(tools::wallet2::address_book_row, 16)
BOOST_CLASS_VERSION(tools::wallet2::unsigned_tx_set, 0)
BOOST_CLASS_VERSION(tools::wallet2::signed_tx_set, 0)
BOOST_CLASS_VERSION(tools::wallet2::tx_construction_data, 0)
BOOST_CLASS_VERSION(tools::wallet2::pending_tx, 0)
namespace boost namespace boost
{ {
@ -869,6 +841,48 @@ namespace boost
a & x.m_payment_id; a & x.m_payment_id;
a & x.m_description; a & x.m_description;
} }
template <class Archive>
inline void serialize(Archive &a, tools::wallet2::unsigned_tx_set &x, const boost::serialization::version_type ver)
{
a & x.txes;
a & x.transfers;
}
template <class Archive>
inline void serialize(Archive &a, tools::wallet2::signed_tx_set &x, const boost::serialization::version_type ver)
{
a & x.ptx;
a & x.key_images;
}
template <class Archive>
inline void serialize(Archive &a, tools::wallet2::tx_construction_data &x, const boost::serialization::version_type ver)
{
a & x.sources;
a & x.change_dts;
a & x.splitted_dsts;
a & x.selected_transfers;
a & x.extra;
a & x.unlock_time;
a & x.use_rct;
a & x.dests;
}
template <class Archive>
inline void serialize(Archive &a, tools::wallet2::pending_tx &x, const boost::serialization::version_type ver)
{
a & x.tx;
a & x.dust;
a & x.fee;
a & x.dust_added_to_fee;
a & x.change_dts;
a & x.selected_transfers;
a & x.key_images;
a & x.tx_key;
a & x.dests;
a & x.construction_data;
}
} }
} }