replace most boost serialization with existing monero serialization

This reduces the attack surface for data that can come from
malicious sources (exported output and key images, multisig
transactions...) since the monero serialization is already
exposed to the outside, and the boost lib we were using had
a few known crashers.

For interoperability, a new load-deprecated-formats wallet
setting is added (off by default). This allows loading boost
format data if there is no alternative. It will likely go
at some point, along with the ability to load those.

Notably, the peer lists file still uses the boost serialization
code, as the data it stores is define in epee, while the new
serialization code is in monero, and migrating it was fairly
hairy. Since this file is local and not obtained from anyone
else, the marginal risk is minimal, but it could be migrated
later if needed.

Some tests and tools also do, this will stay as is for now.
This commit is contained in:
moneromooo-monero 2020-06-24 23:26:58 +00:00
parent 43a4fd9e16
commit 7175dcb107
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3
34 changed files with 837 additions and 392 deletions

View file

@ -28,8 +28,6 @@
#include <boost/range/adaptor/transformed.hpp> #include <boost/range/adaptor/transformed.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/archive/portable_binary_iarchive.hpp>
#include <boost/archive/portable_binary_oarchive.hpp>
#include "common/unordered_containers_boost_serialization.h" #include "common/unordered_containers_boost_serialization.h"
#include "common/command_line.h" #include "common/command_line.h"
#include "common/varint.h" #include "common/varint.h"

View file

@ -37,7 +37,7 @@
#include <sstream> #include <sstream>
#include <atomic> #include <atomic>
#include "serialization/variant.h" #include "serialization/variant.h"
#include "serialization/vector.h" #include "serialization/containers.h"
#include "serialization/binary_archive.h" #include "serialization/binary_archive.h"
#include "serialization/json_archive.h" #include "serialization/json_archive.h"
#include "serialization/debug_archive.h" #include "serialization/debug_archive.h"

View file

@ -34,7 +34,6 @@ using namespace epee;
#include "cryptonote_basic_impl.h" #include "cryptonote_basic_impl.h"
#include "string_tools.h" #include "string_tools.h"
#include "serialization/binary_utils.h" #include "serialization/binary_utils.h"
#include "serialization/container.h"
#include "cryptonote_format_utils.h" #include "cryptonote_format_utils.h"
#include "cryptonote_config.h" #include "cryptonote_config.h"
#include "misc_language.h" #include "misc_language.h"

View file

@ -36,7 +36,6 @@
#include <boost/serialization/set.hpp> #include <boost/serialization/set.hpp>
#include <boost/serialization/map.hpp> #include <boost/serialization/map.hpp>
#include <boost/serialization/is_bitwise_serializable.hpp> #include <boost/serialization/is_bitwise_serializable.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/portable_binary_iarchive.hpp> #include <boost/archive/portable_binary_iarchive.hpp>
#include <boost/archive/portable_binary_oarchive.hpp> #include <boost/archive/portable_binary_oarchive.hpp>
#include "cryptonote_basic.h" #include "cryptonote_basic.h"

View file

@ -39,6 +39,7 @@
#include "misc_language.h" #include "misc_language.h"
#include "string_tools.h" #include "string_tools.h"
#include "time_helper.h" #include "time_helper.h"
#include "serialization/serialization.h"
#include "cryptonote_config.h" #include "cryptonote_config.h"
namespace nodetool namespace nodetool
@ -84,6 +85,15 @@ namespace nodetool
KV_SERIALIZE_OPT(rpc_port, (uint16_t)0) KV_SERIALIZE_OPT(rpc_port, (uint16_t)0)
KV_SERIALIZE_OPT(rpc_credits_per_hash, (uint32_t)0) KV_SERIALIZE_OPT(rpc_credits_per_hash, (uint32_t)0)
END_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP()
BEGIN_SERIALIZE()
FIELD(adr)
FIELD(id)
VARINT_FIELD(last_seen)
VARINT_FIELD(pruning_seed)
VARINT_FIELD(rpc_port)
VARINT_FIELD(rpc_credits_per_hash)
END_SERIALIZE()
}; };
typedef peerlist_entry_base<epee::net_utils::network_address> peerlist_entry; typedef peerlist_entry_base<epee::net_utils::network_address> peerlist_entry;
@ -99,6 +109,12 @@ namespace nodetool
KV_SERIALIZE(id) KV_SERIALIZE(id)
KV_SERIALIZE(first_seen) KV_SERIALIZE(first_seen)
END_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP()
BEGIN_SERIALIZE()
FIELD(adr)
FIELD(id)
VARINT_FIELD(first_seen)
END_SERIALIZE()
}; };
typedef anchor_peerlist_entry_base<epee::net_utils::network_address> anchor_peerlist_entry; typedef anchor_peerlist_entry_base<epee::net_utils::network_address> anchor_peerlist_entry;
@ -114,6 +130,12 @@ namespace nodetool
KV_SERIALIZE(id) KV_SERIALIZE(id)
KV_SERIALIZE(is_income) KV_SERIALIZE(is_income)
END_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP()
BEGIN_SERIALIZE()
FIELD(adr)
FIELD(id)
FIELD(is_income)
END_SERIALIZE()
}; };
typedef connection_entry_base<epee::net_utils::network_address> connection_entry; typedef connection_entry_base<epee::net_utils::network_address> connection_entry;

View file

@ -49,7 +49,7 @@ extern "C" {
#include "hex.h" #include "hex.h"
#include "span.h" #include "span.h"
#include "memwipe.h" #include "memwipe.h"
#include "serialization/vector.h" #include "serialization/containers.h"
#include "serialization/debug_archive.h" #include "serialization/debug_archive.h"
#include "serialization/binary_archive.h" #include "serialization/binary_archive.h"
#include "serialization/json_archive.h" #include "serialization/json_archive.h"
@ -239,6 +239,12 @@ namespace rct {
struct RCTConfig { struct RCTConfig {
RangeProofType range_proof_type; RangeProofType range_proof_type;
int bp_version; int bp_version;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
VARINT_FIELD(range_proof_type)
VARINT_FIELD(bp_version)
END_SERIALIZE()
}; };
struct rctSigBase { struct rctSigBase {
uint8_t type; uint8_t type;
@ -317,6 +323,16 @@ namespace rct {
ar.end_array(); ar.end_array();
return ar.stream().good(); return ar.stream().good();
} }
BEGIN_SERIALIZE_OBJECT()
FIELD(type)
FIELD(message)
FIELD(mixRing)
FIELD(pseudoOuts)
FIELD(ecdhInfo)
FIELD(outPk)
VARINT_FIELD(txnFee)
END_SERIALIZE()
}; };
struct rctSigPrunable { struct rctSigPrunable {
std::vector<rangeSig> rangeSigs; std::vector<rangeSig> rangeSigs;
@ -436,6 +452,12 @@ namespace rct {
return ar.stream().good(); return ar.stream().good();
} }
BEGIN_SERIALIZE_OBJECT()
FIELD(rangeSigs)
FIELD(bulletproofs)
FIELD(MGs)
FIELD(pseudoOuts)
END_SERIALIZE()
}; };
struct rctSig: public rctSigBase { struct rctSig: public rctSigBase {
rctSigPrunable p; rctSigPrunable p;
@ -449,6 +471,11 @@ namespace rct {
{ {
return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 ? p.pseudoOuts : pseudoOuts; return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 ? p.pseudoOuts : pseudoOuts;
} }
BEGIN_SERIALIZE_OBJECT()
FIELDS((rctSigBase&)*this)
FIELD(p)
END_SERIALIZE()
}; };
//other basepoint H = toPoint(cn_fast_hash(G)), G the basepoint //other basepoint H = toPoint(cn_fast_hash(G)), G the basepoint

View file

@ -27,14 +27,12 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/archive/portable_binary_iarchive.hpp> #include <boost/archive/portable_binary_iarchive.hpp>
#include <boost/archive/portable_binary_oarchive.hpp>
#include "cryptonote_config.h" #include "cryptonote_config.h"
#include "include_base_utils.h" #include "include_base_utils.h"
#include "string_tools.h" #include "string_tools.h"
#include "file_io_utils.h" #include "file_io_utils.h"
#include "int-util.h" #include "int-util.h"
#include "common/util.h" #include "common/util.h"
#include "serialization/crypto.h"
#include "common/unordered_containers_boost_serialization.h" #include "common/unordered_containers_boost_serialization.h"
#include "cryptonote_basic/cryptonote_boost_serialization.h" #include "cryptonote_basic/cryptonote_boost_serialization.h"
#include "cryptonote_basic/cryptonote_format_utils.h" #include "cryptonote_basic/cryptonote_format_utils.h"
@ -295,15 +293,29 @@ namespace cryptonote
std::ifstream data; std::ifstream data;
data.open(state_file_path, std::ios_base::binary | std::ios_base::in); data.open(state_file_path, std::ios_base::binary | std::ios_base::in);
if (!data.fail()) if (!data.fail())
{
bool loaded = false;
try
{
binary_archive<false> ar(data);
if (::serialization::serialize(ar, *this))
if (::serialization::check_stream_state(ar))
loaded = true;
}
catch (...) {}
if (!loaded)
{ {
try try
{ {
boost::archive::portable_binary_iarchive a(data); boost::archive::portable_binary_iarchive a(data);
a >> *this; a >> *this;
loaded = true;
} }
catch (const std::exception &e) catch (...) {}
}
if (!loaded)
{ {
MERROR("Failed to load RPC payments file: " << e.what()); MERROR("Failed to load RPC payments file");
m_client_info.clear(); m_client_info.clear();
} }
} }
@ -344,8 +356,9 @@ namespace cryptonote
MWARNING("Failed to save RPC payments to file " << state_file_path); MWARNING("Failed to save RPC payments to file " << state_file_path);
return false; return false;
}; };
boost::archive::portable_binary_oarchive a(data); binary_archive<true> ar(data);
a << *this; if (!::serialization::serialize(ar, *const_cast<rpc_payment*>(this)))
return false;
return true; return true;
CATCH_ENTRY_L0("rpc_payment::store", false); CATCH_ENTRY_L0("rpc_payment::store", false);
} }

View file

