aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/wallet2.cpp')
-rw-r--r--src/wallet/wallet2.cpp121
1 files changed, 68 insertions, 53 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 1c4671150..133db6c2a 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -37,6 +37,7 @@
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/join.hpp>
+#include <boost/algorithm/string/predicate.hpp>
#include <boost/asio/ip/address.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/preprocessor/stringize.hpp>
@@ -5703,12 +5704,18 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
try
{
- std::stringstream iss;
- iss << cache_data;
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(cache_data)};
if (::serialization::serialize(ar, *this))
if (::serialization::check_stream_state(ar))
loaded = true;
+ if (!loaded)
+ {
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(cache_data)};
+ ar.enable_varint_bug_backward_compatibility();
+ if (::serialization::serialize(ar, *this))
+ if (::serialization::check_stream_state(ar))
+ loaded = true;
+ }
}
catch(...) { }
@@ -6028,7 +6035,7 @@ uint64_t wallet2::balance(uint32_t index_major, bool strict) const
{
uint64_t amount = 0;
if(m_light_wallet)
- return m_light_wallet_unlocked_balance;
+ return m_light_wallet_balance;
for (const auto& i : balance_per_subaddress(index_major, strict))
amount += i.second;
return amount;
@@ -6042,7 +6049,7 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t *
if (time_to_unlock)
*time_to_unlock = 0;
if(m_light_wallet)
- return m_light_wallet_balance;
+ return m_light_wallet_unlocked_balance;
for (const auto& i : unlocked_balance_per_subaddress(index_major, strict))
{
amount += i.second.first;
@@ -6778,8 +6785,7 @@ bool wallet2::parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsi
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);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(s)};
if (!::serialization::serialize(ar, exported_txs))
{
LOG_PRINT_L0("Failed to parse data from unsigned tx");
@@ -7093,8 +7099,7 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too
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);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(s)};
if (!::serialization::serialize(ar, signed_txs))
{
LOG_PRINT_L0("Failed to deserialize signed transaction");
@@ -7229,8 +7234,7 @@ bool wallet2::parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx
bool loaded = false;
try
{
- std::istringstream iss(multisig_tx_st);
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(multisig_tx_st)};
if (::serialization::serialize(ar, exported_txs))
if (::serialization::check_stream_state(ar))
loaded = true;
@@ -8753,7 +8757,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
// throw if total amount overflows uint64_t
for(auto& dt: dsts)
{
- THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
+ THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_amount);
needed_money += dt.amount;
LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money));
THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype);
@@ -8912,7 +8916,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
// throw if total amount overflows uint64_t
for(auto& dt: dsts)
{
- THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
+ THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_amount);
needed_money += dt.amount;
LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money));
THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype);
@@ -9885,14 +9889,14 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
needed_money = 0;
for(auto& dt: dsts)
{
- THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
+ THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_amount);
needed_money += dt.amount;
LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money));
THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, 0, m_nettype);
}
// throw if attempting a transaction with no money
- THROW_WALLET_EXCEPTION_IF(needed_money == 0, error::zero_destination);
+ THROW_WALLET_EXCEPTION_IF(needed_money == 0, error::zero_amount);
std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddr = unlocked_balance_per_subaddress(subaddr_account, false);
std::map<uint32_t, uint64_t> balance_per_subaddr = balance_per_subaddress(subaddr_account, false);
@@ -11508,6 +11512,9 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations)
{
+ uint32_t rpc_version;
+ THROW_WALLET_EXCEPTION_IF(!check_connection(&rpc_version), error::wallet_internal_error, "Failed to connect to daemon: " + get_daemon_address());
+
COMMAND_RPC_GET_TRANSACTIONS::request req;
COMMAND_RPC_GET_TRANSACTIONS::response res;
req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
@@ -11553,10 +11560,17 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de
confirmations = 0;
if (!in_pool)
{
- std::string err;
- uint64_t bc_height = get_daemon_blockchain_height(err);
- if (err.empty())
- confirmations = bc_height - res.txs.front().block_height;
+ if (rpc_version < MAKE_CORE_RPC_VERSION(3, 7))
+ {
+ std::string err;
+ uint64_t bc_height = get_daemon_blockchain_height(err);
+ if (err.empty() && bc_height > res.txs.front().block_height)
+ confirmations = bc_height - res.txs.front().block_height;
+ }
+ else
+ {
+ confirmations = res.txs.front().confirmations;
+ }
}
}
@@ -12019,8 +12033,7 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr
serializable_unordered_map<crypto::public_key, crypto::signature> subaddr_spendkeys;
try
{
- std::istringstream iss(sig_decoded);
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(sig_decoded)};
if (::serialization::serialize_noeof(ar, proofs))
if (::serialization::serialize_noeof(ar, subaddr_spendkeys))
if (::serialization::check_stream_state(ar))
@@ -12220,7 +12233,7 @@ uint64_t wallet2::get_approximate_blockchain_height() const
// Calculated blockchain height
uint64_t approx_blockchain_height = fork_block + (time(NULL) - fork_time)/seconds_per_block;
// testnet got some huge rollbacks, so the estimation is way off
- static const uint64_t approximate_testnet_rolled_back_blocks = 303967;
+ static const uint64_t approximate_testnet_rolled_back_blocks = 342100;
if (m_nettype == TESTNET && approx_blockchain_height > approximate_testnet_rolled_back_blocks)
approx_blockchain_height -= approximate_testnet_rolled_back_blocks;
LOG_PRINT_L2("Calculated blockchain height: " << approx_blockchain_height);
@@ -12531,7 +12544,7 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle
bool wallet2::export_key_images(const std::string &filename, bool all) const
{
PERF_TIMER(export_key_images);
- std::pair<size_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(all);
+ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(all);
std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC));
const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
const uint32_t offset = ski.first;
@@ -12558,7 +12571,7 @@ bool wallet2::export_key_images(const std::string &filename, bool all) const
}
//----------------------------------------------------------------------------------------------------
-std::pair<size_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> wallet2::export_key_images(bool all) const
+std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> wallet2::export_key_images(bool all) const
{
PERF_TIMER(export_key_images_raw);
std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
@@ -13055,7 +13068,7 @@ void wallet2::import_blockchain(const std::tuple<size_t, crypto::hash, std::vect
m_last_block_reward = cryptonote::get_outs_money_amount(genesis.miner_tx);
}
//----------------------------------------------------------------------------------------------------
-std::pair<size_t, std::vector<tools::wallet2::transfer_details>> wallet2::export_outputs(bool all) const
+std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> wallet2::export_outputs(bool all) const
{
PERF_TIMER(export_outputs);
std::vector<tools::wallet2::transfer_details> outs;
@@ -13095,7 +13108,7 @@ std::string wallet2::export_outputs_to_str(bool all) const
return magic + ciphertext;
}
//----------------------------------------------------------------------------------------------------
-size_t wallet2::import_outputs(const std::pair<size_t, std::vector<tools::wallet2::transfer_details>> &outputs)
+size_t wallet2::import_outputs(const std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> &outputs)
{
PERF_TIMER(import_outputs);
@@ -13201,12 +13214,10 @@ size_t wallet2::import_outputs_from_str(const std::string &outputs_st)
try
{
std::string body(data, headerlen);
- std::pair<size_t, std::vector<tools::wallet2::transfer_details>> outputs;
+ std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> outputs;
try
{
- std::stringstream iss;
- iss << body;
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(body)};
if (::serialization::serialize(ar, outputs))
if (::serialization::check_stream_state(ar))
loaded = true;
@@ -13458,8 +13469,7 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
bool loaded = false;
try
{
- std::istringstream iss(body);
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(body)};
if (::serialization::serialize(ar, i))
if (::serialization::check_stream_state(ar))
loaded = true;
@@ -14181,15 +14191,15 @@ void wallet2::hash_m_transfer(const transfer_details & transfer, crypto::hash &h
KECCAK_CTX state;
keccak_init(&state);
keccak_update(&state, (const uint8_t *) transfer.m_txid.data, sizeof(transfer.m_txid.data));
- keccak_update(&state, (const uint8_t *) transfer.m_internal_output_index, sizeof(transfer.m_internal_output_index));
- keccak_update(&state, (const uint8_t *) transfer.m_global_output_index, sizeof(transfer.m_global_output_index));
- keccak_update(&state, (const uint8_t *) transfer.m_amount, sizeof(transfer.m_amount));
+ keccak_update(&state, (const uint8_t *) &transfer.m_internal_output_index, sizeof(transfer.m_internal_output_index));
+ keccak_update(&state, (const uint8_t *) &transfer.m_global_output_index, sizeof(transfer.m_global_output_index));
+ keccak_update(&state, (const uint8_t *) &transfer.m_amount, sizeof(transfer.m_amount));
keccak_finish(&state, (uint8_t *) hash.data);
}
//----------------------------------------------------------------------------------------------------
-uint64_t wallet2::hash_m_transfers(int64_t transfer_height, crypto::hash &hash) const
+uint64_t wallet2::hash_m_transfers(boost::optional<uint64_t> transfer_height, crypto::hash &hash) const
{
- CHECK_AND_ASSERT_THROW_MES(transfer_height > (int64_t)m_transfers.size(), "Hash height is greater than number of transfers");
+ CHECK_AND_ASSERT_THROW_MES(!transfer_height || *transfer_height <= m_transfers.size(), "Hash height is greater than number of transfers");
KECCAK_CTX state;
crypto::hash tmp_hash{};
@@ -14197,12 +14207,12 @@ uint64_t wallet2::hash_m_transfers(int64_t transfer_height, crypto::hash &hash)
keccak_init(&state);
for(const transfer_details & transfer : m_transfers){
- if (transfer_height >= 0 && current_height >= (uint64_t)transfer_height){
+ if (transfer_height && current_height >= *transfer_height){
break;
}
hash_m_transfer(transfer, tmp_hash);
- keccak_update(&state, (const uint8_t *) transfer.m_block_height, sizeof(transfer.m_block_height));
+ keccak_update(&state, (const uint8_t *) &transfer.m_block_height, sizeof(transfer.m_block_height));
keccak_update(&state, (const uint8_t *) tmp_hash.data, sizeof(tmp_hash.data));
current_height += 1;
}
@@ -14214,23 +14224,28 @@ uint64_t wallet2::hash_m_transfers(int64_t transfer_height, crypto::hash &hash)
void wallet2::finish_rescan_bc_keep_key_images(uint64_t transfer_height, const crypto::hash &hash)
{
// Compute hash of m_transfers, if differs there had to be BC reorg.
- crypto::hash new_transfers_hash{};
- hash_m_transfers((int64_t) transfer_height, new_transfers_hash);
+ if (transfer_height <= m_transfers.size()) {
+ crypto::hash new_transfers_hash{};
+ hash_m_transfers(transfer_height, new_transfers_hash);
- if (new_transfers_hash != hash)
- {
- // Soft-Reset to avoid inconsistency in case of BC reorg.
- clear_soft(false); // keep_key_images works only with soft reset.
- THROW_WALLET_EXCEPTION_IF(true, error::wallet_internal_error, "Transfers changed during rescan, soft or hard rescan is needed");
- }
+ if (new_transfers_hash == hash) {
+ // Restore key images in m_transfers from m_key_images
+ for(auto it = m_key_images.begin(); it != m_key_images.end(); it++)
+ {
+ THROW_WALLET_EXCEPTION_IF(it->second >= m_transfers.size(),
+ error::wallet_internal_error,
+ "Key images cache contains illegal transfer offset");
+ m_transfers[it->second].m_key_image = it->first;
+ m_transfers[it->second].m_key_image_known = true;
+ }
- // Restore key images in m_transfers from m_key_images
- for(auto it = m_key_images.begin(); it != m_key_images.end(); it++)
- {
- THROW_WALLET_EXCEPTION_IF(it->second >= m_transfers.size(), error::wallet_internal_error, "Key images cache contains illegal transfer offset");
- m_transfers[it->second].m_key_image = it->first;
- m_transfers[it->second].m_key_image_known = true;
+ return;
+ }
}
+
+ // Soft-Reset to avoid inconsistency in case of BC reorg.
+ clear_soft(false); // keep_key_images works only with soft reset.
+ THROW_WALLET_EXCEPTION_IF(true, error::wallet_internal_error, "Transfers changed during rescan, soft or hard rescan is needed");
}
//----------------------------------------------------------------------------------------------------
uint64_t wallet2::get_bytes_sent() const