aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/api/wallet.cpp13
-rw-r--r--src/wallet/api/wallet.h5
-rw-r--r--src/wallet/api/wallet2_api.h7
-rw-r--r--src/wallet/api/wallet_manager.cpp4
-rw-r--r--src/wallet/api/wallet_manager.h5
-rw-r--r--src/wallet/message_store.cpp83
-rw-r--r--src/wallet/message_store.h77
-rw-r--r--src/wallet/wallet2.cpp334
-rw-r--r--src/wallet/wallet2.h210
-rw-r--r--src/wallet/wallet_rpc_server.cpp50
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h2
11 files changed, 619 insertions, 171 deletions
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 66e248427..73ab88a9f 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -938,13 +938,13 @@ string WalletImpl::keysFilename() const
return m_wallet->get_keys_file();
}
-bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit, const std::string &daemon_username, const std::string &daemon_password, bool use_ssl, bool lightWallet)
+bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit, const std::string &daemon_username, const std::string &daemon_password, bool use_ssl, bool lightWallet, const std::string &proxy_address)
{
clearStatus();
m_wallet->set_light_wallet(lightWallet);
if(daemon_username != "")
m_daemon_login.emplace(daemon_username, daemon_password);
- return doInit(daemon_address, upper_transaction_size_limit, use_ssl);
+ return doInit(daemon_address, proxy_address, upper_transaction_size_limit, use_ssl);
}
bool WalletImpl::lightWalletLogin(bool &isNewWallet) const
@@ -2088,6 +2088,11 @@ bool WalletImpl::trustedDaemon() const
return m_wallet->is_trusted_daemon();
}
+bool WalletImpl::setProxy(const std::string &address)
+{
+ return m_wallet->set_proxy(address);
+}
+
bool WalletImpl::watchOnly() const
{
return m_wallet->watch_only();
@@ -2241,9 +2246,9 @@ void WalletImpl::pendingTxPostProcess(PendingTransactionImpl * pending)
pending->m_pending_tx = exported_txs.ptx;
}
-bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit, bool ssl)
+bool WalletImpl::doInit(const string &daemon_address, const std::string &proxy_address, uint64_t upper_transaction_size_limit, bool ssl)
{
- if (!m_wallet->init(daemon_address, m_daemon_login, boost::asio::ip::tcp::endpoint{}, upper_transaction_size_limit))
+ if (!m_wallet->init(daemon_address, m_daemon_login, proxy_address, upper_transaction_size_limit))
return false;
// in case new wallet, this will force fast-refresh (pulling hashes instead of blocks)
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 43d85b704..caf1e9ed4 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -102,11 +102,12 @@ public:
bool store(const std::string &path) override;
std::string filename() const override;
std::string keysFilename() const override;
- bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, const std::string &daemon_username = "", const std::string &daemon_password = "", bool use_ssl = false, bool lightWallet = false) override;
+ bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, const std::string &daemon_username = "", const std::string &daemon_password = "", bool use_ssl = false, bool lightWallet = false, const std::string &proxy_address = "") override;
bool connectToDaemon() override;
ConnectionStatus connected() const override;
void setTrustedDaemon(bool arg) override;
bool trustedDaemon() const override;
+ bool setProxy(const std::string &address) override;
uint64_t balance(uint32_t accountIndex = 0) const override;
uint64_t unlockedBalance(uint32_t accountIndex = 0) const override;
uint64_t blockChainHeight() const override;
@@ -225,7 +226,7 @@ private:
void stopRefresh();
bool isNewWallet() const;
void pendingTxPostProcess(PendingTransactionImpl * pending);
- bool doInit(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, bool ssl = false);
+ bool doInit(const std::string &daemon_address, const std::string &proxy_address, uint64_t upper_transaction_size_limit = 0, bool ssl = false);
private:
friend class PendingTransactionImpl;
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index e2f96a069..50df7e5dd 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -533,9 +533,10 @@ struct Wallet
* \param daemon_username
* \param daemon_password
* \param lightWallet - start wallet in light mode, connect to a openmonero compatible server.
+ * \param proxy_address - set proxy address, empty string to disable
* \return - true on success
*/
- virtual bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, const std::string &daemon_username = "", const std::string &daemon_password = "", bool use_ssl = false, bool lightWallet = false) = 0;
+ virtual bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, const std::string &daemon_username = "", const std::string &daemon_password = "", bool use_ssl = false, bool lightWallet = false, const std::string &proxy_address = "") = 0;
/*!
* \brief createWatchOnly - Creates a watch only wallet
@@ -594,6 +595,7 @@ struct Wallet
virtual ConnectionStatus connected() const = 0;
virtual void setTrustedDaemon(bool arg) = 0;
virtual bool trustedDaemon() const = 0;
+ virtual bool setProxy(const std::string &address) = 0;
virtual uint64_t balance(uint32_t accountIndex = 0) const = 0;
uint64_t balanceAll() const {
uint64_t result = 0;
@@ -1298,6 +1300,9 @@ struct WalletManager
std::string subdir,
const char *buildtag = nullptr,
const char *current_version = nullptr);
+
+ //! sets proxy address, empty string to disable
+ virtual bool setProxy(const std::string &address) = 0;
};
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index 69d17eb02..900fe91e5 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -375,6 +375,10 @@ std::tuple<bool, std::string, std::string, std::string, std::string> WalletManag
return std::make_tuple(false, "", "", "", "");
}
+bool WalletManagerImpl::setProxy(const std::string &address)
+{
+ return m_http_client.set_proxy(address);
+}
///////////////////// WalletManagerFactory implementation //////////////////////
WalletManager *WalletManagerFactory::getWalletManager()
diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h
index ca8e9ada2..2f603b0a9 100644
--- a/src/wallet/api/wallet_manager.h
+++ b/src/wallet/api/wallet_manager.h
@@ -30,7 +30,7 @@
#include "wallet/api/wallet2_api.h"
-#include "net/http_client.h"
+#include "net/http.h"
#include <string>
namespace Monero {
@@ -92,11 +92,12 @@ public:
bool startMining(const std::string &address, uint32_t threads = 1, bool background_mining = false, bool ignore_battery = true) override;
bool stopMining() override;
std::string resolveOpenAlias(const std::string &address, bool &dnssec_valid) const override;
+ bool setProxy(const std::string &address) override;
private:
WalletManagerImpl() {}
friend struct WalletManagerFactory;
- epee::net_utils::http::http_simple_client m_http_client;
+ net::http::client m_http_client;
std::string m_errorString;
};
diff --git a/src/wallet/message_store.cpp b/src/wallet/message_store.cpp
index fb07b42f0..303b576c7 100644
--- a/src/wallet/message_store.cpp
+++ b/src/wallet/message_store.cpp
@@ -27,7 +27,6 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "message_store.h"
-#include <boost/archive/portable_binary_oarchive.hpp>
#include <boost/archive/portable_binary_iarchive.hpp>
#include <boost/format.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)
{
std::stringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- ar << m_signers;
+ binary_archive<true> ar(oss);
+ THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, m_signers), tools::error::wallet_internal_error, "Failed to serialize signer config");
signer_config = oss.str();
}
@@ -194,8 +193,8 @@ void message_store::unpack_signer_config(const multisig_wallet_state &state, con
{
std::stringstream iss;
iss << signer_config;
- boost::archive::portable_binary_iarchive ar(iss);
- ar >> signers;
+ binary_archive<false> ar(iss);
+ THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, signers), tools::error::wallet_internal_error, "Failed to serialize signer config");
}
catch (...)
{
@@ -364,8 +363,8 @@ size_t message_store::add_auto_config_data_message(const multisig_wallet_state &
data.monero_address = me.monero_address;
std::stringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- ar << data;
+ binary_archive<true> ar(oss);
+ 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());
}
@@ -384,8 +383,8 @@ void message_store::process_auto_config_data_message(uint32_t id)
{
std::stringstream iss;
iss << m.content;
- boost::archive::portable_binary_iarchive ar(iss);
- ar >> data;
+ binary_archive<false> ar(iss);
+ THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, data), tools::error::wallet_internal_error, "Failed to serialize auto config data");
}
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)
{
std::stringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- ar << *this;
+ binary_archive<true> ar(oss);
+ THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, *this), tools::error::wallet_internal_error, "Failed to serialize MMS state");
std::string buf = oss.str();
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;
std::stringstream file_oss;
- boost::archive::portable_binary_oarchive file_ar(file_oss);
- file_ar << write_file_data;
+ binary_archive<true> file_ar(file_oss);
+ 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());
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;
bool file_exists = boost::filesystem::exists(filename, ignored_ec);
@@ -785,17 +784,37 @@ 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);
THROW_WALLET_EXCEPTION_IF(!success, tools::error::file_read_error, filename);
+ bool loaded = false;
file_data read_file_data;
try
{
std::stringstream iss;
iss << buf;
- boost::archive::portable_binary_iarchive ar(iss);
- ar >> read_file_data;
+ binary_archive<false> ar(iss);
+ if (::serialization::serialize(ar, read_file_data))
+ if (::serialization::check_stream_state(ar))
+ loaded = true;
}
- catch (const std::exception &e)
+ catch (...) {}
+ if (!loaded && load_deprecated_formats)
+ {
+ try
+ {
+ std::stringstream iss;
+ iss << buf;
+ boost::archive::portable_binary_iarchive ar(iss);
+ ar >> read_file_data;
+ loaded = true;
+ }
+ catch (const std::exception &e)
+ {
+ MERROR("MMS file " << filename << " has bad structure <iv,encrypted_data>: " << e.what());
+ THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename);
+ }
+ }
+ if (!loaded)
{
- MERROR("MMS file " << filename << " has bad structure <iv,encrypted_data>: " << e.what());
+ MERROR("MMS file " << filename << " has bad structure <iv,encrypted_data>");
THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename);
}
@@ -805,16 +824,36 @@ void message_store::read_from_file(const multisig_wallet_state &state, const std
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]);
+ loaded = false;
try
{
std::stringstream iss;
iss << decrypted_data;
- boost::archive::portable_binary_iarchive ar(iss);
- ar >> *this;
+ binary_archive<false> ar(iss);
+ if (::serialization::serialize(ar, *this))
+ if (::serialization::check_stream_state(ar))
+ loaded = true;
}
- catch (const std::exception &e)
+ catch(...) {}
+ if (!loaded && load_deprecated_formats)
+ {
+ try
+ {
+ std::stringstream iss;
+ iss << decrypted_data;
+ boost::archive::portable_binary_iarchive ar(iss);
+ ar >> *this;
+ loaded = true;
+ }
+ catch (const std::exception &e)
+ {
+ MERROR("MMS file " << filename << " has bad structure: " << e.what());
+ THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename);
+ }
+ }
+ if (!loaded)
{
- MERROR("MMS file " << filename << " has bad structure: " << e.what());
+ MERROR("MMS file " << filename << " has bad structure");
THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename);
}
diff --git a/src/wallet/message_store.h b/src/wallet/message_store.h
index 9055fd776..0f53587d4 100644
--- a/src/wallet/message_store.h
+++ b/src/wallet/message_store.h
@@ -44,6 +44,9 @@
#include "common/command_line.h"
#include "wipeable_string.h"
#include "net/abstract_http_client.h"
+#include "serialization/crypto.h"
+#include "serialization/string.h"
+#include "serialization/containers.h"
#include "message_transporter.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
@@ -112,6 +115,24 @@ namespace mms
uint32_t round;
uint32_t signature_count;
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)
// 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;
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()
{
monero_address_known = false;
@@ -164,6 +200,13 @@ namespace mms
std::string label;
std::string transport_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
@@ -174,6 +217,13 @@ namespace mms
uint32_t file_version;
crypto::chacha_iv iv;
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
@@ -198,6 +248,19 @@ namespace mms
uint32_t multisig_rounds_passed;
size_t num_transfer_details;
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
@@ -283,7 +346,7 @@ namespace mms
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 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>
inline void serialize(t_archive &a, const unsigned int ver)
@@ -298,6 +361,18 @@ namespace mms
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_direction_to_string(message_direction direction);
static const char* message_state_to_string(message_state state);
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index ded5c7212..c67565570 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -48,6 +48,7 @@ using namespace epee;
#include "wallet_rpc_helpers.h"
#include "wallet2.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
+#include "net/parse.h"
#include "rpc/core_rpc_server_commands_defs.h"
#include "rpc/core_rpc_server_error_codes.h"
#include "rpc/rpc_payment_signature.h"
@@ -102,8 +103,8 @@ using namespace cryptonote;
// 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 UNSIGNED_TX_PREFIX "Monero unsigned tx set\004"
-#define SIGNED_TX_PREFIX "Monero signed tx set\004"
+#define UNSIGNED_TX_PREFIX "Monero unsigned tx set\005"
+#define SIGNED_TX_PREFIX "Monero signed tx set\005"
#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
@@ -440,30 +441,14 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
);
}
- boost::asio::ip::tcp::endpoint proxy{};
+ std::string proxy;
if (use_proxy)
{
- namespace ip = boost::asio::ip;
-
- const auto proxy_address = command_line::get_arg(vm, opts.proxy);
-
- boost::string_ref proxy_port{proxy_address};
- boost::string_ref proxy_host = proxy_port.substr(0, proxy_port.rfind(":"));
- if (proxy_port.size() == proxy_host.size())
- proxy_host = "127.0.0.1";
- else
- proxy_port = proxy_port.substr(proxy_host.size() + 1);
-
- uint16_t port_value = 0;
+ proxy = command_line::get_arg(vm, opts.proxy);
THROW_WALLET_EXCEPTION_IF(
- !epee::string_tools::get_xtype_from_string(port_value, std::string{proxy_port}),
+ !net::get_tcp_endpoint(proxy),
tools::error::wallet_internal_error,
- std::string{"Invalid port specified for --"} + opts.proxy.name
- );
-
- boost::system::error_code error{};
- proxy = ip::tcp::endpoint{ip::address::from_string(std::string{proxy_host}, error), port_value};
- THROW_WALLET_EXCEPTION_IF(bool(error), tools::error::wallet_internal_error, std::string{"Invalid IP address specified for --"} + opts.proxy.name);
+ std::string{"Invalid address specified for --"} + opts.proxy.name);
}
boost::optional<bool> trusted_daemon;
@@ -488,7 +473,10 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
}
std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(nettype, kdf_rounds, unattended));
- wallet->init(std::move(daemon_address), std::move(login), std::move(proxy), 0, *trusted_daemon, std::move(ssl_options));
+ if (!wallet->init(std::move(daemon_address), std::move(login), std::move(proxy), 0, *trusted_daemon, std::move(ssl_options)))
+ {
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to initialize the wallet"));
+ }
boost::filesystem::path ringdb_path = command_line::get_arg(vm, opts.shared_ringdb_dir);
wallet->set_ring_database(ringdb_path.string());
wallet->get_message_store().set_options(vm);
@@ -1125,7 +1113,7 @@ void wallet_device_callback::on_progress(const hw::device_progress& event)
}
wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std::unique_ptr<epee::net_utils::http::http_client_factory> http_client_factory):
- m_http_client(std::move(http_client_factory->create())),
+ m_http_client(http_client_factory->create()),
m_multisig_rescan_info(NULL),
m_multisig_rescan_k(NULL),
m_upper_transaction_weight_limit(0),
@@ -1195,6 +1183,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
m_offline(false),
m_rpc_version(0),
m_export_format(ExportFormat::Binary),
+ m_load_deprecated_formats(false),
m_credits_target(0)
{
set_rpc_client_secret_key(rct::rct2sk(rct::skGen()));
@@ -1325,18 +1314,17 @@ bool wallet2::set_daemon(std::string daemon_address, boost::optional<epee::net_u
return ret;
}
//----------------------------------------------------------------------------------------------------
-bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, boost::asio::ip::tcp::endpoint proxy, uint64_t upper_transaction_weight_limit, bool trusted_daemon, epee::net_utils::ssl_options_t ssl_options)
+bool wallet2::set_proxy(const std::string &address)
{
+ return m_http_client->set_proxy(address);
+}
+//----------------------------------------------------------------------------------------------------
+bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, const std::string &proxy_address, uint64_t upper_transaction_weight_limit, bool trusted_daemon, epee::net_utils::ssl_options_t ssl_options)
+{
+ CHECK_AND_ASSERT_MES(set_proxy(proxy_address), false, "failed to set proxy address");
m_checkpoints.init_default_checkpoints(m_nettype);
m_is_initialized = true;
m_upper_transaction_weight_limit = upper_transaction_weight_limit;
- if (proxy != boost::asio::ip::tcp::endpoint{})
- {
- epee::net_utils::http::abstract_http_client* abstract_http_client = m_http_client.get();
- epee::net_utils::http::http_simple_client* http_simple_client = dynamic_cast<epee::net_utils::http::http_simple_client*>(abstract_http_client);
- CHECK_AND_ASSERT_MES(http_simple_client != nullptr, false, "http_simple_client must be used to set proxy");
- http_simple_client->set_connector(net::socks::connector{std::move(proxy)});
- }
return set_daemon(daemon_address, daemon_login, trusted_daemon, std::move(ssl_options));
}
//----------------------------------------------------------------------------------------------------
@@ -3916,6 +3904,9 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee:
value2.SetInt(m_export_format);
json.AddMember("export_format", value2, json.GetAllocator());
+ value2.SetInt(m_load_deprecated_formats);
+ json.AddMember("load_deprecated_formats", value2, json.GetAllocator());
+
value2.SetUint(1);
json.AddMember("encrypted_secret_keys", value2, json.GetAllocator());
@@ -4085,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_original_keys_available = false;
m_export_format = ExportFormat::Binary;
+ m_load_deprecated_formats = false;
m_device_name = "";
m_device_derivation_path = "";
m_key_device_type = hw::device::device_type::SOFTWARE;
@@ -4265,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);
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());
if (m_device_name.empty())
{
@@ -5614,10 +5609,26 @@ 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]);
try {
- std::stringstream iss;
- iss << cache_data;
- boost::archive::portable_binary_iarchive ar(iss);
- ar >> *this;
+ 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;
+ iss << cache_data;
+ boost::archive::portable_binary_iarchive ar(iss);
+ ar >> *this;
+ }
}
catch(...)
{
@@ -5714,7 +5725,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
try
{
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)
{
@@ -5904,8 +5915,9 @@ boost::optional<wallet2::cache_file_data> wallet2::get_cache_file_data(const epe
try
{
std::stringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- ar << *this;
+ binary_archive<true> ar(oss);
+ if (!::serialization::serialize(ar, *this))
+ return boost::none;
boost::optional<wallet2::cache_file_data> cache_file_data = (wallet2::cache_file_data) {};
cache_file_data.get().cache_data = oss.str();
@@ -6567,10 +6579,11 @@ std::string wallet2::dump_tx_to_str(const std::vector<pending_tx> &ptx_vector) c
txs.transfers = export_outputs();
// save as binary
std::ostringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
+ binary_archive<true> ar(oss);
try
{
- ar << txs;
+ if (!::serialization::serialize(ar, txs))
+ return std::string();
}
catch (...)
{
@@ -6614,6 +6627,11 @@ bool wallet2::parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsi
s = s.substr(1);
if (version == '\003')
{
+ if (!m_load_deprecated_formats)
+ {
+ LOG_PRINT_L0("Not loading deprecated format");
+ return false;
+ }
try
{
std::istringstream iss(s);
@@ -6628,6 +6646,11 @@ bool wallet2::parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsi
}
else if (version == '\004')
{
+ if (!m_load_deprecated_formats)
+ {
+ LOG_PRINT_L0("Not loading deprecated format");
+ return false;
+ }
try
{
s = decrypt_with_view_secret_key(s);
@@ -6649,6 +6672,26 @@ bool wallet2::parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsi
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
{
LOG_PRINT_L0("Unsupported version in unsigned tx");
@@ -6846,10 +6889,11 @@ std::string wallet2::sign_tx_dump_to_str(unsigned_tx_set &exported_txs, std::vec
// save as binary
std::ostringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
+ binary_archive<true> ar(oss);
try
{
- ar << signed_txes;
+ if (!::serialization::serialize(ar, signed_txes))
+ return std::string();
}
catch(...)
{
@@ -6898,6 +6942,11 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too
s = s.substr(1);
if (version == '\003')
{
+ if (!m_load_deprecated_formats)
+ {
+ LOG_PRINT_L0("Not loading deprecated format");
+ return false;
+ }
try
{
std::istringstream iss(s);
@@ -6912,6 +6961,11 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too
}
else if (version == '\004')
{
+ if (!m_load_deprecated_formats)
+ {
+ LOG_PRINT_L0("Not loading deprecated format");
+ return false;
+ }
try
{
s = decrypt_with_view_secret_key(s);
@@ -6933,6 +6987,26 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too
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
{
LOG_PRINT_L0("Unsupported version in signed transaction");
@@ -6984,10 +7058,11 @@ std::string wallet2::save_multisig_tx(multisig_tx_set txs)
// save as binary
std::ostringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
+ binary_archive<true> ar(oss);
try
{
- ar << txs;
+ if (!::serialization::serialize(ar, txs))
+ return std::string();
}
catch (...)
{
@@ -7051,13 +7126,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());
return false;
}
+ bool loaded = false;
try
{
std::istringstream iss(multisig_tx_st);
- boost::archive::portable_binary_iarchive ar(iss);
- ar >> exported_txs;
+ binary_archive<false> ar(iss);
+ if (::serialization::serialize(ar, exported_txs))
+ if (::serialization::check_stream_state(ar))
+ loaded = true;
}
- catch (...)
+ catch (...) {}
+ try
+ {
+ if (!loaded && m_load_deprecated_formats)
+ {
+ std::istringstream iss(multisig_tx_st);
+ boost::archive::portable_binary_iarchive ar(iss);
+ ar >> exported_txs;
+ loaded = true;
+ }
+ }
+ catch(...) {}
+
+ if (!loaded)
{
LOG_PRINT_L0("Failed to parse multisig tx data");
return false;
@@ -9544,8 +9635,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)
{
// Lookup key image from cache
- std::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_map<uint64_t, crypto::key_image> index_keyimage_map;
+ 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()) {
// pub key found. key image for index cached?
index_keyimage_map = found_pub_key->second;
@@ -11425,7 +11516,7 @@ std::string wallet2::get_tx_proof(const cryptonote::transaction &tx, const crypt
hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[i], additional_tx_keys[i - 1], sig[i]);
}
}
- sig_str = std::string("OutProofV1");
+ sig_str = std::string("OutProofV2");
}
else
{
@@ -11461,7 +11552,7 @@ std::string wallet2::get_tx_proof(const cryptonote::transaction &tx, const crypt
hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i - 1], boost::none, shared_secret[i], a, sig[i]);
}
}
- sig_str = std::string("InProofV1");
+ sig_str = std::string("InProofV2");
}
const size_t num_sigs = shared_secret.size();
@@ -11540,8 +11631,14 @@ bool wallet2::check_tx_proof(const crypto::hash &txid, const cryptonote::account
bool wallet2::check_tx_proof(const cryptonote::transaction &tx, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message, const std::string &sig_str, uint64_t &received) const
{
+ // InProofV1, InProofV2, OutProofV1, OutProofV2
const bool is_out = sig_str.substr(0, 3) == "Out";
- const std::string header = is_out ? "OutProofV1" : "InProofV1";
+ const std::string header = is_out ? sig_str.substr(0,10) : sig_str.substr(0,9);
+ int version = 2; // InProofV2
+ if (is_out && sig_str.substr(8,2) == "V1") version = 1; // OutProofV1
+ else if (is_out) version = 2; // OutProofV2
+ else if (sig_str.substr(7,2) == "V1") version = 1; // InProofV1
+
const size_t header_len = header.size();
THROW_WALLET_EXCEPTION_IF(sig_str.size() < header_len || sig_str.substr(0, header_len) != header, error::wallet_internal_error,
"Signature header check error");
@@ -11588,27 +11685,27 @@ bool wallet2::check_tx_proof(const cryptonote::transaction &tx, const cryptonote
if (is_out)
{
good_signature[0] = is_subaddress ?
- crypto::check_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[0], sig[0]) :
- crypto::check_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[0], sig[0]);
+ crypto::check_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[0], sig[0], version) :
+ crypto::check_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[0], sig[0], version);
for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
{
good_signature[i + 1] = is_subaddress ?
- crypto::check_tx_proof(prefix_hash, additional_tx_pub_keys[i], address.m_view_public_key, address.m_spend_public_key, shared_secret[i + 1], sig[i + 1]) :
- crypto::check_tx_proof(prefix_hash, additional_tx_pub_keys[i], address.m_view_public_key, boost::none, shared_secret[i + 1], sig[i + 1]);
+ crypto::check_tx_proof(prefix_hash, additional_tx_pub_keys[i], address.m_view_public_key, address.m_spend_public_key, shared_secret[i + 1], sig[i + 1], version) :
+ crypto::check_tx_proof(prefix_hash, additional_tx_pub_keys[i], address.m_view_public_key, boost::none, shared_secret[i + 1], sig[i + 1], version);
}
}
else
{
good_signature[0] = is_subaddress ?
- crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, address.m_spend_public_key, shared_secret[0], sig[0]) :
- crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, shared_secret[0], sig[0]);
+ crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, address.m_spend_public_key, shared_secret[0], sig[0], version) :
+ crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, shared_secret[0], sig[0], version);
for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
{
good_signature[i + 1] = is_subaddress ?
- crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i], address.m_spend_public_key, shared_secret[i + 1], sig[i + 1]) :
- crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i], boost::none, shared_secret[i + 1], sig[i + 1]);
+ crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i], address.m_spend_public_key, shared_secret[i + 1], sig[i + 1], version) :
+ crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i], boost::none, shared_secret[i + 1], sig[i + 1], version);
}
}
@@ -11727,7 +11824,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
- 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)
{
crypto::secret_key subaddr_spend_skey = m_account.get_keys().m_spend_secret_key;
@@ -11744,9 +11841,10 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t,
// serialize & encode
std::ostringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- ar << proofs << subaddr_spendkeys;
- return "ReserveProofV1" + tools::base58::encode(oss.str());
+ binary_archive<true> ar(oss);
+ 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());
}
bool wallet2::check_reserve_proof(const cryptonote::account_public_address &address, const std::string &message, const std::string &sig_str, uint64_t &total, uint64_t &spent)
@@ -11755,19 +11853,39 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr
THROW_WALLET_EXCEPTION_IF(!check_connection(&rpc_version), error::wallet_internal_error, "Failed to connect to daemon: " + get_daemon_address());
THROW_WALLET_EXCEPTION_IF(rpc_version < MAKE_CORE_RPC_VERSION(1, 0), error::wallet_internal_error, "Daemon RPC version is too old");
- static constexpr char header[] = "ReserveProofV1";
- THROW_WALLET_EXCEPTION_IF(!boost::string_ref{sig_str}.starts_with(header), error::wallet_internal_error,
+ static constexpr char header_v1[] = "ReserveProofV1";
+ static constexpr char header_v2[] = "ReserveProofV2"; // assumes same length as header_v1
+ THROW_WALLET_EXCEPTION_IF(!boost::string_ref{sig_str}.starts_with(header_v1) && !boost::string_ref{sig_str}.starts_with(header_v2), error::wallet_internal_error,
"Signature header check error");
+ int version = 2; // assume newest version
+ if (boost::string_ref{sig_str}.starts_with(header_v1))
+ version = 1;
+ else if (boost::string_ref{sig_str}.starts_with(header_v2))
+ version = 2;
std::string sig_decoded;
- THROW_WALLET_EXCEPTION_IF(!tools::base58::decode(sig_str.substr(std::strlen(header)), 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");
- std::istringstream iss(sig_decoded);
- boost::archive::portable_binary_iarchive ar(iss);
+ bool loaded = false;
std::vector<reserve_proof_entry> proofs;
- std::unordered_map<crypto::public_key, crypto::signature> subaddr_spendkeys;
- ar >> proofs >> subaddr_spendkeys;
+ 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);
+ boost::archive::portable_binary_iarchive ar(iss);
+ ar >> proofs >> subaddr_spendkeys.parent();
+ }
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");
@@ -11841,9 +11959,9 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr
const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(tx);
// check singature for shared secret
- ok = crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, proof.shared_secret, proof.shared_secret_sig);
+ ok = crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, proof.shared_secret, proof.shared_secret_sig, version);
if (!ok && additional_tx_pub_keys.size() == tx.vout.size())
- ok = crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[proof.index_in_tx], boost::none, proof.shared_secret, proof.shared_secret_sig);
+ ok = crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[proof.index_in_tx], boost::none, proof.shared_secret, proof.shared_secret_sig, version);
if (!ok)
return false;
@@ -12006,7 +12124,7 @@ std::string wallet2::get_description() const
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
if (m_account_tags.second.size() != get_num_subaddress_accounts())
@@ -12728,9 +12846,9 @@ std::string wallet2::export_outputs_to_str(bool all) const
PERF_TIMER(export_outputs_to_str);
std::stringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- const auto& outputs = export_outputs(all);
- ar << outputs;
+ binary_archive<true> ar(oss);
+ auto outputs = export_outputs(all);
+ 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));
const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
@@ -12842,23 +12960,39 @@ size_t wallet2::import_outputs_from_str(const std::string &outputs_st)
}
size_t imported_outputs = 0;
+ bool loaded = false;
try
{
std::string body(data, headerlen);
- std::stringstream iss;
- iss << body;
std::pair<size_t, std::vector<tools::wallet2::transfer_details>> outputs;
try
{
- boost::archive::portable_binary_iarchive ar(iss);
- ar >> outputs;
+ std::stringstream iss;
+ iss << body;
+ binary_archive<false> ar(iss);
+ if (::serialization::serialize(ar, outputs))
+ if (::serialization::check_stream_state(ar))
+ loaded = true;
}
- catch (...)
+ catch (...) {}
+
+ if (!loaded && m_load_deprecated_formats)
{
- iss.str("");
- iss << body;
- boost::archive::binary_iarchive ar(iss);
- ar >> outputs;
+ try
+ {
+ std::stringstream iss;
+ iss << body;
+ boost::archive::portable_binary_iarchive ar(iss);
+ ar >> outputs;
+ loaded = true;
+ }
+ catch (...) {}
+ }
+
+ if (!loaded)
+ {
+ outputs.first = 0;
+ outputs.second = {};
}
imported_outputs = import_outputs(outputs);
@@ -13012,8 +13146,8 @@ cryptonote::blobdata wallet2::export_multisig()
}
std::stringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- ar << info;
+ binary_archive<true> ar(oss);
+ 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;
std::string header;
@@ -13083,10 +13217,26 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
seen.insert(signer);
std::string body(data, headerlen);
- std::istringstream iss(body);
std::vector<tools::wallet2::multisig_info> i;
- boost::archive::portable_binary_iarchive ar(iss);
- ar >> 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);
+ 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()));
info.push_back(std::move(i));
}
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 712f91613..92a38a01d 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -45,7 +45,7 @@
#include "cryptonote_basic/account.h"
#include "cryptonote_basic/account_boost_serialization.h"
#include "cryptonote_basic/cryptonote_basic_impl.h"
-#include "net/http_client.h"
+#include "net/http.h"
#include "storages/http_abstract_invoke.h"
#include "rpc/core_rpc_server_commands_defs.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
@@ -57,7 +57,10 @@
#include "ringct/rctTypes.h"
#include "ringct/rctOps.h"
#include "checkpoints/checkpoints.h"
+#include "serialization/crypto.h"
+#include "serialization/string.h"
#include "serialization/pair.h"
+#include "serialization/containers.h"
#include "wallet_errors.h"
#include "common/password.h"
@@ -205,6 +208,13 @@ private:
a & m_blockchain;
}
+ BEGIN_SERIALIZE_OBJECT()
+ VERSION_FIELD(0)
+ VARINT_FIELD(m_offset)
+ FIELD(m_genesis)
+ FIELD(m_blockchain)
+ END_SERIALIZE()
+
private:
size_t m_offset;
crypto::hash m_genesis;
@@ -269,7 +279,7 @@ private:
static bool verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key, hw::device &hwdev, uint64_t kdf_rounds);
static bool query_device(hw::device::device_type& device_type, const std::string& keys_file_name, const epee::wipeable_string& password, uint64_t kdf_rounds = 1);
- wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, uint64_t kdf_rounds = 1, bool unattended = false, std::unique_ptr<epee::net_utils::http::http_client_factory> http_client_factory = std::unique_ptr<epee::net_utils::http::http_simple_client_factory>(new epee::net_utils::http::http_simple_client_factory()));
+ wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, uint64_t kdf_rounds = 1, bool unattended = false, std::unique_ptr<epee::net_utils::http::http_client_factory> http_client_factory = std::unique_ptr<epee::net_utils::http::http_client_factory>(new net::http::client_factory()));
~wallet2();
struct multisig_info
@@ -372,6 +382,19 @@ private:
uint64_t m_timestamp;
bool m_coinbase;
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
@@ -384,6 +407,12 @@ private:
{
payment_details m_pd;
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
@@ -400,6 +429,21 @@ private:
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::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
@@ -419,6 +463,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(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) {}
+
+ 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
@@ -451,7 +510,7 @@ private:
};
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
{
@@ -460,6 +519,15 @@ private:
std::unordered_set<rct::key> used_L;
std::unordered_set<crypto::public_key> signing_keys;
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:
@@ -502,13 +570,26 @@ private:
{
std::vector<tx_construction_data> txes;
std::pair<size_t, wallet2::transfer_container> transfers;
+
+ BEGIN_SERIALIZE_OBJECT()
+ VERSION_FIELD(0)
+ FIELD(txes)
+ FIELD(transfers)
+ END_SERIALIZE()
};
struct signed_tx_set
{
std::vector<pending_tx> ptx;
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
@@ -543,7 +624,7 @@ private:
FIELD(cache_data)
END_SERIALIZE()
};
-
+
// GUI Address book
struct address_book_row
{
@@ -552,6 +633,15 @@ private:
std::string m_description;
bool m_is_subaddress;
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
@@ -562,6 +652,16 @@ private:
crypto::key_image key_image;
crypto::signature shared_secret_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;
@@ -753,13 +853,14 @@ private:
bool deinit();
bool init(std::string daemon_address = "http://localhost:8080",
boost::optional<epee::net_utils::http::login> daemon_login = boost::none,
- boost::asio::ip::tcp::endpoint proxy = {},
+ const std::string &proxy = "",
uint64_t upper_transaction_weight_limit = 0,
bool trusted_daemon = true,
epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect);
bool set_daemon(std::string daemon_address = "http://localhost:8080",
boost::optional<epee::net_utils::http::login> daemon_login = boost::none, bool trusted_daemon = true,
epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect);
+ bool set_proxy(const std::string &address);
void stop() { m_run.store(false, std::memory_order_relaxed); m_message_store.stop(); }
@@ -917,6 +1018,7 @@ private:
{
std::vector<crypto::hash> blockchain;
a & blockchain;
+ m_blockchain.clear();
for (const auto &b: blockchain)
{
m_blockchain.push_back(b);
@@ -928,25 +1030,25 @@ private:
}
a & m_transfers;
a & m_account_public_address;
- a & m_key_images;
+ a & m_key_images.parent();
if(ver < 6)
return;
- a & m_unconfirmed_txs;
+ a & m_unconfirmed_txs.parent();
if(ver < 7)
return;
- a & m_payments;
+ a & m_payments.parent();
if(ver < 8)
return;
- a & m_tx_keys;
+ a & m_tx_keys.parent();
if(ver < 9)
return;
- a & m_confirmed_txs;
+ a & m_confirmed_txs.parent();
if(ver < 11)
return;
a & dummy_refresh_height;
if(ver < 12)
return;
- a & m_tx_notes;
+ a & m_tx_notes.parent();
if(ver < 13)
return;
if (ver < 17)
@@ -954,6 +1056,7 @@ private:
// we're loading an old version, where m_unconfirmed_payments was a std::map
std::unordered_map<crypto::hash, payment_details> m;
a & m;
+ m_unconfirmed_payments.clear();
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}));
}
@@ -962,6 +1065,7 @@ private:
if(ver < 15)
{
// 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)
{
const transfer_details &td = m_transfers[i];
@@ -971,7 +1075,7 @@ private:
}
return;
}
- a & m_pub_keys;
+ a & m_pub_keys.parent();
if(ver < 16)
return;
a & m_address_book;
@@ -982,6 +1086,7 @@ private:
// we're loading an old version, where m_unconfirmed_payments payload was payment_details
std::unordered_multimap<crypto::hash, payment_details> m;
a & m;
+ m_unconfirmed_payments.clear();
for (const auto &i: m)
m_unconfirmed_payments.insert(std::make_pair(i.first, pool_payment_details{i.second, false}));
}
@@ -991,20 +1096,20 @@ private:
a & m_scanned_pool_txs[1];
if (ver < 20)
return;
- a & m_subaddresses;
+ a & m_subaddresses.parent();
std::unordered_map<cryptonote::subaddress_index, crypto::public_key> dummy_subaddresses_inv;
a & dummy_subaddresses_inv;
a & m_subaddress_labels;
- a & m_additional_tx_keys;
+ a & m_additional_tx_keys.parent();
if(ver < 21)
return;
- a & m_attributes;
+ a & m_attributes.parent();
if(ver < 22)
return;
- a & m_unconfirmed_payments;
+ a & m_unconfirmed_payments.parent();
if(ver < 23)
return;
- a & m_account_tags;
+ a & (std::pair<std::map<std::string, std::string>, std::vector<std::string>>&)m_account_tags;
if(ver < 24)
return;
a & m_ring_history_saved;
@@ -1013,18 +1118,48 @@ private:
a & m_last_block_reward;
if(ver < 26)
return;
- a & m_tx_device;
+ a & m_tx_device.parent();
if(ver < 27)
return;
a & m_device_last_key_image_sync;
if(ver < 28)
return;
- a & m_cold_key_images;
+ a & m_cold_key_images.parent();
if(ver < 29)
return;
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
* \param file_path Wallet file path
@@ -1096,6 +1231,8 @@ private:
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; }
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; }
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; }
@@ -1187,7 +1324,7 @@ private:
* \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)
*/
- 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.
* \param account_indices Indices of accounts.
@@ -1527,28 +1664,28 @@ private:
std::string m_mms_file;
const std::unique_ptr<epee::net_utils::http::abstract_http_client> m_http_client;
hashchain m_blockchain;
- std::unordered_map<crypto::hash, unconfirmed_transfer_details> m_unconfirmed_txs;
- std::unordered_map<crypto::hash, confirmed_transfer_details> m_confirmed_txs;
- std::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, unconfirmed_transfer_details> m_unconfirmed_txs;
+ serializable_unordered_map<crypto::hash, confirmed_transfer_details> m_confirmed_txs;
+ serializable_unordered_multimap<crypto::hash, pool_payment_details> m_unconfirmed_payments;
+ serializable_unordered_map<crypto::hash, crypto::secret_key> m_tx_keys;
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;
payment_container m_payments;
- std::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::key_image, size_t> m_key_images;
+ serializable_unordered_map<crypto::public_key, size_t> m_pub_keys;
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::unordered_map<crypto::hash, std::string> m_tx_notes;
- std::unordered_map<std::string, std::string> m_attributes;
+ serializable_unordered_map<crypto::hash, std::string> m_tx_notes;
+ serializable_unordered_map<std::string, std::string> m_attributes;
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
const std::vector<std::vector<tools::wallet2::multisig_info>> *m_multisig_rescan_info;
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;
@@ -1615,7 +1752,7 @@ private:
uint64_t m_credits_target;
// 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
bool m_light_wallet; /* sends view key to daemon for scanning */
@@ -1629,7 +1766,7 @@ private:
// 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;
// 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;
bool m_ring_history_saved;
@@ -1656,6 +1793,7 @@ private:
std::unique_ptr<wallet_device_callback> m_device_callback;
ExportFormat m_export_format;
+ bool m_load_deprecated_formats;
static boost::mutex default_daemon_address_lock;
static std::string default_daemon_address;
@@ -2052,7 +2190,7 @@ namespace boost
a & x.key_images;
if (ver < 1)
return;
- a & x.tx_key_images;
+ a & x.tx_key_images.parent();
}
template <class Archive>
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index fcaaf7616..0ed749cb7 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -80,7 +80,7 @@ namespace
return pwd_container;
}
//------------------------------------------------------------------------------------------------------------------------------
- void set_confirmations(tools::wallet_rpc::transfer_entry &entry, uint64_t blockchain_height, uint64_t block_reward)
+ void set_confirmations(tools::wallet_rpc::transfer_entry &entry, uint64_t blockchain_height, uint64_t block_reward, uint64_t unlock_time)
{
if (entry.height >= blockchain_height || (entry.height == 0 && (!strcmp(entry.type.c_str(), "pending") || !strcmp(entry.type.c_str(), "pool"))))
entry.confirmations = 0;
@@ -91,6 +91,18 @@ namespace
entry.suggested_confirmations_threshold = 0;
else
entry.suggested_confirmations_threshold = (entry.amount + block_reward - 1) / block_reward;
+
+ if (unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
+ {
+ if (unlock_time > blockchain_height)
+ entry.suggested_confirmations_threshold = std::max(entry.suggested_confirmations_threshold, unlock_time - blockchain_height);
+ }
+ else
+ {
+ const uint64_t now = time(NULL);
+ if (unlock_time > now)
+ entry.suggested_confirmations_threshold = std::max(entry.suggested_confirmations_threshold, (unlock_time - now + DIFFICULTY_TARGET_V2 - 1) / DIFFICULTY_TARGET_V2);
+ }
}
}
@@ -335,7 +347,7 @@ namespace tools
entry.subaddr_index = pd.m_subaddr_index;
entry.subaddr_indices.push_back(pd.m_subaddr_index);
entry.address = m_wallet->get_subaddress_as_str(pd.m_subaddr_index);
- set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward());
+ set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward(), pd.m_unlock_time);
}
//------------------------------------------------------------------------------------------------------------------------------
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::confirmed_transfer_details &pd)
@@ -365,7 +377,7 @@ namespace tools
for (uint32_t i: pd.m_subaddr_indices)
entry.subaddr_indices.push_back({pd.m_subaddr_account, i});
entry.address = m_wallet->get_subaddress_as_str({pd.m_subaddr_account, 0});
- set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward());
+ set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward(), pd.m_unlock_time);
}
//------------------------------------------------------------------------------------------------------------------------------
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::unconfirmed_transfer_details &pd)
@@ -396,7 +408,7 @@ namespace tools
for (uint32_t i: pd.m_subaddr_indices)
entry.subaddr_indices.push_back({pd.m_subaddr_account, i});
entry.address = m_wallet->get_subaddress_as_str({pd.m_subaddr_account, 0});
- set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward());
+ set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward(), pd.m_tx.unlock_time);
}
//------------------------------------------------------------------------------------------------------------------------------
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &payment_id, const tools::wallet2::pool_payment_details &ppd)
@@ -419,7 +431,7 @@ namespace tools
entry.subaddr_index = pd.m_subaddr_index;
entry.subaddr_indices.push_back(pd.m_subaddr_index);
entry.address = m_wallet->get_subaddress_as_str(pd.m_subaddr_index);
- set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward());
+ set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward(), pd.m_unlock_time);
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE::request& req, wallet_rpc::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er, const connection_context *ctx)
@@ -826,10 +838,11 @@ namespace tools
static std::string ptx_to_string(const tools::wallet2::pending_tx &ptx)
{
std::ostringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
+ binary_archive<true> ar(oss);
try
{
- ar << ptx;
+ if (!::serialization::serialize(ar, const_cast<tools::wallet2::pending_tx&>(ptx)))
+ return "";
}
catch (...)
{
@@ -1538,14 +1551,31 @@ namespace tools
return false;
}
+ bool loaded = false;
tools::wallet2::pending_tx ptx;
+
try
{
std::istringstream iss(blob);
- boost::archive::portable_binary_iarchive ar(iss);
- ar >> ptx;
+ binary_archive<false> ar(iss);
+ if (::serialization::serialize(ar, ptx))
+ loaded = true;
}
- catch (...)
+ catch(...) {}
+
+ if (!loaded && !m_restricted)
+ {
+ try
+ {
+ std::istringstream iss(blob);
+ boost::archive::portable_binary_iarchive ar(iss);
+ ar >> ptx;
+ loaded = true;
+ }
+ catch (...) {}
+ }
+
+ if (!loaded)
{
er.code = WALLET_RPC_ERROR_CODE_BAD_TX_METADATA;
er.message = "Failed to parse tx metadata.";
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index ae861d177..5b2536bf1 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -47,7 +47,7 @@
// advance which version they will stop working with
// Don't go over 32767 for any of these
#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 WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR)
namespace tools