@ -31,10 +31,17 @@
#include <string> #include <string>
#include <unordered_set> #include <unordered_set>
#include <unordered_map> #include <unordered_map>
#include <map>
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <boost/serialization/version.hpp> #include <boost/serialization/version.hpp>
#include "cryptonote_basic/blobdatatype.h" #include "cryptonote_basic/blobdatatype.h"
#include "cryptonote_basic/cryptonote_basic.h" #include "cryptonote_basic/cryptonote_basic.h"
#include <boost/serialization/list.hpp>
#include <boost/serialization/vector.hpp>
#include "serialization/crypto.h"
#include "serialization/string.h"
#include "serialization/pair.h"
#include "serialization/containers.h"
namespace cryptonote namespace cryptonote
{ {
@ -96,6 +103,33 @@ namespace cryptonote
a & nonces_bad; a & nonces_bad;
a & nonces_dupe; a & nonces_dupe;
} }
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
FIELD(block)
FIELD(previous_block)
FIELD(hashing_blob)
FIELD(previous_hashing_blob)
VARINT_FIELD(seed_height)
VARINT_FIELD(previous_seed_height)
FIELD(seed_hash)
FIELD(previous_seed_hash)
VARINT_FIELD(cookie)
FIELD(top)
FIELD(previous_top)
VARINT_FIELD(credits)
FIELD(payments)
FIELD(previous_payments)
FIELD(update_time)
FIELD(last_request_timestamp)
FIELD(block_template_update_time)
VARINT_FIELD(credits_total)
VARINT_FIELD(credits_used)
VARINT_FIELD(nonces_good)
VARINT_FIELD(nonces_stale)
VARINT_FIELD(nonces_bad)
VARINT_FIELD(nonces_dupe)
END_SERIALIZE()
}; };
public: public:
@ -114,8 +148,8 @@ namespace cryptonote
template <class t_archive> template <class t_archive>
inline void serialize(t_archive &a, const unsigned int ver) inline void serialize(t_archive &a, const unsigned int ver)
{ {
a & m_client_info; a & m_client_info.parent();
a & m_hashrate; a & m_hashrate.parent();
a & m_credits_total; a & m_credits_total;
a & m_credits_used; a & m_credits_used;
a & m_nonces_good; a & m_nonces_good;
@ -124,6 +158,18 @@ namespace cryptonote
a & m_nonces_dupe; a & m_nonces_dupe;
} }
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
FIELD(m_client_info)
FIELD(m_hashrate)
VARINT_FIELD(m_credits_total)
VARINT_FIELD(m_credits_used)
VARINT_FIELD(m_nonces_good)
VARINT_FIELD(m_nonces_stale)
VARINT_FIELD(m_nonces_bad)
VARINT_FIELD(m_nonces_dupe)
END_SERIALIZE()
bool load(std::string directory); bool load(std::string directory);
bool store(const std::string &directory = std::string()) const; bool store(const std::string &directory = std::string()) const;
@ -131,9 +177,9 @@ namespace cryptonote
cryptonote::account_public_address m_address; cryptonote::account_public_address m_address;
uint64_t m_diff; uint64_t m_diff;
uint64_t m_credits_per_hash_found; uint64_t m_credits_per_hash_found;
std::unordered_map<crypto::public_key, client_info> m_client_info; serializable_unordered_map<crypto::public_key, client_info> m_client_info;
std::string m_directory; std::string m_directory;
std::map<uint64_t, uint64_t> m_hashrate; serializable_map<uint64_t, uint64_t> m_hashrate;
uint64_t m_credits_total; uint64_t m_credits_total;
uint64_t m_credits_used; uint64_t m_credits_used;
uint64_t m_nonces_good; uint64_t m_nonces_good;
@ -143,6 +189,3 @@ namespace cryptonote
mutable boost::mutex mutex; mutable boost::mutex mutex;
}; };
} }
BOOST_CLASS_VERSION(cryptonote::rpc_payment, 0);
BOOST_CLASS_VERSION(cryptonote::rpc_payment::client_info, 0);

View file

