aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/api/address_book.cpp2
-rw-r--r--src/wallet/api/wallet.cpp5
-rw-r--r--src/wallet/wallet2.cpp40
-rw-r--r--src/wallet/wallet2.h6
-rw-r--r--src/wallet/wallet_rpc_server.cpp54
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h5
-rw-r--r--src/wallet/wallet_rpc_server_error_codes.h6
7 files changed, 79 insertions, 39 deletions
diff --git a/src/wallet/api/address_book.cpp b/src/wallet/api/address_book.cpp
index 8089a6a05..38c34a912 100644
--- a/src/wallet/api/address_book.cpp
+++ b/src/wallet/api/address_book.cpp
@@ -74,7 +74,7 @@ bool AddressBookImpl::addRow(const std::string &dst_addr , const std::string &pa
// integrated + long payment id provided
if(has_long_pid && info.has_payment_id) {
- m_errorString = tr("Integrated address and long payment id can't be used at the same time");
+ m_errorString = tr("Integrated address and long payment ID can't be used at the same time");
m_errorCode = Invalid_Payment_Id;
return false;
}
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 82948081e..5ce8ede8d 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -626,7 +626,7 @@ bool WalletImpl::close(bool store)
if (status() != Status_Critical)
m_wallet->store();
else
- LOG_ERROR("Status_Critical - not storing wallet");
+ LOG_ERROR("Status_Critical - not saving wallet");
LOG_PRINT_L1("wallet::store done");
}
LOG_PRINT_L1("Calling wallet::stop...");
@@ -732,7 +732,7 @@ bool WalletImpl::store(const std::string &path)
m_wallet->store_to(path, m_password);
}
} catch (const std::exception &e) {
- LOG_ERROR("Error storing wallet: " << e.what());
+ LOG_ERROR("Error saving wallet: " << e.what());
m_status = Status_Error;
m_errorString = e.what();
}
@@ -1198,6 +1198,7 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const
for (const std::pair<uint64_t, uint64_t> outs_for_amount : e.scanty_outs()) {
writer << "\n" << tr("output amount") << " = " << print_money(outs_for_amount.first) << ", " << tr("found outputs to use") << " = " << outs_for_amount.second;
}
+ writer << "\n" << tr("Please sweep unmixable outputs.");
m_errorString = writer.str();
m_status = Status_Error;
} catch (const tools::error::tx_not_constructed&) {
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 1ed0d2b57..87577d2fd 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -223,7 +223,7 @@ boost::optional<tools::password_container> get_password(const boost::program_opt
THROW_WALLET_EXCEPTION_IF(!password_prompter, tools::error::wallet_internal_error, tools::wallet2::tr("no password specified; use --prompt-for-password to prompt for a password"));
- return password_prompter(verify ? tr("Enter new wallet password") : tr("Wallet password"), verify);
+ return password_prompter(verify ? tr("Enter a new password for the wallet") : tr("Wallet password"), verify);
}
std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file, const boost::program_options::variables_map& vm, const options& opts, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
@@ -361,6 +361,7 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
wallet.reset(make_basic(vm, opts, password_prompter).release());
wallet->set_refresh_from_block_height(field_scan_from_height);
+ wallet->explicit_refresh_from_block_height(field_scan_from_height_found);
try
{
@@ -532,12 +533,9 @@ size_t estimate_tx_size(bool use_rct, int n_inputs, int mixin, int n_outputs, si
return n_inputs * (mixin+1) * APPROXIMATE_INPUT_BYTES + extra_size;
}
-uint8_t get_bulletproof_fork(bool testnet)
+uint8_t get_bulletproof_fork()
{
- if (testnet)
- return 7;
- else
- return 255; // TODO
+ return 8;
}
crypto::hash8 get_short_payment_id(const tools::wallet2::pending_tx &ptx)
@@ -604,6 +602,7 @@ wallet2::wallet2(bool testnet, bool restricted):
m_refresh_type(RefreshOptimizeCoinbase),
m_auto_refresh(true),
m_refresh_from_block_height(0),
+ m_explicit_refresh_from_block_height(true),
m_confirm_missing_payment_id(true),
m_ask_password(true),
m_min_output_count(0),
@@ -1216,7 +1215,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
td.m_rct = false;
}
set_unspent(m_transfers.size()-1);
- if (!m_multisig)
+ if (!m_multisig && !m_watch_only)
m_key_images[td.m_key_image] = m_transfers.size()-1;
m_pub_keys[tx_scan_info[o].in_ephemeral.pub] = m_transfers.size()-1;
if (m_multisig)
@@ -1310,11 +1309,21 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
uint64_t amount = boost::get<cryptonote::txin_to_key>(in).amount;
if (amount > 0)
{
- THROW_WALLET_EXCEPTION_IF(amount != td.amount(), error::wallet_internal_error,
- std::string("Inconsistent amount in tx input: got ") + print_money(amount) +
- std::string(", expected ") + print_money(td.amount()));
+ if(amount != td.amount())
+ {
+ MERROR("Inconsistent amount in tx input: got " << print_money(amount) <<
+ ", expected " << print_money(td.amount()));
+ // this means:
+ // 1) the same output pub key was used as destination multiple times,
+ // 2) the wallet set the highest amount among them to transfer_details::m_amount, and
+ // 3) the wallet somehow spent that output with an amount smaller than the above amount, causing inconsistency
+ td.m_amount = amount;
+ }
+ }
+ else
+ {
+ amount = td.amount();
}
- amount = td.amount();
tx_money_spent_in_ins += amount;
if (subaddr_account && *subaddr_account != td.m_subaddr_index.major)
LOG_ERROR("spent funds are from different subaddress accounts; count of incoming/outgoing payments will be incorrect");
@@ -6637,7 +6646,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
uint64_t needed_fee, available_for_fee = 0;
uint64_t upper_transaction_size_limit = get_upper_transaction_size_limit();
const bool use_rct = use_fork_rules(4, 0);
- const bool bulletproof = use_fork_rules(get_bulletproof_fork(m_testnet), 0);
+ const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
const uint64_t fee_per_kb = get_per_kb_fee();
const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm());
@@ -7146,7 +7155,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
std::vector<std::vector<get_outs_entry>> outs;
const bool use_rct = fake_outs_count > 0 && use_fork_rules(4, 0);
- const bool bulletproof = use_fork_rules(get_bulletproof_fork(m_testnet), 0);
+ const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
const uint64_t fee_per_kb = get_per_kb_fee();
const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm());
@@ -8349,8 +8358,9 @@ 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
- if (m_testnet && approx_blockchain_height > 105000)
- approx_blockchain_height -= 105000;
+ static const uint64_t approximate_testnet_rolled_back_blocks = 148540;
+ if (m_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);
return approx_blockchain_height;
}
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 71302be09..28289842b 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -561,6 +561,9 @@ namespace tools
void set_refresh_from_block_height(uint64_t height) {m_refresh_from_block_height = height;}
uint64_t get_refresh_from_block_height() const {return m_refresh_from_block_height;}
+ void explicit_refresh_from_block_height(bool expl) {m_explicit_refresh_from_block_height = expl;}
+ bool explicit_refresh_from_block_height() const {return m_explicit_refresh_from_block_height;}
+
// upper_transaction_size_limit as defined below is set to
// approximately 125% of the fixed minimum allowable penalty
// free block size. TODO: fix this so that it actually takes
@@ -1118,6 +1121,9 @@ namespace tools
RefreshType m_refresh_type;
bool m_auto_refresh;
uint64_t m_refresh_from_block_height;
+ // If m_refresh_from_block_height is explicitly set to zero we need this to differentiate it from the case that
+ // m_refresh_from_block_height was defaulted to zero.*/
+ bool m_explicit_refresh_from_block_height;
bool m_confirm_missing_payment_id;
bool m_ask_password;
uint32_t m_min_output_count;
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 97faf0b56..6d5419521 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -39,6 +39,7 @@ using namespace epee;
#include "wallet/wallet_args.h"
#include "common/command_line.h"
#include "common/i18n.h"
+#include "cryptonote_config.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_basic/account.h"
#include "multisig/multisig.h"
@@ -1803,11 +1804,11 @@ namespace tools
return false;
}
- uint64_t min_height = 0, max_height = (uint64_t)-1;
+ uint64_t min_height = 0, max_height = CRYPTONOTE_MAX_BLOCK_NUMBER;
if (req.filter_by_height)
{
min_height = req.min_height;
- max_height = req.max_height;
+ max_height = req.max_height <= max_height ? req.max_height : max_height;
}
if (req.in)
@@ -1889,8 +1890,15 @@ namespace tools
return false;
}
+ if (req.account_index >= m_wallet->get_num_subaddress_accounts())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_ACCOUNT_INDEX_OUT_OF_BOUNDS;
+ er.message = "Account index is out of bound";
+ return false;
+ }
+
std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> payments;
- m_wallet->get_payments(payments, 0);
+ m_wallet->get_payments(payments, 0, (uint64_t)-1, req.account_index);
for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) {
if (i->second.m_tx_hash == txid)
{
@@ -1900,7 +1908,7 @@ namespace tools
}
std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> payments_out;
- m_wallet->get_payments_out(payments_out, 0);
+ m_wallet->get_payments_out(payments_out, 0, (uint64_t)-1, req.account_index);
for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::const_iterator i = payments_out.begin(); i != payments_out.end(); ++i) {
if (i->first == txid)
{
@@ -1910,7 +1918,7 @@ namespace tools
}
std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>> upayments;
- m_wallet->get_unconfirmed_payments_out(upayments);
+ m_wallet->get_unconfirmed_payments_out(upayments, req.account_index);
for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) {
if (i->first == txid)
{
@@ -1922,7 +1930,7 @@ namespace tools
m_wallet->update_pool_state();
std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>> pool_payments;
- m_wallet->get_unconfirmed_payments(pool_payments);
+ m_wallet->get_unconfirmed_payments(pool_payments, req.account_index);
for (std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>>::const_iterator i = pool_payments.begin(); i != pool_payments.end(); ++i) {
if (i->second.m_pd.m_tx_hash == txid)
{
@@ -2397,6 +2405,11 @@ namespace tools
{
std::rethrow_exception(e);
}
+ catch (const tools::error::no_connection_to_daemon& e)
+ {
+ er.code = WALLET_RPC_ERROR_CODE_NO_DAEMON_CONNECTION;
+ er.message = e.what();
+ }
catch (const tools::error::daemon_busy& e)
{
er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY;
@@ -2412,6 +2425,11 @@ namespace tools
er.code = WALLET_RPC_ERROR_CODE_NOT_ENOUGH_MONEY;
er.message = e.what();
}
+ catch (const tools::error::not_enough_unlocked_money& e)
+ {
+ er.code = WALLET_RPC_ERROR_CODE_NOT_ENOUGH_UNLOCKED_MONEY;
+ er.message = e.what();
+ }
catch (const tools::error::tx_not_possible& e)
{
er.code = WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE;
@@ -2425,7 +2443,7 @@ namespace tools
catch (const tools::error::not_enough_outs_to_mix& e)
{
er.code = WALLET_RPC_ERROR_CODE_NOT_ENOUGH_OUTS_TO_MIX;
- er.message = e.what();
+ er.message = e.what() + std::string(" Please use sweep_dust.");
}
catch (const error::file_exists& e)
{
@@ -2439,12 +2457,12 @@ namespace tools
}
catch (const error::account_index_outofbound& e)
{
- er.code = WALLET_RPC_ERROR_CODE_ACCOUNT_INDEX_OUTOFBOUND;
+ er.code = WALLET_RPC_ERROR_CODE_ACCOUNT_INDEX_OUT_OF_BOUNDS;
er.message = e.what();
}
catch (const error::address_index_outofbound& e)
{
- er.code = WALLET_RPC_ERROR_CODE_ADDRESS_INDEX_OUTOFBOUND;
+ er.code = WALLET_RPC_ERROR_CODE_ADDRESS_INDEX_OUT_OF_BOUNDS;
er.message = e.what();
}
catch (const std::exception& e)
@@ -2922,12 +2940,12 @@ int main(int argc, char** argv) {
// if we ^C during potentially length load/refresh, there's no server loop yet
if (quit)
{
- MINFO(tools::wallet_rpc_server::tr("Storing wallet..."));
+ MINFO(tools::wallet_rpc_server::tr("Saving wallet..."));
wal->store();
- MINFO(tools::wallet_rpc_server::tr("Stored ok"));
+ MINFO(tools::wallet_rpc_server::tr("Successfully saved"));
return 1;
}
- MINFO(tools::wallet_rpc_server::tr("Loaded ok"));
+ MINFO(tools::wallet_rpc_server::tr("Successfully loaded"));
}
catch (const std::exception& e)
{
@@ -2938,11 +2956,11 @@ just_dir:
tools::wallet_rpc_server wrpc;
if (wal) wrpc.set_wallet(wal.release());
bool r = wrpc.init(&(vm.get()));
- CHECK_AND_ASSERT_MES(r, 1, tools::wallet_rpc_server::tr("Failed to initialize wallet rpc server"));
+ CHECK_AND_ASSERT_MES(r, 1, tools::wallet_rpc_server::tr("Failed to initialize wallet RPC server"));
tools::signal_handler::install([&wrpc](int) {
wrpc.send_stop_signal();
});
- LOG_PRINT_L0(tools::wallet_rpc_server::tr("Starting wallet rpc server"));
+ LOG_PRINT_L0(tools::wallet_rpc_server::tr("Starting wallet RPC server"));
try
{
wrpc.run();
@@ -2952,16 +2970,16 @@ just_dir:
LOG_ERROR(tools::wallet_rpc_server::tr("Failed to run wallet: ") << e.what());
return 1;
}
- LOG_PRINT_L0(tools::wallet_rpc_server::tr("Stopped wallet rpc server"));
+ LOG_PRINT_L0(tools::wallet_rpc_server::tr("Stopped wallet RPC server"));
try
{
- LOG_PRINT_L0(tools::wallet_rpc_server::tr("Storing wallet..."));
+ LOG_PRINT_L0(tools::wallet_rpc_server::tr("Saving wallet..."));
wrpc.stop();
- LOG_PRINT_L0(tools::wallet_rpc_server::tr("Stored ok"));
+ LOG_PRINT_L0(tools::wallet_rpc_server::tr("Successfully saved"));
}
catch (const std::exception& e)
{
- LOG_ERROR(tools::wallet_rpc_server::tr("Failed to store wallet: ") << e.what());
+ LOG_ERROR(tools::wallet_rpc_server::tr("Failed to save wallet: ") << e.what());
return 1;
}
return 0;
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index e9f112b63..e38cba5a5 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -29,6 +29,7 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
+#include "cryptonote_config.h"
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/subaddress_index.h"
@@ -1262,7 +1263,7 @@ namespace wallet_rpc
KV_SERIALIZE(pool);
KV_SERIALIZE(filter_by_height);
KV_SERIALIZE(min_height);
- KV_SERIALIZE(max_height);
+ KV_SERIALIZE_OPT(max_height, (uint64_t)CRYPTONOTE_MAX_BLOCK_NUMBER);
KV_SERIALIZE(account_index);
KV_SERIALIZE(subaddr_indices);
END_KV_SERIALIZE_MAP()
@@ -1291,9 +1292,11 @@ namespace wallet_rpc
struct request
{
std::string txid;
+ uint32_t account_index;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(txid);
+ KV_SERIALIZE_OPT(account_index, (uint32_t)0)
END_KV_SERIALIZE_MAP()
};
diff --git a/src/wallet/wallet_rpc_server_error_codes.h b/src/wallet/wallet_rpc_server_error_codes.h
index 311556657..d47467940 100644
--- a/src/wallet/wallet_rpc_server_error_codes.h
+++ b/src/wallet/wallet_rpc_server_error_codes.h
@@ -44,8 +44,8 @@
#define WALLET_RPC_ERROR_CODE_WRONG_URI -11
#define WALLET_RPC_ERROR_CODE_WRONG_INDEX -12
#define WALLET_RPC_ERROR_CODE_NOT_OPEN -13
-#define WALLET_RPC_ERROR_CODE_ACCOUNT_INDEX_OUTOFBOUND -14
-#define WALLET_RPC_ERROR_CODE_ADDRESS_INDEX_OUTOFBOUND -15
+#define WALLET_RPC_ERROR_CODE_ACCOUNT_INDEX_OUT_OF_BOUNDS -14
+#define WALLET_RPC_ERROR_CODE_ADDRESS_INDEX_OUT_OF_BOUNDS -15
#define WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE -16
#define WALLET_RPC_ERROR_CODE_NOT_ENOUGH_MONEY -17
#define WALLET_RPC_ERROR_CODE_TX_TOO_LARGE -18
@@ -67,3 +67,5 @@
#define WALLET_RPC_ERROR_CODE_BAD_MULTISIG_TX_DATA -34
#define WALLET_RPC_ERROR_CODE_MULTISIG_SIGNATURE -35
#define WALLET_RPC_ERROR_CODE_MULTISIG_SUBMISSION -36
+#define WALLET_RPC_ERROR_CODE_NOT_ENOUGH_UNLOCKED_MONEY -37
+#define WALLET_RPC_ERROR_CODE_NO_DAEMON_CONNECTION -38