@ -28,10 +28,6 @@
// //
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
#include "serialization.h"
namespace serialization namespace serialization
{ {
namespace detail namespace detail
@ -103,7 +99,7 @@ bool do_serialize_container(Archive<true> &ar, C &v)
return false; return false;
if (i != v.begin()) if (i != v.begin())
ar.delimit_array(); ar.delimit_array();
if(!::serialization::detail::serialize_container_element(ar, const_cast<typename C::value_type&>(*i))) if(!::serialization::detail::serialize_container_element(ar, (typename C::value_type&)*i))
return false; return false;
if (!ar.stream().good()) if (!ar.stream().good())
return false; return false;

View file

@ -0,0 +1,128 @@
// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
#include <vector>
#include <deque>
#include <unordered_map>
#include <map>
#include <unordered_set>
#include <set>
#include "serialization.h"
template <template <bool> class Archive, class T> bool do_serialize(Archive<false> &ar, std::vector<T> &v);
template <template <bool> class Archive, class T> bool do_serialize(Archive<true> &ar, std::vector<T> &v);
template <template <bool> class Archive, class T> bool do_serialize(Archive<false> &ar, std::deque<T> &v);
template <template <bool> class Archive, class T> bool do_serialize(Archive<true> &ar, std::deque<T> &v);
template<typename K, typename V>
class serializable_unordered_map: public std::unordered_map<K, V>
{
public:
typedef typename std::pair<K, V> value_type;
typename std::unordered_map<K, V> &parent() { return *this; }
};
template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<false> &ar, serializable_unordered_map<K, V> &v);
template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<true> &ar, serializable_unordered_map<K, V> &v);
template<typename K, typename V>
class serializable_map: public std::map<K, V>
{
public:
typedef typename std::pair<K, V> value_type;
typename std::map<K, V> &parent() { return *this; }
};
template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<false> &ar, serializable_map<K, V> &v);
template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<true> &ar, serializable_map<K, V> &v);
template<typename K, typename V>
class serializable_unordered_multimap: public std::unordered_multimap<K, V>
{
public:
typedef typename std::pair<K, V> value_type;
typename std::unordered_multimap<K, V> &parent() { return *this; }
};
template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<false> &ar, serializable_unordered_multimap<K, V> &v);
template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<true> &ar, serializable_unordered_multimap<K, V> &v);
template <template <bool> class Archive, class T> bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v);
template <template <bool> class Archive, class T> bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v);
template <template <bool> class Archive, class T> bool do_serialize(Archive<false> &ar, std::set<T> &v);
template <template <bool> class Archive, class T> bool do_serialize(Archive<true> &ar, std::set<T> &v);
namespace serialization
{
namespace detail
{
template <typename T> void do_reserve(std::vector<T> &c, size_t N) { c.reserve(N); }
template <typename T> void do_add(std::vector<T> &c, T &&e) { c.emplace_back(std::forward<T>(e)); }
template <typename T> void do_add(std::deque<T> &c, T &&e) { c.emplace_back(std::forward<T>(e)); }
template <typename K, typename V> void do_add(serializable_unordered_map<K, V> &c, std::pair<K, V> &&e) { c.insert(std::forward<std::pair<K, V>>(e)); }
template <typename K, typename V> void do_add(serializable_map<K, V> &c, std::pair<K, V> &&e) { c.insert(std::forward<std::pair<K, V>>(e)); }
template <typename K, typename V> void do_add(serializable_unordered_multimap<K, V> &c, std::pair<K, V> &&e) { c.insert(std::forward<std::pair<K, V>>(e)); }
template <typename T> void do_add(std::unordered_set<T> &c, T &&e) { c.insert(std::forward<T>(e)); }
template <typename T> void do_add(std::set<T> &c, T &&e) { c.insert(std::forward<T>(e)); }
}
}
#include "container.h"
template <template <bool> class Archive, class T> bool do_serialize(Archive<false> &ar, std::vector<T> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, class T> bool do_serialize(Archive<true> &ar, std::vector<T> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, class T> bool do_serialize(Archive<false> &ar, std::deque<T> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, class T> bool do_serialize(Archive<true> &ar, std::deque<T> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<false> &ar, serializable_unordered_map<K, V> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<true> &ar, serializable_unordered_map<K, V> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<false> &ar, serializable_map<K, V> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<true> &ar, serializable_map<K, V> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<false> &ar, serializable_unordered_multimap<K, V> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<true> &ar, serializable_unordered_multimap<K, V> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, class T> bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, class T> bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, class T> bool do_serialize(Archive<false> &ar, std::set<T> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, class T> bool do_serialize(Archive<true> &ar, std::set<T> &v) { return do_serialize_container(ar, v); }

View file

@ -1,64 +0,0 @@
// Copyright (c) 2014-2020, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
#include <deque>
template <template <bool> class Archive, class T>
bool do_serialize(Archive<false> &ar, std::deque<T> &v);
template <template <bool> class Archive, class T>
bool do_serialize(Archive<true> &ar, std::deque<T> &v);
namespace serialization
{
namespace detail
{
template <typename T>
void do_reserve(std::deque<T> &c, size_t N)
{
c.reserve(N);
}
template <typename T>
void do_add(std::deque<T> &c, T &&e)
{
c.emplace_back(std::move(e));
}
}
}
#include "serialization.h"
template <template <bool> class Archive, class T>
bool do_serialize(Archive<false> &ar, std::deque<T> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, class T>
bool do_serialize(Archive<true> &ar, std::deque<T> &v) { return do_serialize_container(ar, v); }

View file

@ -44,7 +44,7 @@ namespace serialization
template <typename T> template <typename T>
void do_add(std::list<T> &c, T &&e) void do_add(std::list<T> &c, T &&e)
{ {
c.emplace_back(std::move(e)); c.emplace_back(std::forward<T>(e));
} }
} }
} }

View file

@ -48,6 +48,7 @@
#include <string> #include <string>
#include <boost/type_traits/is_integral.hpp> #include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/integral_constant.hpp> #include <boost/type_traits/integral_constant.hpp>
#include <boost/mpl/bool.hpp>
/*! \struct is_blob_type /*! \struct is_blob_type
* *
@ -278,6 +279,27 @@ inline bool do_serialize(Archive &ar, bool &v)
if (!ar.stream().good()) return false; \ if (!ar.stream().good()) return false; \
} while(0); } while(0);
/*! \macro MAGIC_FIELD(m)
*/
#define MAGIC_FIELD(m) \
std::string magic = m; \
do { \
ar.tag("magic"); \
ar.serialize_blob((void*)magic.data(), magic.size()); \
if (!ar.stream().good()) return false; \
if (magic != m) return false; \
} while(0);
/*! \macro VERSION_FIELD(v)
*/
#define VERSION_FIELD(v) \
uint32_t version = v; \
do { \
ar.tag("version"); \
ar.serialize_varint(version); \
if (!ar.stream().good()) return false; \
} while(0);
namespace serialization { namespace serialization {
/*! \namespace detail /*! \namespace detail

View file

@ -1,58 +0,0 @@
// Copyright (c) 2014-2020, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
#include <set>
template <template <bool> class Archive, class T>
bool do_serialize(Archive<false> &ar, std::set<T> &v);
template <template <bool> class Archive, class T>
bool do_serialize(Archive<true> &ar, std::set<T> &v);
namespace serialization
{
namespace detail
{
template <typename T>
void do_add(std::set<T> &c, T &&e)
{
c.insert(std::move(e));
}
}
}
#include "serialization.h"
template <template <bool> class Archive, class T>
bool do_serialize(Archive<false> &ar, std::set<T> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, class T>
bool do_serialize(Archive<true> &ar, std::set<T> &v) { return do_serialize_container(ar, v); }

View file

@ -1,58 +0,0 @@
// Copyright (c) 2014-2020, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
#include <set>
template <template <bool> class Archive, class T>
bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v);
template <template <bool> class Archive, class T>
bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v);
namespace serialization
{
namespace detail
{
template <typename T>
void do_add(std::unordered_set<T> &c, T &&e)
{
c.insert(std::move(e));
}
}
}
#include "serialization.h"
template <template <bool> class Archive, class T>
bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, class T>
bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v) { return do_serialize_container(ar, v); }

View file

@ -1,65 +0,0 @@
// Copyright (c) 2014-2020, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
#include <vector>
#include "serialization.h"
template <template <bool> class Archive, class T>
bool do_serialize(Archive<false> &ar, std::vector<T> &v);
template <template <bool> class Archive, class T>
bool do_serialize(Archive<true> &ar, std::vector<T> &v);
namespace serialization
{
namespace detail
{
template <typename T>
void do_reserve(std::vector<T> &c, size_t N)
{
c.reserve(N);
}
template <typename T>
void do_add(std::vector<T> &c, T &&e)
{
c.emplace_back(std::move(e));
}
}
}
#include "container.h"
template <template <bool> class Archive, class T>
bool do_serialize(Archive<false> &ar, std::vector<T> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, class T>
bool do_serialize(Archive<true> &ar, std::vector<T> &v) { return do_serialize_container(ar, v); }

View file

@ -3100,6 +3100,28 @@ bool simple_wallet::set_export_format(const std::vector<std::string> &args/* = s
return true; return true;
} }
bool simple_wallet::set_load_deprecated_formats(const std::vector<std::string> &args/* = std::vector<std::string()*/)
{
if (args.size() < 2)
{
fail_msg_writer() << tr("Value not specified");
return true;
}
const auto pwd_container = get_and_verify_password();
if (pwd_container)
{
parse_bool_and_use(args[1], [&](bool r) {
m_wallet->load_deprecated_formats(r);
m_wallet->rewrite(m_wallet_file, pwd_container->password());
if (r)
message_writer() << tr("Warning: deprecated formats use boost serialization, which has buffer overflows and crashers. Only load deprecated formats from sources you trust.");
});
}
return true;
}
bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<std::string>()*/) bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{ {
if(args.empty()) if(args.empty())
@ -3789,6 +3811,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
success_msg_writer() << "persistent-rpc-client-id = " << m_wallet->persistent_rpc_client_id(); success_msg_writer() << "persistent-rpc-client-id = " << m_wallet->persistent_rpc_client_id();
success_msg_writer() << "auto-mine-for-rpc-payment-threshold = " << m_wallet->auto_mine_for_rpc_payment_threshold(); success_msg_writer() << "auto-mine-for-rpc-payment-threshold = " << m_wallet->auto_mine_for_rpc_payment_threshold();
success_msg_writer() << "credits-target = " << m_wallet->credits_target(); success_msg_writer() << "credits-target = " << m_wallet->credits_target();
success_msg_writer() << "load-deprecated-formats = " << m_wallet->load_deprecated_formats();
return true; return true;
} }
else else
@ -3850,6 +3873,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
CHECK_SIMPLE_VARIABLE("setup-background-mining", set_setup_background_mining, tr("1/yes or 0/no")); CHECK_SIMPLE_VARIABLE("setup-background-mining", set_setup_background_mining, tr("1/yes or 0/no"));
CHECK_SIMPLE_VARIABLE("device-name", set_device_name, tr("<device_name[:device_spec]>")); CHECK_SIMPLE_VARIABLE("device-name", set_device_name, tr("<device_name[:device_spec]>"));
CHECK_SIMPLE_VARIABLE("export-format", set_export_format, tr("\"binary\" or \"ascii\"")); CHECK_SIMPLE_VARIABLE("export-format", set_export_format, tr("\"binary\" or \"ascii\""));
CHECK_SIMPLE_VARIABLE("load-deprecated-formats", set_load_deprecated_formats, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("persistent-rpc-client-id", set_persistent_rpc_client_id, tr("0 or 1")); CHECK_SIMPLE_VARIABLE("persistent-rpc-client-id", set_persistent_rpc_client_id, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("auto-mine-for-rpc-payment-threshold", set_auto_mine_for_rpc_payment_threshold, tr("floating point >= 0")); CHECK_SIMPLE_VARIABLE("auto-mine-for-rpc-payment-threshold", set_auto_mine_for_rpc_payment_threshold, tr("floating point >= 0"));
CHECK_SIMPLE_VARIABLE("credits-target", set_credits_target, tr("unsigned integer")); CHECK_SIMPLE_VARIABLE("credits-target", set_credits_target, tr("unsigned integer"));

View file

@ -151,6 +151,7 @@ namespace cryptonote
bool set_setup_background_mining(const std::vector<std::string> &args = std::vector<std::string>()); bool set_setup_background_mining(const std::vector<std::string> &args = std::vector<std::string>());
bool set_device_name(const std::vector<std::string> &args = std::vector<std::string>()); bool set_device_name(const std::vector<std::string> &args = std::vector<std::string>());
bool set_export_format(const std::vector<std::string> &args = std::vector<std::string>()); bool set_export_format(const std::vector<std::string> &args = std::vector<std::string>());
bool set_load_deprecated_formats(const std::vector<std::string> &args = std::vector<std::string>());
bool set_persistent_rpc_client_id(const std::vector<std::string> &args = std::vector<std::string>()); bool set_persistent_rpc_client_id(const std::vector<std::string> &args = std::vector<std::string>());
bool set_auto_mine_for_rpc_payment_threshold(const std::vector<std::string> &args = std::vector<std::string>()); bool set_auto_mine_for_rpc_payment_threshold(const std::vector<std::string> &args = std::vector<std::string>());
bool set_credits_target(const std::vector<std::string> &args = std::vector<std::string>()); bool set_credits_target(const std::vector<std::string> &args = std::vector<std::string>());

View file

@ -27,7 +27,6 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "message_store.h" #include "message_store.h"
#include <boost/archive/portable_binary_oarchive.hpp>
#include <boost/archive/portable_binary_iarchive.hpp> #include <boost/archive/portable_binary_iarchive.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@ -182,8 +181,8 @@ bool message_store::signer_labels_complete() const
void message_store::get_signer_config(std::string &signer_config) void message_store::get_signer_config(std::string &signer_config)
{ {
std::stringstream oss; std::stringstream oss;
boost::archive::portable_binary_oarchive ar(oss); binary_archive<true> ar(oss);
ar << m_signers; THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, m_signers), tools::error::wallet_internal_error, "Failed to serialize signer config");
signer_config = oss.str(); signer_config = oss.str();
} }
@ -194,8 +193,8 @@ void message_store::unpack_signer_config(const multisig_wallet_state &state, con
{ {
std::stringstream iss; std::stringstream iss;
iss << signer_config; iss << signer_config;
boost::archive::portable_binary_iarchive ar(iss); binary_archive<false> ar(iss);
ar >> signers; THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, signers), tools::error::wallet_internal_error, "Failed to serialize signer config");
} }
catch (...) catch (...)
{ {
@ -364,8 +363,8 @@ size_t message_store::add_auto_config_data_message(const multisig_wallet_state &
data.monero_address = me.monero_address; data.monero_address = me.monero_address;
std::stringstream oss; std::stringstream oss;
boost::archive::portable_binary_oarchive ar(oss); binary_archive<true> ar(oss);
ar << data; THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, data), tools::error::wallet_internal_error, "Failed to serialize auto config data");
return add_message(state, 0, message_type::auto_config_data, message_direction::out, oss.str()); return add_message(state, 0, message_type::auto_config_data, message_direction::out, oss.str());
} }
@ -384,8 +383,8 @@ void message_store::process_auto_config_data_message(uint32_t id)
{ {
std::stringstream iss; std::stringstream iss;
iss << m.content; iss << m.content;
boost::archive::portable_binary_iarchive ar(iss); binary_archive<false> ar(iss);
ar >> data; THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, data), tools::error::wallet_internal_error, "Failed to serialize auto config data");
} }
catch (...) catch (...)
{ {
@ -745,8 +744,8 @@ std::string message_store::get_sanitized_text(const std::string &text, size_t ma
void message_store::write_to_file(const multisig_wallet_state &state, const std::string &filename) void message_store::write_to_file(const multisig_wallet_state &state, const std::string &filename)
{ {
std::stringstream oss; std::stringstream oss;
boost::archive::portable_binary_oarchive ar(oss); binary_archive<true> ar(oss);
ar << *this; THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, *this), tools::error::wallet_internal_error, "Failed to serialize MMS state");
std::string buf = oss.str(); std::string buf = oss.str();
crypto::chacha_key key; crypto::chacha_key key;
@ -762,14 +761,14 @@ void message_store::write_to_file(const multisig_wallet_state &state, const std:
write_file_data.encrypted_data = encrypted_data; write_file_data.encrypted_data = encrypted_data;
std::stringstream file_oss; std::stringstream file_oss;
boost::archive::portable_binary_oarchive file_ar(file_oss); binary_archive<true> file_ar(file_oss);
file_ar << write_file_data; THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(file_ar, write_file_data), tools::error::wallet_internal_error, "Failed to serialize MMS state");
bool success = epee::file_io_utils::save_string_to_file(filename, file_oss.str()); bool success = epee::file_io_utils::save_string_to_file(filename, file_oss.str());
THROW_WALLET_EXCEPTION_IF(!success, tools::error::file_save_error, filename); THROW_WALLET_EXCEPTION_IF(!success, tools::error::file_save_error, filename);
} }
void message_store::read_from_file(const multisig_wallet_state &state, const std::string &filename) void message_store::read_from_file(const multisig_wallet_state &state, const std::string &filename, bool load_deprecated_formats)
{ {
boost::system::error_code ignored_ec; boost::system::error_code ignored_ec;
bool file_exists = boost::filesystem::exists(filename, ignored_ec); bool file_exists = boost::filesystem::exists(filename, ignored_ec);
@ -785,19 +784,39 @@ void message_store::read_from_file(const multisig_wallet_state &state, const std
bool success = epee::file_io_utils::load_file_to_string(filename, buf); bool success = epee::file_io_utils::load_file_to_string(filename, buf);
THROW_WALLET_EXCEPTION_IF(!success, tools::error::file_read_error, filename); THROW_WALLET_EXCEPTION_IF(!success, tools::error::file_read_error, filename);
bool loaded = false;
file_data read_file_data; file_data read_file_data;
try
{
std::stringstream iss;
iss << buf;
binary_archive<false> ar(iss);
if (::serialization::serialize(ar, read_file_data))
if (::serialization::check_stream_state(ar))
loaded = true;
}
catch (...) {}
if (!loaded && load_deprecated_formats)
{
try try
{ {
std::stringstream iss; std::stringstream iss;
iss << buf; iss << buf;
boost::archive::portable_binary_iarchive ar(iss); boost::archive::portable_binary_iarchive ar(iss);
ar >> read_file_data; ar >> read_file_data;
loaded = true;
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {
MERROR("MMS file " << filename << " has bad structure <iv,encrypted_data>: " << e.what()); MERROR("MMS file " << filename << " has bad structure <iv,encrypted_data>: " << e.what());
THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename); THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename);
} }
}
if (!loaded)
{
MERROR("MMS file " << filename << " has bad structure <iv,encrypted_data>");
THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename);
}
crypto::chacha_key key; crypto::chacha_key key;
crypto::generate_chacha_key(&state.view_secret_key, sizeof(crypto::secret_key), key, 1); crypto::generate_chacha_key(&state.view_secret_key, sizeof(crypto::secret_key), key, 1);
@ -805,18 +824,38 @@ void message_store::read_from_file(const multisig_wallet_state &state, const std
decrypted_data.resize(read_file_data.encrypted_data.size()); decrypted_data.resize(read_file_data.encrypted_data.size());
crypto::chacha20(read_file_data.encrypted_data.data(), read_file_data.encrypted_data.size(), key, read_file_data.iv, &decrypted_data[0]); crypto::chacha20(read_file_data.encrypted_data.data(), read_file_data.encrypted_data.size(), key, read_file_data.iv, &decrypted_data[0]);
loaded = false;
try
{
std::stringstream iss;
iss << decrypted_data;
binary_archive<false> ar(iss);
if (::serialization::serialize(ar, *this))
if (::serialization::check_stream_state(ar))
loaded = true;
}
catch(...) {}
if (!loaded && load_deprecated_formats)
{
try try
{ {
std::stringstream iss; std::stringstream iss;
iss << decrypted_data; iss << decrypted_data;
boost::archive::portable_binary_iarchive ar(iss); boost::archive::portable_binary_iarchive ar(iss);
ar >> *this; ar >> *this;
loaded = true;
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {
MERROR("MMS file " << filename << " has bad structure: " << e.what()); MERROR("MMS file " << filename << " has bad structure: " << e.what());
THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename); THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename);
} }
}
if (!loaded)
{
MERROR("MMS file " << filename << " has bad structure");
THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename);
}
m_filename = filename; m_filename = filename;
} }

View file

@ -44,6 +44,9 @@
#include "common/command_line.h" #include "common/command_line.h"
#include "wipeable_string.h" #include "wipeable_string.h"
#include "net/abstract_http_client.h" #include "net/abstract_http_client.h"
#include "serialization/crypto.h"
#include "serialization/string.h"
#include "serialization/containers.h"
#include "message_transporter.h" #include "message_transporter.h"
#undef MONERO_DEFAULT_LOG_CATEGORY #undef MONERO_DEFAULT_LOG_CATEGORY
@ -112,6 +115,24 @@ namespace mms
uint32_t round; uint32_t round;
uint32_t signature_count; uint32_t signature_count;
std::string transport_id; std::string transport_id;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
VARINT_FIELD(id)
VARINT_FIELD(type)
VARINT_FIELD(direction)
FIELD(content)
VARINT_FIELD(created)
VARINT_FIELD(modified)
VARINT_FIELD(sent)
VARINT_FIELD(signer_index)
FIELD(hash)
VARINT_FIELD(state)
VARINT_FIELD(wallet_height)
VARINT_FIELD(round)
VARINT_FIELD(signature_count)
FIELD(transport_id)
END_SERIALIZE()
}; };
// "wallet_height" (for lack of a short name that would describe what it is about) // "wallet_height" (for lack of a short name that would describe what it is about)
// is the number of transfers present in the wallet at the time of message // is the number of transfers present in the wallet at the time of message
@ -132,6 +153,21 @@ namespace mms
std::string auto_config_transport_address; std::string auto_config_transport_address;
bool auto_config_running; bool auto_config_running;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
FIELD(label)
FIELD(transport_address)
FIELD(monero_address_known)
FIELD(monero_address)
FIELD(me)
VARINT_FIELD(index)
FIELD(auto_config_token)
FIELD(auto_config_public_key)
FIELD(auto_config_secret_key)
FIELD(auto_config_transport_address)
FIELD(auto_config_running)
END_SERIALIZE()
authorized_signer() authorized_signer()
{ {
monero_address_known = false; monero_address_known = false;
@ -164,6 +200,13 @@ namespace mms
std::string label; std::string label;
std::string transport_address; std::string transport_address;
cryptonote::account_public_address monero_address; cryptonote::account_public_address monero_address;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
FIELD(label)
FIELD(transport_address)
FIELD(monero_address)
END_SERIALIZE()
}; };
// Overal .mms file structure, with the "message_store" object serialized to and // Overal .mms file structure, with the "message_store" object serialized to and
@ -174,6 +217,13 @@ namespace mms
uint32_t file_version; uint32_t file_version;
crypto::chacha_iv iv; crypto::chacha_iv iv;
std::string encrypted_data; std::string encrypted_data;
BEGIN_SERIALIZE_OBJECT()
FIELD(magic_string)
FIELD(file_version)
FIELD(iv)
FIELD(encrypted_data)
END_SERIALIZE()
}; };
// The following struct provides info about the current state of a "wallet2" object // The following struct provides info about the current state of a "wallet2" object
@ -198,6 +248,19 @@ namespace mms
uint32_t multisig_rounds_passed; uint32_t multisig_rounds_passed;
size_t num_transfer_details; size_t num_transfer_details;
std::string mms_file; std::string mms_file;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
FIELD(address)
VARINT_FIELD(nettype)
FIELD(view_secret_key)
FIELD(multisig)
FIELD(multisig_is_ready)
FIELD(has_multisig_partial_key_images)
VARINT_FIELD(multisig_rounds_passed)
VARINT_FIELD(num_transfer_details)
FIELD(mms_file)
END_SERIALIZE()
}; };
class message_store class message_store
@ -283,7 +346,7 @@ namespace mms
void stop() { m_run.store(false, std::memory_order_relaxed); m_transporter.stop(); } void stop() { m_run.store(false, std::memory_order_relaxed); m_transporter.stop(); }
void write_to_file(const multisig_wallet_state &state, const std::string &filename); void write_to_file(const multisig_wallet_state &state, const std::string &filename);
void read_from_file(const multisig_wallet_state &state, const std::string &filename); void read_from_file(const multisig_wallet_state &state, const std::string &filename, bool load_deprecated_formats = false);
template <class t_archive> template <class t_archive>
inline void serialize(t_archive &a, const unsigned int ver) inline void serialize(t_archive &a, const unsigned int ver)
@ -298,6 +361,18 @@ namespace mms
a & m_auto_send; a & m_auto_send;
} }
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
FIELD(m_active)
VARINT_FIELD(m_num_authorized_signers)
VARINT_FIELD(m_nettype)
VARINT_FIELD(m_num_required_signers)
FIELD(m_signers)
FIELD(m_messages)
VARINT_FIELD(m_next_message_id)
FIELD(m_auto_send)
END_SERIALIZE()
static const char* message_type_to_string(message_type type); static const char* message_type_to_string(message_type type);
static const char* message_direction_to_string(message_direction direction); static const char* message_direction_to_string(message_direction direction);
static const char* message_state_to_string(message_state state); static const char* message_state_to_string(message_state state);

View file

@ -103,8 +103,8 @@ using namespace cryptonote;
// used to target a given block weight (additional outputs may be added on top to build fee) // used to target a given block weight (additional outputs may be added on top to build fee)
#define TX_WEIGHT_TARGET(bytes) (bytes*2/3) #define TX_WEIGHT_TARGET(bytes) (bytes*2/3)
#define UNSIGNED_TX_PREFIX "Monero unsigned tx set\004" #define UNSIGNED_TX_PREFIX "Monero unsigned tx set\005"
#define SIGNED_TX_PREFIX "Monero signed tx set\004" #define SIGNED_TX_PREFIX "Monero signed tx set\005"
#define MULTISIG_UNSIGNED_TX_PREFIX "Monero multisig unsigned tx set\001" #define MULTISIG_UNSIGNED_TX_PREFIX "Monero multisig unsigned tx set\001"
#define RECENT_OUTPUT_RATIO (0.5) // 50% of outputs are from the recent zone #define RECENT_OUTPUT_RATIO (0.5) // 50% of outputs are from the recent zone
@ -1183,6 +1183,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
m_offline(false), m_offline(false),
m_rpc_version(0), m_rpc_version(0),
m_export_format(ExportFormat::Binary), m_export_format(ExportFormat::Binary),
m_load_deprecated_formats(false),
m_credits_target(0) m_credits_target(0)
{ {
set_rpc_client_secret_key(rct::rct2sk(rct::skGen())); set_rpc_client_secret_key(rct::rct2sk(rct::skGen()));
@ -3903,6 +3904,9 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee:
value2.SetInt(m_export_format); value2.SetInt(m_export_format);
json.AddMember("export_format", value2, json.GetAllocator()); json.AddMember("export_format", value2, json.GetAllocator());
value2.SetInt(m_load_deprecated_formats);
json.AddMember("load_deprecated_formats", value2, json.GetAllocator());
value2.SetUint(1); value2.SetUint(1);
json.AddMember("encrypted_secret_keys", value2, json.GetAllocator()); json.AddMember("encrypted_secret_keys", value2, json.GetAllocator());
@ -4072,6 +4076,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
m_subaddress_lookahead_minor = SUBADDRESS_LOOKAHEAD_MINOR; m_subaddress_lookahead_minor = SUBADDRESS_LOOKAHEAD_MINOR;
m_original_keys_available = false; m_original_keys_available = false;
m_export_format = ExportFormat::Binary; m_export_format = ExportFormat::Binary;
m_load_deprecated_formats = false;
m_device_name = ""; m_device_name = "";
m_device_derivation_path = ""; m_device_derivation_path = "";
m_key_device_type = hw::device::device_type::SOFTWARE; m_key_device_type = hw::device::device_type::SOFTWARE;
@ -4252,6 +4257,9 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, export_format, ExportFormat, Int, false, Binary); GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, export_format, ExportFormat, Int, false, Binary);
m_export_format = field_export_format; m_export_format = field_export_format;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, load_deprecated_formats, int, Int, false, false);
m_load_deprecated_formats = field_load_deprecated_formats;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, device_name, std::string, String, false, std::string()); GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, device_name, std::string, String, false, std::string());
if (m_device_name.empty()) if (m_device_name.empty())
{ {
@ -5617,11 +5625,27 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), m_cache_key, cache_file_data.iv, &cache_data[0]); crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), m_cache_key, cache_file_data.iv, &cache_data[0]);
try { try {
bool loaded = false;
try
{
std::stringstream iss;
iss << cache_data;
binary_archive<false> ar(iss);
if (::serialization::serialize(ar, *this))
if (::serialization::check_stream_state(ar))
loaded = true;
}
catch(...) { }
if (!loaded)
{
std::stringstream iss; std::stringstream iss;
iss << cache_data; iss << cache_data;
boost::archive::portable_binary_iarchive ar(iss); boost::archive::portable_binary_iarchive ar(iss);
ar >> *this; ar >> *this;
} }
}
catch(...) catch(...)
{ {
// try with previous scheme: direct from keys // try with previous scheme: direct from keys
@ -5717,7 +5741,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
try try
{ {
if (use_fs) if (use_fs)
m_message_store.read_from_file(get_multisig_wallet_state(), m_mms_file); m_message_store.read_from_file(get_multisig_wallet_state(), m_mms_file, m_load_deprecated_formats);
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {
@ -5907,8 +5931,9 @@ boost::optional<wallet2::cache_file_data> wallet2::get_cache_file_data(const epe
try try
{ {
std::stringstream oss; std::stringstream oss;
boost::archive::portable_binary_oarchive ar(oss); binary_archive<true> ar(oss);
ar << *this; if (!::serialization::serialize(ar, *this))
return boost::none;
boost::optional<wallet2::cache_file_data> cache_file_data = (wallet2::cache_file_data) {}; boost::optional<wallet2::cache_file_data> cache_file_data = (wallet2::cache_file_data) {};
cache_file_data.get().cache_data = oss.str(); cache_file_data.get().cache_data = oss.str();
@ -6570,10 +6595,11 @@ std::string wallet2::dump_tx_to_str(const std::vector<pending_tx> &ptx_vector) c
txs.transfers = export_outputs(); txs.transfers = export_outputs();
// save as binary // save as binary
std::ostringstream oss; std::ostringstream oss;
boost::archive::portable_binary_oarchive ar(oss); binary_archive<true> ar(oss);
try try
{ {
ar << txs; if (!::serialization::serialize(ar, txs))
return std::string();
} }
catch (...) catch (...)
{ {
@ -6617,6 +6643,11 @@ bool wallet2::parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsi
s = s.substr(1); s = s.substr(1);
if (version == '\003') if (version == '\003')
{ {
if (!m_load_deprecated_formats)
{
LOG_PRINT_L0("Not loading deprecated format");
return false;
}
try try
{ {
std::istringstream iss(s); std::istringstream iss(s);
@ -6631,6 +6662,11 @@ bool wallet2::parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsi
} }
else if (version == '\004') else if (version == '\004')
{ {
if (!m_load_deprecated_formats)
{
LOG_PRINT_L0("Not loading deprecated format");
return false;
}
try try
{ {
s = decrypt_with_view_secret_key(s); s = decrypt_with_view_secret_key(s);
@ -6652,6 +6688,26 @@ bool wallet2::parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsi
return false; return false;
} }
} }
else if (version == '\005')
{
try { s = decrypt_with_view_secret_key(s); }
catch(const std::exception &e) { LOG_PRINT_L0("Failed to decrypt unsigned tx: " << e.what()); return false; }
try
{
std::istringstream iss(s);
binary_archive<false> ar(iss);
if (!::serialization::serialize(ar, exported_txs))
{
LOG_PRINT_L0("Failed to parse data from unsigned tx");
return false;
}
}
catch (...)
{
LOG_PRINT_L0("Failed to parse data from unsigned tx");
return false;
}
}
else else
{ {
LOG_PRINT_L0("Unsupported version in unsigned tx"); LOG_PRINT_L0("Unsupported version in unsigned tx");
@ -6849,10 +6905,11 @@ std::string wallet2::sign_tx_dump_to_str(unsigned_tx_set &exported_txs, std::vec
// save as binary // save as binary
std::ostringstream oss; std::ostringstream oss;
boost::archive::portable_binary_oarchive ar(oss); binary_archive<true> ar(oss);
try try
{ {
ar << signed_txes; if (!::serialization::serialize(ar, signed_txes))
return std::string();
} }
catch(...) catch(...)
{ {
@ -6901,6 +6958,11 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too
s = s.substr(1); s = s.substr(1);
if (version == '\003') if (version == '\003')
{ {
if (!m_load_deprecated_formats)
{
LOG_PRINT_L0("Not loading deprecated format");
return false;
}
try try
{ {
std::istringstream iss(s); std::istringstream iss(s);
@ -6915,6 +6977,11 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too
} }
else if (version == '\004') else if (version == '\004')
{ {
if (!m_load_deprecated_formats)
{
LOG_PRINT_L0("Not loading deprecated format");
return false;
}
try try
{ {
s = decrypt_with_view_secret_key(s); s = decrypt_with_view_secret_key(s);
@ -6936,6 +7003,26 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too
return false; return false;
} }
} }
else if (version == '\005')
{
try { s = decrypt_with_view_secret_key(s); }
catch (const std::exception &e) { LOG_PRINT_L0("Failed to decrypt signed transaction: " << e.what()); return false; }
try
{
std::istringstream iss(s);
binary_archive<false> ar(iss);
if (!::serialization::serialize(ar, signed_txs))
{
LOG_PRINT_L0("Failed to deserialize signed transaction");
return false;
}
}
catch (const std::exception &e)
{
LOG_PRINT_L0("Failed to decrypt signed transaction: " << e.what());
return false;
}
}
else else
{ {
LOG_PRINT_L0("Unsupported version in signed transaction"); LOG_PRINT_L0("Unsupported version in signed transaction");
@ -6987,10 +7074,11 @@ std::string wallet2::save_multisig_tx(multisig_tx_set txs)
// save as binary // save as binary
std::ostringstream oss; std::ostringstream oss;
boost::archive::portable_binary_oarchive ar(oss); binary_archive<true> ar(oss);
try try
{ {
ar << txs; if (!::serialization::serialize(ar, txs))
return std::string();
} }
catch (...) catch (...)
{ {
@ -7054,13 +7142,29 @@ bool wallet2::parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx
LOG_PRINT_L0("Failed to decrypt multisig tx data: " << e.what()); LOG_PRINT_L0("Failed to decrypt multisig tx data: " << e.what());
return false; return false;
} }
bool loaded = false;
try try
{
std::istringstream iss(multisig_tx_st);
binary_archive<false> ar(iss);
if (::serialization::serialize(ar, exported_txs))
if (::serialization::check_stream_state(ar))
loaded = true;
}
catch (...) {}
try
{
if (!loaded && m_load_deprecated_formats)
{ {
std::istringstream iss(multisig_tx_st); std::istringstream iss(multisig_tx_st);
boost::archive::portable_binary_iarchive ar(iss); boost::archive::portable_binary_iarchive ar(iss);
ar >> exported_txs; ar >> exported_txs;
loaded = true;
} }
catch (...) }
catch(...) {}
if (!loaded)
{ {
LOG_PRINT_L0("Failed to parse multisig tx data"); LOG_PRINT_L0("Failed to parse multisig tx data");
return false; return false;
@ -9547,8 +9651,8 @@ bool wallet2::light_wallet_parse_rct_str(const std::string& rct_string, const cr
bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image, const crypto::public_key& tx_public_key, uint64_t out_index) bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image, const crypto::public_key& tx_public_key, uint64_t out_index)
{ {
// Lookup key image from cache // Lookup key image from cache
std::map<uint64_t, crypto::key_image> index_keyimage_map; serializable_map<uint64_t, crypto::key_image> index_keyimage_map;
std::unordered_map<crypto::public_key, std::map<uint64_t, crypto::key_image> >::const_iterator found_pub_key = m_key_image_cache.find(tx_public_key); serializable_unordered_map<crypto::public_key, serializable_map<uint64_t, crypto::key_image> >::const_iterator found_pub_key = m_key_image_cache.find(tx_public_key);
if(found_pub_key != m_key_image_cache.end()) { if(found_pub_key != m_key_image_cache.end()) {
// pub key found. key image for index cached? // pub key found. key image for index cached?
index_keyimage_map = found_pub_key->second; index_keyimage_map = found_pub_key->second;
@ -11736,7 +11840,7 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t,
} }
// collect all subaddress spend keys that received those outputs and generate their signatures // collect all subaddress spend keys that received those outputs and generate their signatures
std::unordered_map<crypto::public_key, crypto::signature> subaddr_spendkeys; serializable_unordered_map<crypto::public_key, crypto::signature> subaddr_spendkeys;
for (const cryptonote::subaddress_index &index : subaddr_indices) for (const cryptonote::subaddress_index &index : subaddr_indices)
{ {
crypto::secret_key subaddr_spend_skey = m_account.get_keys().m_spend_secret_key; crypto::secret_key subaddr_spend_skey = m_account.get_keys().m_spend_secret_key;
@ -11753,8 +11857,9 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t,
// serialize & encode // serialize & encode
std::ostringstream oss; std::ostringstream oss;
boost::archive::portable_binary_oarchive ar(oss); binary_archive<true> ar(oss);
ar << proofs << subaddr_spendkeys; THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, proofs), error::wallet_internal_error, "Failed to serialize proof");
THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, subaddr_spendkeys), error::wallet_internal_error, "Failed to serialize proof");
return "ReserveProofV2" + tools::base58::encode(oss.str()); return "ReserveProofV2" + tools::base58::encode(oss.str());
} }
@ -11778,11 +11883,25 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr
THROW_WALLET_EXCEPTION_IF(!tools::base58::decode(sig_str.substr(std::strlen(header_v1)), sig_decoded), error::wallet_internal_error, THROW_WALLET_EXCEPTION_IF(!tools::base58::decode(sig_str.substr(std::strlen(header_v1)), sig_decoded), error::wallet_internal_error,
"Signature decoding error"); "Signature decoding error");
bool loaded = false;
std::vector<reserve_proof_entry> proofs;
serializable_unordered_map<crypto::public_key, crypto::signature> subaddr_spendkeys;
try
{
std::istringstream iss(sig_decoded);
binary_archive<false> ar(iss);
if (::serialization::serialize_noeof(ar, proofs))
if (::serialization::serialize_noeof(ar, subaddr_spendkeys))
if (::serialization::check_stream_state(ar))
loaded = true;
}
catch(...) {}
if (!loaded && m_load_deprecated_formats)
{
std::istringstream iss(sig_decoded); std::istringstream iss(sig_decoded);
boost::archive::portable_binary_iarchive ar(iss); boost::archive::portable_binary_iarchive ar(iss);
std::vector<reserve_proof_entry> proofs; ar >> proofs >> subaddr_spendkeys.parent();
std::unordered_map<crypto::public_key, crypto::signature> subaddr_spendkeys; }
ar >> proofs >> subaddr_spendkeys;
THROW_WALLET_EXCEPTION_IF(subaddr_spendkeys.count(address.m_spend_public_key) == 0, error::wallet_internal_error, THROW_WALLET_EXCEPTION_IF(subaddr_spendkeys.count(address.m_spend_public_key) == 0, error::wallet_internal_error,
"The given address isn't found in the proof"); "The given address isn't found in the proof");
@ -12021,7 +12140,7 @@ std::string wallet2::get_description() const
return ""; return "";
} }
const std::pair<std::map<std::string, std::string>, std::vector<std::string>>& wallet2::get_account_tags() const std::pair<serializable_map<std::string, std::string>, std::vector<std::string>>& wallet2::get_account_tags()
{ {
// ensure consistency // ensure consistency
if (m_account_tags.second.size() != get_num_subaddress_accounts()) if (m_account_tags.second.size() != get_num_subaddress_accounts())
@ -12743,9 +12862,9 @@ std::string wallet2::export_outputs_to_str(bool all) const
PERF_TIMER(export_outputs_to_str); PERF_TIMER(export_outputs_to_str);
std::stringstream oss; std::stringstream oss;
boost::archive::portable_binary_oarchive ar(oss); binary_archive<true> ar(oss);
const auto& outputs = export_outputs(all); auto outputs = export_outputs(all);
ar << outputs; THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, outputs), error::wallet_internal_error, "Failed to serialize output data");
std::string magic(OUTPUT_EXPORT_FILE_MAGIC, strlen(OUTPUT_EXPORT_FILE_MAGIC)); std::string magic(OUTPUT_EXPORT_FILE_MAGIC, strlen(OUTPUT_EXPORT_FILE_MAGIC));
const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
@ -12857,23 +12976,39 @@ size_t wallet2::import_outputs_from_str(const std::string &outputs_st)
} }
size_t imported_outputs = 0; size_t imported_outputs = 0;
bool loaded = false;
try try
{ {
std::string body(data, headerlen); std::string body(data, headerlen);
std::stringstream iss;
iss << body;
std::pair<size_t, std::vector<tools::wallet2::transfer_details>> outputs; std::pair<size_t, std::vector<tools::wallet2::transfer_details>> outputs;
try try
{ {
std::stringstream iss;
iss << body;
binary_archive<false> ar(iss);
if (::serialization::serialize(ar, outputs))
if (::serialization::check_stream_state(ar))
loaded = true;
}
catch (...) {}
if (!loaded && m_load_deprecated_formats)
{
try
{
std::stringstream iss;
iss << body;
boost::archive::portable_binary_iarchive ar(iss); boost::archive::portable_binary_iarchive ar(iss);
ar >> outputs; ar >> outputs;
loaded = true;
} }
catch (...) catch (...) {}
}
if (!loaded)
{ {
iss.str(""); outputs.first = 0;
iss << body; outputs.second = {};
boost::archive::binary_iarchive ar(iss);
ar >> outputs;
} }
imported_outputs = import_outputs(outputs); imported_outputs = import_outputs(outputs);
@ -13027,8 +13162,8 @@ cryptonote::blobdata wallet2::export_multisig()
} }
std::stringstream oss; std::stringstream oss;
boost::archive::portable_binary_oarchive ar(oss); binary_archive<true> ar(oss);
ar << info; CHECK_AND_ASSERT_THROW_MES(::serialization::serialize(ar, info), "Failed to serialize multisig data");
const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
std::string header; std::string header;
@ -13098,10 +13233,26 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
seen.insert(signer); seen.insert(signer);
std::string body(data, headerlen); std::string body(data, headerlen);
std::istringstream iss(body);
std::vector<tools::wallet2::multisig_info> i; std::vector<tools::wallet2::multisig_info> i;
bool loaded = false;
try
{
std::istringstream iss(body);
binary_archive<false> ar(iss);
if (::serialization::serialize(ar, i))
if (::serialization::check_stream_state(ar))
loaded = true;
}
catch(...) {}
if (!loaded && m_load_deprecated_formats)
{
std::istringstream iss(body);
boost::archive::portable_binary_iarchive ar(iss); boost::archive::portable_binary_iarchive ar(iss);
ar >> i; ar >> i;
loaded = true;
}
CHECK_AND_ASSERT_THROW_MES(loaded, "Failed to load output data");
MINFO(boost::format("%u outputs found") % boost::lexical_cast<std::string>(i.size())); MINFO(boost::format("%u outputs found") % boost::lexical_cast<std::string>(i.size()));
info.push_back(std::move(i)); info.push_back(std::move(i));
} }

View file

@ -57,7 +57,10 @@
#include "ringct/rctTypes.h" #include "ringct/rctTypes.h"
#include "ringct/rctOps.h" #include "ringct/rctOps.h"
#include "checkpoints/checkpoints.h" #include "checkpoints/checkpoints.h"
#include "serialization/crypto.h"
#include "serialization/string.h"
#include "serialization/pair.h" #include "serialization/pair.h"
#include "serialization/containers.h"
#include "wallet_errors.h" #include "wallet_errors.h"
#include "common/password.h" #include "common/password.h"
@ -205,6 +208,13 @@ private:
a & m_blockchain; a & m_blockchain;
} }
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
VARINT_FIELD(m_offset)
FIELD(m_genesis)
FIELD(m_blockchain)
END_SERIALIZE()
private: private:
size_t m_offset; size_t m_offset;
crypto::hash m_genesis; crypto::hash m_genesis;
@ -381,6 +391,19 @@ private:
uint64_t m_timestamp; uint64_t m_timestamp;
bool m_coinbase; bool m_coinbase;
cryptonote::subaddress_index m_subaddr_index; cryptonote::subaddress_index m_subaddr_index;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
FIELD(m_tx_hash)
VARINT_FIELD(m_amount)
FIELD(m_amounts)
VARINT_FIELD(m_fee)
VARINT_FIELD(m_block_height)
VARINT_FIELD(m_unlock_time)
VARINT_FIELD(m_timestamp)
FIELD(m_coinbase)
FIELD(m_subaddr_index)
END_SERIALIZE()
}; };
struct address_tx : payment_details struct address_tx : payment_details
@ -393,6 +416,12 @@ private:
{ {
payment_details m_pd; payment_details m_pd;
bool m_double_spend_seen; bool m_double_spend_seen;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
FIELD(m_pd)
FIELD(m_double_spend_seen)
END_SERIALIZE()
}; };
struct unconfirmed_transfer_details struct unconfirmed_transfer_details
@ -409,6 +438,21 @@ private:
uint32_t m_subaddr_account; // subaddress account of your wallet to be used in this transfer uint32_t m_subaddr_account; // subaddress account of your wallet to be used in this transfer
std::set<uint32_t> m_subaddr_indices; // set of address indices used as inputs in this transfer std::set<uint32_t> m_subaddr_indices; // set of address indices used as inputs in this transfer
std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> m_rings; // relative std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> m_rings; // relative
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
FIELD(m_tx)
VARINT_FIELD(m_amount_in)
VARINT_FIELD(m_amount_out)
VARINT_FIELD(m_change)
VARINT_FIELD(m_sent_time)
FIELD(m_dests)
FIELD(m_payment_id)
VARINT_FIELD(m_timestamp)
VARINT_FIELD(m_subaddr_account)
FIELD(m_subaddr_indices)
FIELD(m_rings)
END_SERIALIZE()
}; };
struct confirmed_transfer_details struct confirmed_transfer_details
@ -428,6 +472,21 @@ private:
confirmed_transfer_details(): m_amount_in(0), m_amount_out(0), m_change((uint64_t)-1), m_block_height(0), m_payment_id(crypto::null_hash), m_timestamp(0), m_unlock_time(0), m_subaddr_account((uint32_t)-1) {} confirmed_transfer_details(): m_amount_in(0), m_amount_out(0), m_change((uint64_t)-1), m_block_height(0), m_payment_id(crypto::null_hash), m_timestamp(0), m_unlock_time(0), m_subaddr_account((uint32_t)-1) {}
confirmed_transfer_details(const unconfirmed_transfer_details &utd, uint64_t height): confirmed_transfer_details(const unconfirmed_transfer_details &utd, uint64_t height):
m_amount_in(utd.m_amount_in), m_amount_out(utd.m_amount_out), m_change(utd.m_change), m_block_height(height), m_dests(utd.m_dests), m_payment_id(utd.m_payment_id), m_timestamp(utd.m_timestamp), m_unlock_time(utd.m_tx.unlock_time), m_subaddr_account(utd.m_subaddr_account), m_subaddr_indices(utd.m_subaddr_indices), m_rings(utd.m_rings) {} m_amount_in(utd.m_amount_in), m_amount_out(utd.m_amount_out), m_change(utd.m_change), m_block_height(height), m_dests(utd.m_dests), m_payment_id(utd.m_payment_id), m_timestamp(utd.m_timestamp), m_unlock_time(utd.m_tx.unlock_time), m_subaddr_account(utd.m_subaddr_account), m_subaddr_indices(utd.m_subaddr_indices), m_rings(utd.m_rings) {}
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
VARINT_FIELD(m_amount_in)
VARINT_FIELD(m_amount_out)
VARINT_FIELD(m_change)
VARINT_FIELD(m_block_height)
FIELD(m_dests)
FIELD(m_payment_id)
VARINT_FIELD(m_timestamp)
VARINT_FIELD(m_unlock_time)
VARINT_FIELD(m_subaddr_account)
FIELD(m_subaddr_indices)
FIELD(m_rings)
END_SERIALIZE()
}; };
struct tx_construction_data struct tx_construction_data
@ -460,7 +519,7 @@ private:
}; };
typedef std::vector<transfer_details> transfer_container; typedef std::vector<transfer_details> transfer_container;
typedef std::unordered_multimap<crypto::hash, payment_details> payment_container; typedef serializable_unordered_multimap<crypto::hash, payment_details> payment_container;
struct multisig_sig struct multisig_sig
{ {
@ -469,6 +528,15 @@ private:
std::unordered_set<rct::key> used_L; std::unordered_set<rct::key> used_L;
std::unordered_set<crypto::public_key> signing_keys; std::unordered_set<crypto::public_key> signing_keys;
rct::multisig_out msout; rct::multisig_out msout;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
FIELD(sigs)
FIELD(ignore)
FIELD(used_L)
FIELD(signing_keys)
FIELD(msout)
END_SERIALIZE()
}; };
// The convention for destinations is: // The convention for destinations is:
@ -511,13 +579,26 @@ private:
{ {
std::vector<tx_construction_data> txes; std::vector<tx_construction_data> txes;
std::pair<size_t, wallet2::transfer_container> transfers; std::pair<size_t, wallet2::transfer_container> transfers;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
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;
std::unordered_map<crypto::public_key, crypto::key_image> tx_key_images; serializable_unordered_map<crypto::public_key, crypto::key_image> tx_key_images;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
FIELD(ptx)
FIELD(key_images)
FIELD(tx_key_images)
END_SERIALIZE()
}; };
struct multisig_tx_set struct multisig_tx_set
@ -561,6 +642,15 @@ private:
std::string m_description; std::string m_description;
bool m_is_subaddress; bool m_is_subaddress;
bool m_has_payment_id; bool m_has_payment_id;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
FIELD(m_address)
FIELD(m_payment_id)
FIELD(m_description)
FIELD(m_is_subaddress)
FIELD(m_has_payment_id)
END_SERIALIZE()
}; };
struct reserve_proof_entry struct reserve_proof_entry
@ -571,6 +661,16 @@ private:
crypto::key_image key_image; crypto::key_image key_image;
crypto::signature shared_secret_sig; crypto::signature shared_secret_sig;
crypto::signature key_image_sig; crypto::signature key_image_sig;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
FIELD(txid)
VARINT_FIELD(index_in_tx)
FIELD(shared_secret)
FIELD(key_image)
FIELD(shared_secret_sig)
FIELD(key_image_sig)
END_SERIALIZE()
}; };
typedef std::tuple<uint64_t, crypto::public_key, rct::key> get_outs_entry; typedef std::tuple<uint64_t, crypto::public_key, rct::key> get_outs_entry;
@ -927,6 +1027,7 @@ private:
{ {
std::vector<crypto::hash> blockchain; std::vector<crypto::hash> blockchain;
a & blockchain; a & blockchain;
m_blockchain.clear();
for (const auto &b: blockchain) for (const auto &b: blockchain)
{ {
m_blockchain.push_back(b); m_blockchain.push_back(b);
@ -938,25 +1039,25 @@ private:
} }
a & m_transfers; a & m_transfers;
a & m_account_public_address; a & m_account_public_address;
a & m_key_images; a & m_key_images.parent();
if(ver < 6) if(ver < 6)
return; return;
a & m_unconfirmed_txs; a & m_unconfirmed_txs.parent();
if(ver < 7) if(ver < 7)
return; return;
a & m_payments; a & m_payments.parent();
if(ver < 8) if(ver < 8)
return; return;
a & m_tx_keys; a & m_tx_keys.parent();
if(ver < 9) if(ver < 9)
return; return;
a & m_confirmed_txs; a & m_confirmed_txs.parent();
if(ver < 11) if(ver < 11)
return; return;
a & dummy_refresh_height; a & dummy_refresh_height;
if(ver < 12) if(ver < 12)
return; return;
a & m_tx_notes; a & m_tx_notes.parent();
if(ver < 13) if(ver < 13)
return; return;
if (ver < 17) if (ver < 17)
@ -964,6 +1065,7 @@ private:
// we're loading an old version, where m_unconfirmed_payments was a std::map // we're loading an old version, where m_unconfirmed_payments was a std::map
std::unordered_map<crypto::hash, payment_details> m; std::unordered_map<crypto::hash, payment_details> m;
a & m; a & m;
m_unconfirmed_payments.clear();
for (std::unordered_map<crypto::hash, payment_details>::const_iterator i = m.begin(); i != m.end(); ++i) for (std::unordered_map<crypto::hash, payment_details>::const_iterator i = m.begin(); i != m.end(); ++i)
m_unconfirmed_payments.insert(std::make_pair(i->first, pool_payment_details{i->second, false})); m_unconfirmed_payments.insert(std::make_pair(i->first, pool_payment_details{i->second, false}));
} }
@ -972,6 +1074,7 @@ private:
if(ver < 15) if(ver < 15)
{ {
// we're loading an older wallet without a pubkey map, rebuild it // we're loading an older wallet without a pubkey map, rebuild it
m_pub_keys.clear();
for (size_t i = 0; i < m_transfers.size(); ++i) for (size_t i = 0; i < m_transfers.size(); ++i)
{ {
const transfer_details &td = m_transfers[i]; const transfer_details &td = m_transfers[i];
@ -981,7 +1084,7 @@ private:
} }
return; return;
} }
a & m_pub_keys; a & m_pub_keys.parent();
if(ver < 16) if(ver < 16)
return; return;
a & m_address_book; a & m_address_book;
@ -992,6 +1095,7 @@ private:
// we're loading an old version, where m_unconfirmed_payments payload was payment_details // we're loading an old version, where m_unconfirmed_payments payload was payment_details
std::unordered_multimap<crypto::hash, payment_details> m; std::unordered_multimap<crypto::hash, payment_details> m;
a & m; a & m;
m_unconfirmed_payments.clear();
for (const auto &i: m) for (const auto &i: m)
m_unconfirmed_payments.insert(std::make_pair(i.first, pool_payment_details{i.second, false})); m_unconfirmed_payments.insert(std::make_pair(i.first, pool_payment_details{i.second, false}));
} }
@ -1001,20 +1105,20 @@ private:
a & m_scanned_pool_txs[1]; a & m_scanned_pool_txs[1];
if (ver < 20) if (ver < 20)
return; return;
a & m_subaddresses; a & m_subaddresses.parent();
std::unordered_map<cryptonote::subaddress_index, crypto::public_key> dummy_subaddresses_inv; std::unordered_map<cryptonote::subaddress_index, crypto::public_key> dummy_subaddresses_inv;
a & dummy_subaddresses_inv; a & dummy_subaddresses_inv;
a & m_subaddress_labels; a & m_subaddress_labels;
a & m_additional_tx_keys; a & m_additional_tx_keys.parent();
if(ver < 21) if(ver < 21)
return; return;
a & m_attributes; a & m_attributes.parent();
if(ver < 22) if(ver < 22)
return; return;
a & m_unconfirmed_payments; a & m_unconfirmed_payments.parent();
if(ver < 23) if(ver < 23)
return; return;
a & m_account_tags; a & (std::pair<std::map<std::string, std::string>, std::vector<std::string>>&)m_account_tags;
if(ver < 24) if(ver < 24)
return; return;
a & m_ring_history_saved; a & m_ring_history_saved;
@ -1023,18 +1127,48 @@ private:
a & m_last_block_reward; a & m_last_block_reward;
if(ver < 26) if(ver < 26)
return; return;
a & m_tx_device; a & m_tx_device.parent();
if(ver < 27) if(ver < 27)
return; return;
a & m_device_last_key_image_sync; a & m_device_last_key_image_sync;
if(ver < 28) if(ver < 28)
return; return;
a & m_cold_key_images; a & m_cold_key_images.parent();
if(ver < 29) if(ver < 29)
return; return;
a & m_rpc_client_secret_key; a & m_rpc_client_secret_key;
} }
BEGIN_SERIALIZE_OBJECT()
MAGIC_FIELD("monero wallet cache")
VERSION_FIELD(0)
FIELD(m_blockchain)
FIELD(m_transfers)
FIELD(m_account_public_address)
FIELD(m_key_images)
FIELD(m_unconfirmed_txs)
FIELD(m_payments)
FIELD(m_tx_keys)
FIELD(m_confirmed_txs)
FIELD(m_tx_notes)
FIELD(m_unconfirmed_payments)
FIELD(m_pub_keys)
FIELD(m_address_book)
FIELD(m_scanned_pool_txs[0])
FIELD(m_scanned_pool_txs[1])
FIELD(m_subaddresses)
FIELD(m_subaddress_labels)
FIELD(m_additional_tx_keys)
FIELD(m_attributes)
FIELD(m_account_tags)
FIELD(m_ring_history_saved)
FIELD(m_last_block_reward)
FIELD(m_tx_device)
FIELD(m_device_last_key_image_sync)
FIELD(m_cold_key_images)
FIELD(m_rpc_client_secret_key)
END_SERIALIZE()
/*! /*!
* \brief Check if wallet keys and bin files exist * \brief Check if wallet keys and bin files exist
* \param file_path Wallet file path * \param file_path Wallet file path
@ -1106,6 +1240,8 @@ private:
void device_derivation_path(const std::string &device_derivation_path) { m_device_derivation_path = device_derivation_path; } void device_derivation_path(const std::string &device_derivation_path) { m_device_derivation_path = device_derivation_path; }
const ExportFormat & export_format() const { return m_export_format; } const ExportFormat & export_format() const { return m_export_format; }
inline void set_export_format(const ExportFormat& export_format) { m_export_format = export_format; } inline void set_export_format(const ExportFormat& export_format) { m_export_format = export_format; }
bool load_deprecated_formats() const { return m_load_deprecated_formats; }
void load_deprecated_formats(bool load) { m_load_deprecated_formats = load; }
bool persistent_rpc_client_id() const { return m_persistent_rpc_client_id; } bool persistent_rpc_client_id() const { return m_persistent_rpc_client_id; }
void persistent_rpc_client_id(bool persistent) { m_persistent_rpc_client_id = persistent; } void persistent_rpc_client_id(bool persistent) { m_persistent_rpc_client_id = persistent; }
void auto_mine_for_rpc_payment_threshold(float threshold) { m_auto_mine_for_rpc_payment_threshold = threshold; } void auto_mine_for_rpc_payment_threshold(float threshold) { m_auto_mine_for_rpc_payment_threshold = threshold; }
@ -1197,7 +1333,7 @@ private:
* \brief Get the list of registered account tags. * \brief Get the list of registered account tags.
* \return first.Key=(tag's name), first.Value=(tag's label), second[i]=(i-th account's tag) * \return first.Key=(tag's name), first.Value=(tag's label), second[i]=(i-th account's tag)
*/ */
const std::pair<std::map<std::string, std::string>, std::vector<std::string>>& get_account_tags(); const std::pair<serializable_map<std::string, std::string>, std::vector<std::string>>& get_account_tags();
/*! /*!
* \brief Set a tag to the given accounts. * \brief Set a tag to the given accounts.
* \param account_indices Indices of accounts. * \param account_indices Indices of accounts.
@ -1539,28 +1675,28 @@ private:
std::string m_mms_file; std::string m_mms_file;
const std::unique_ptr<epee::net_utils::http::abstract_http_client> m_http_client; const std::unique_ptr<epee::net_utils::http::abstract_http_client> m_http_client;
hashchain m_blockchain; hashchain m_blockchain;
std::unordered_map<crypto::hash, unconfirmed_transfer_details> m_unconfirmed_txs; serializable_unordered_map<crypto::hash, unconfirmed_transfer_details> m_unconfirmed_txs;
std::unordered_map<crypto::hash, confirmed_transfer_details> m_confirmed_txs; serializable_unordered_map<crypto::hash, confirmed_transfer_details> m_confirmed_txs;
std::unordered_multimap<crypto::hash, pool_payment_details> m_unconfirmed_payments; serializable_unordered_multimap<crypto::hash, pool_payment_details> m_unconfirmed_payments;
std::unordered_map<crypto::hash, crypto::secret_key> m_tx_keys; serializable_unordered_map<crypto::hash, crypto::secret_key> m_tx_keys;
cryptonote::checkpoints m_checkpoints; cryptonote::checkpoints m_checkpoints;
std::unordered_map<crypto::hash, std::vector<crypto::secret_key>> m_additional_tx_keys; serializable_unordered_map<crypto::hash, std::vector<crypto::secret_key>> m_additional_tx_keys;
transfer_container m_transfers; transfer_container m_transfers;
payment_container m_payments; payment_container m_payments;
std::unordered_map<crypto::key_image, size_t> m_key_images; serializable_unordered_map<crypto::key_image, size_t> m_key_images;
std::unordered_map<crypto::public_key, size_t> m_pub_keys; serializable_unordered_map<crypto::public_key, size_t> m_pub_keys;
cryptonote::account_public_address m_account_public_address; cryptonote::account_public_address m_account_public_address;
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> m_subaddresses; serializable_unordered_map<crypto::public_key, cryptonote::subaddress_index> m_subaddresses;
std::vector<std::vector<std::string>> m_subaddress_labels; std::vector<std::vector<std::string>> m_subaddress_labels;
std::unordered_map<crypto::hash, std::string> m_tx_notes; serializable_unordered_map<crypto::hash, std::string> m_tx_notes;
std::unordered_map<std::string, std::string> m_attributes; serializable_unordered_map<std::string, std::string> m_attributes;
std::vector<tools::wallet2::address_book_row> m_address_book; std::vector<tools::wallet2::address_book_row> m_address_book;
std::pair<std::map<std::string, std::string>, std::vector<std::string>> m_account_tags; std::pair<serializable_map<std::string, std::string>, std::vector<std::string>> m_account_tags;
uint64_t m_upper_transaction_weight_limit; //TODO: auto-calc this value or request from daemon, now use some fixed value uint64_t m_upper_transaction_weight_limit; //TODO: auto-calc this value or request from daemon, now use some fixed value
const std::vector<std::vector<tools::wallet2::multisig_info>> *m_multisig_rescan_info; const std::vector<std::vector<tools::wallet2::multisig_info>> *m_multisig_rescan_info;
const std::vector<std::vector<rct::key>> *m_multisig_rescan_k; const std::vector<std::vector<rct::key>> *m_multisig_rescan_k;
std::unordered_map<crypto::public_key, crypto::key_image> m_cold_key_images; serializable_unordered_map<crypto::public_key, crypto::key_image> m_cold_key_images;
std::atomic<bool> m_run; std::atomic<bool> m_run;
@ -1627,7 +1763,7 @@ private:
uint64_t m_credits_target; uint64_t m_credits_target;
// Aux transaction data from device // Aux transaction data from device
std::unordered_map<crypto::hash, std::string> m_tx_device; serializable_unordered_map<crypto::hash, std::string> m_tx_device;
// Light wallet // Light wallet
bool m_light_wallet; /* sends view key to daemon for scanning */ bool m_light_wallet; /* sends view key to daemon for scanning */
@ -1641,7 +1777,7 @@ private:
// We save the info from the first call in m_light_wallet_address_txs for easier lookup. // We save the info from the first call in m_light_wallet_address_txs for easier lookup.
std::unordered_map<crypto::hash, address_tx> m_light_wallet_address_txs; std::unordered_map<crypto::hash, address_tx> m_light_wallet_address_txs;
// store calculated key image for faster lookup // store calculated key image for faster lookup
std::unordered_map<crypto::public_key, std::map<uint64_t, crypto::key_image> > m_key_image_cache; serializable_unordered_map<crypto::public_key, serializable_map<uint64_t, crypto::key_image> > m_key_image_cache;
std::string m_ring_database; std::string m_ring_database;
bool m_ring_history_saved; bool m_ring_history_saved;
@ -1668,6 +1804,7 @@ private:
std::unique_ptr<wallet_device_callback> m_device_callback; std::unique_ptr<wallet_device_callback> m_device_callback;
ExportFormat m_export_format; ExportFormat m_export_format;
bool m_load_deprecated_formats;
static boost::mutex default_daemon_address_lock; static boost::mutex default_daemon_address_lock;
static std::string default_daemon_address; static std::string default_daemon_address;
@ -2064,7 +2201,7 @@ namespace boost
a & x.key_images; a & x.key_images;
if (ver < 1) if (ver < 1)
return; return;
a & x.tx_key_images; a & x.tx_key_images.parent();
} }
template <class Archive> template <class Archive>

View file

@ -838,10 +838,11 @@ namespace tools
static std::string ptx_to_string(const tools::wallet2::pending_tx &ptx) static std::string ptx_to_string(const tools::wallet2::pending_tx &ptx)
{ {
std::ostringstream oss; std::ostringstream oss;
boost::archive::portable_binary_oarchive ar(oss); binary_archive<true> ar(oss);
try try
{ {
ar << ptx; if (!::serialization::serialize(ar, const_cast<tools::wallet2::pending_tx&>(ptx)))
return "";
} }
catch (...) catch (...)
{ {
@ -1550,14 +1551,31 @@ namespace tools
return false; return false;
} }
bool loaded = false;
tools::wallet2::pending_tx ptx; tools::wallet2::pending_tx ptx;
try
{
std::istringstream iss(blob);
binary_archive<false> ar(iss);
if (::serialization::serialize(ar, ptx))
loaded = true;
}
catch(...) {}
if (!loaded && !m_restricted)
{
try try
{ {
std::istringstream iss(blob); std::istringstream iss(blob);
boost::archive::portable_binary_iarchive ar(iss); boost::archive::portable_binary_iarchive ar(iss);
ar >> ptx; ar >> ptx;
loaded = true;
} }
catch (...) catch (...) {}
}
if (!loaded)
{ {
er.code = WALLET_RPC_ERROR_CODE_BAD_TX_METADATA; er.code = WALLET_RPC_ERROR_CODE_BAD_TX_METADATA;
er.message = "Failed to parse tx metadata."; er.message = "Failed to parse tx metadata.";

View file

@ -47,7 +47,7 @@
// advance which version they will stop working with // advance which version they will stop working with
// Don't go over 32767 for any of these // Don't go over 32767 for any of these
#define WALLET_RPC_VERSION_MAJOR 1 #define WALLET_RPC_VERSION_MAJOR 1
#define WALLET_RPC_VERSION_MINOR 18 #define WALLET_RPC_VERSION_MINOR 19
#define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor))
#define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR) #define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR)
namespace tools namespace tools

View file

@ -35,8 +35,6 @@
#include <iostream> #include <iostream>
#include <stdint.h> #include <stdint.h>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/serialization/vector.hpp> #include <boost/serialization/vector.hpp>

Binary file not shown.

Binary file not shown.

View file

@ -40,7 +40,7 @@ BEGIN_INIT_SIMPLE_FUZZER()
static tools::wallet2 local_wallet; static tools::wallet2 local_wallet;
wallet = &local_wallet; wallet = &local_wallet;
static const char * const spendkey_hex = "0b4f47697ec99c3de6579304e5f25c68b07afbe55b71d99620bf6cbf4e45a80f"; static const char * const spendkey_hex = "f285d4ac9e66271256fc7cde0d3d6b36f66efff6ccd766706c408e86f4997a0d";
crypto::secret_key spendkey; crypto::secret_key spendkey;
epee::string_tools::hex_to_pod(spendkey_hex, spendkey); epee::string_tools::hex_to_pod(spendkey_hex, spendkey);
@ -50,12 +50,12 @@ BEGIN_INIT_SIMPLE_FUZZER()
END_INIT_SIMPLE_FUZZER() END_INIT_SIMPLE_FUZZER()
BEGIN_SIMPLE_FUZZER() BEGIN_SIMPLE_FUZZER()
std::string s = std::string("\x01\x16serialization::archive") + std::string((const char*)buf, len); std::string s((const char*)buf, len);
std::pair<size_t, std::vector<tools::wallet2::transfer_details>> outputs; std::pair<size_t, std::vector<tools::wallet2::transfer_details>> outputs;
std::stringstream iss; std::stringstream iss;
iss << s; iss << s;
boost::archive::portable_binary_iarchive ar(iss); binary_archive<false> ar(iss);
ar >> outputs; ::serialization::serialize(ar, outputs);
size_t n_outputs = wallet->import_outputs(outputs); size_t n_outputs = wallet->import_outputs(outputs);
std::cout << boost::lexical_cast<std::string>(n_outputs) << " outputs imported" << std::endl; std::cout << boost::lexical_cast<std::string>(n_outputs) << " outputs imported" << std::endl;
END_SIMPLE_FUZZER() END_SIMPLE_FUZZER()

View file

@ -40,7 +40,7 @@ BEGIN_INIT_SIMPLE_FUZZER()
static tools::wallet2 local_wallet; static tools::wallet2 local_wallet;
wallet = &local_wallet; wallet = &local_wallet;
static const char * const spendkey_hex = "0b4f47697ec99c3de6579304e5f25c68b07afbe55b71d99620bf6cbf4e45a80f"; static const char * const spendkey_hex = "f285d4ac9e66271256fc7cde0d3d6b36f66efff6ccd766706c408e86f4997a0d";
crypto::secret_key spendkey; crypto::secret_key spendkey;
epee::string_tools::hex_to_pod(spendkey_hex, spendkey); epee::string_tools::hex_to_pod(spendkey_hex, spendkey);
@ -50,12 +50,12 @@ BEGIN_INIT_SIMPLE_FUZZER()
END_INIT_SIMPLE_FUZZER() END_INIT_SIMPLE_FUZZER()
BEGIN_SIMPLE_FUZZER() BEGIN_SIMPLE_FUZZER()
std::string s = std::string("\x01\x16serialization::archive") + std::string((const char*)buf, len); std::string s((const char*)buf, len);
tools::wallet2::unsigned_tx_set exported_txs; tools::wallet2::unsigned_tx_set exported_txs;
std::stringstream iss; std::stringstream iss;
iss << s; iss << s;
boost::archive::portable_binary_iarchive ar(iss); binary_archive<false> ar(iss);
ar >> exported_txs; ::serialization::serialize(ar, exported_txs);
std::vector<tools::wallet2::pending_tx> ptx; std::vector<tools::wallet2::pending_tx> ptx;
bool success = wallet->sign_tx(exported_txs, "/tmp/cold-transaction-test-signed", ptx); bool success = wallet->sign_tx(exported_txs, "/tmp/cold-transaction-test-signed", ptx);
std::cout << (success ? "signed" : "error") << std::endl; std::cout << (success ? "signed" : "error") << std::endl;

View file

@ -42,7 +42,7 @@
#include "serialization/json_archive.h" #include "serialization/json_archive.h"
#include "serialization/debug_archive.h" #include "serialization/debug_archive.h"
#include "serialization/variant.h" #include "serialization/variant.h"
#include "serialization/vector.h" #include "serialization/containers.h"
#include "serialization/binary_utils.h" #include "serialization/binary_utils.h"
#include "wallet/wallet2.h" #include "wallet/wallet2.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"

View file

@ -40,7 +40,7 @@
#include "serialization/json_archive.h" #include "serialization/json_archive.h"
#include "serialization/debug_archive.h" #include "serialization/debug_archive.h"
#include "serialization/variant.h" #include "serialization/variant.h"
#include "serialization/vector.h" #include "serialization/containers.h"
#include "serialization/binary_utils.h" #include "serialization/binary_utils.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
using namespace std; using namespace std;