aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt24
-rw-r--r--src/crypto/CMakeLists.txt2
-rw-r--r--src/cryptonote_basic/miner.cpp10
-rw-r--r--src/daemon/command_parser_executor.cpp15
-rw-r--r--src/daemon/command_parser_executor.h2
-rw-r--r--src/daemon/command_server.cpp5
-rw-r--r--src/daemon/rpc_command_executor.cpp28
-rw-r--r--src/daemon/rpc_command_executor.h2
-rw-r--r--src/rpc/core_rpc_server.cpp46
-rw-r--r--src/rpc/core_rpc_server.h2
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h23
-rw-r--r--src/simplewallet/simplewallet.cpp238
-rw-r--r--src/wallet/CMakeLists.txt7
-rw-r--r--src/wallet/api/unsigned_transaction.cpp14
-rw-r--r--src/wallet/wallet2.cpp24
15 files changed, 227 insertions, 215 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7cf03db71..d83242a3c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -101,18 +101,24 @@ add_subdirectory(crypto)
add_subdirectory(ringct)
add_subdirectory(cryptonote_basic)
add_subdirectory(cryptonote_core)
-add_subdirectory(blockchain_db)
+if(NOT IOS)
+ add_subdirectory(blockchain_db)
+endif()
add_subdirectory(mnemonics)
-add_subdirectory(rpc)
+if(NOT IOS)
+ add_subdirectory(rpc)
+endif()
add_subdirectory(wallet)
-add_subdirectory(p2p)
+if(NOT IOS)
+ add_subdirectory(p2p)
+endif()
add_subdirectory(cryptonote_protocol)
-
-add_subdirectory(simplewallet)
-add_subdirectory(daemonizer)
-add_subdirectory(daemon)
-
-add_subdirectory(blockchain_utilities)
+if(NOT IOS)
+ add_subdirectory(simplewallet)
+ add_subdirectory(daemonizer)
+ add_subdirectory(daemon)
+ add_subdirectory(blockchain_utilities)
+endif()
if(PER_BLOCK_CHECKPOINT)
add_subdirectory(blocks)
diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt
index c047b0042..277ee64c2 100644
--- a/src/crypto/CMakeLists.txt
+++ b/src/crypto/CMakeLists.txt
@@ -93,7 +93,7 @@ endif()
# Because of the way Qt works on android with JNI, the code does not live in the main android thread
# So this code runs with a 1 MB default stack size.
# This will force the use of the heap for the allocation of the scratchpad
-if (ANDROID)
+if (ANDROID OR IOS)
if( BUILD_GUI_DEPS )
add_definitions(-DFORCE_USE_HEAP=1)
endif()
diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
index 4c84e7eee..9f2da8a94 100644
--- a/src/cryptonote_basic/miner.cpp
+++ b/src/cryptonote_basic/miner.cpp
@@ -377,6 +377,7 @@ namespace cryptonote
void miner::pause()
{
CRITICAL_REGION_LOCAL(m_miners_count_lock);
+ MDEBUG("miner::pause: " << m_pausers_count << " -> " << (m_pausers_count + 1));
++m_pausers_count;
if(m_pausers_count == 1 && is_mining())
MDEBUG("MINING PAUSED");
@@ -385,6 +386,7 @@ namespace cryptonote
void miner::resume()
{
CRITICAL_REGION_LOCAL(m_miners_count_lock);
+ MDEBUG("miner::resume: " << m_pausers_count << " -> " << (m_pausers_count - 1));
--m_pausers_count;
if(m_pausers_count < 0)
{
@@ -812,9 +814,11 @@ namespace cryptonote
const std::string POWER_SUPPLY_STATUS_PATHS[] =
{
"/sys/class/power_supply/ACAD/online",
- "/sys/class/power_supply/AC/online"
+ "/sys/class/power_supply/AC/online",
+ "/sys/class/power_supply/AC0/online",
+ "/sys/class/power_supply/ADP0/online"
};
-
+
for(const std::string& path : POWER_SUPPLY_STATUS_PATHS)
{
if( epee::file_io_utils::is_file_exist(path) )
@@ -823,7 +827,7 @@ namespace cryptonote
break;
}
}
-
+
if( power_supply_path.empty() )
{
LOG_ERROR("Couldn't find battery/power status file, can't determine if plugged in!");
diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp
index 4e6e83eb5..a7caeeffc 100644
--- a/src/daemon/command_parser_executor.cpp
+++ b/src/daemon/command_parser_executor.cpp
@@ -563,4 +563,19 @@ bool t_command_parser_executor::update(const std::vector<std::string>& args)
return m_executor.update(args.front());
}
+bool t_command_parser_executor::relay_tx(const std::vector<std::string>& args)
+{
+ if (args.size() != 1) return false;
+
+ std::string txid;
+ crypto::hash hash;
+ if (!parse_hash256(args[0], hash))
+ {
+ std::cout << "failed to parse tx id" << std::endl;
+ return true;
+ }
+ txid = args[0];
+ return m_executor.relay_tx(txid);
+}
+
} // namespace daemonize
diff --git a/src/daemon/command_parser_executor.h b/src/daemon/command_parser_executor.h
index 0a5ca8dd9..a453553f1 100644
--- a/src/daemon/command_parser_executor.h
+++ b/src/daemon/command_parser_executor.h
@@ -132,6 +132,8 @@ public:
bool print_blockchain_dynamic_stats(const std::vector<std::string>& args);
bool update(const std::vector<std::string>& args);
+
+ bool relay_tx(const std::vector<std::string>& args);
};
} // namespace daemonize
diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp
index 0081e00dc..21f550a85 100644
--- a/src/daemon/command_server.cpp
+++ b/src/daemon/command_server.cpp
@@ -248,6 +248,11 @@ t_command_server::t_command_server(
, std::bind(&t_command_parser_executor::update, &m_parser, p::_1)
, "subcommands: check (check if an update is available), download (download it is there is), update (not implemented)"
);
+ m_command_lookup.set_handler(
+ "relay_tx"
+ , std::bind(&t_command_parser_executor::relay_tx, &m_parser, p::_1)
+ , "Relay a given transaction by its txid"
+ );
}
bool t_command_server::process_command_str(const std::string& cmd)
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index c5b17268d..249007436 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -1646,4 +1646,32 @@ bool t_rpc_command_executor::update(const std::string &command)
return true;
}
+bool t_rpc_command_executor::relay_tx(const std::string &txid)
+{
+ cryptonote::COMMAND_RPC_RELAY_TX::request req;
+ cryptonote::COMMAND_RPC_RELAY_TX::response res;
+ std::string fail_message = "Unsuccessful";
+ epee::json_rpc::error error_resp;
+
+ req.txids.push_back(txid);
+
+ if (m_is_rpc)
+ {
+ if (!m_rpc_client->json_rpc_request(req, res, "relay_tx", fail_message.c_str()))
+ {
+ return true;
+ }
+ }
+ else
+ {
+ if (!m_rpc_server->on_relay_tx(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
+ {
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
+ return true;
+ }
+ }
+
+ return true;
+}
+
}// namespace daemonize
diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h
index a015c83ea..3f551bd14 100644
--- a/src/daemon/rpc_command_executor.h
+++ b/src/daemon/rpc_command_executor.h
@@ -153,6 +153,8 @@ public:
bool print_blockchain_dynamic_stats(uint64_t nblocks);
bool update(const std::string &command);
+
+ bool relay_tx(const std::string &txid);
};
} // namespace daemonize
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index a800dbb35..7cce0bf04 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -1588,6 +1588,52 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
+ bool core_rpc_server::on_relay_tx(const COMMAND_RPC_RELAY_TX::request& req, COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& error_resp)
+ {
+ if(!check_core_busy())
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
+ error_resp.message = "Core is busy.";
+ return false;
+ }
+
+ bool failed = false;
+ for (const auto &str: req.txids)
+ {
+ cryptonote::blobdata txid_data;
+ if(!epee::string_tools::parse_hexstr_to_binbuff(str, txid_data))
+ {
+ res.status = std::string("Invalid transaction id: ") + str;
+ failed = true;
+ }
+ crypto::hash txid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
+
+ cryptonote::transaction tx;
+ bool r = m_core.get_pool_transaction(txid, tx);
+ if (r)
+ {
+ cryptonote_connection_context fake_context = AUTO_VAL_INIT(fake_context);
+ NOTIFY_NEW_TRANSACTIONS::request r;
+ r.txs.push_back(cryptonote::tx_to_blob(tx));
+ m_core.get_protocol()->relay_transactions(r, fake_context);
+ //TODO: make sure that tx has reached other nodes here, probably wait to receive reflections from other nodes
+ }
+ else
+ {
+ res.status = std::string("Transaction not found in pool: ") + str;
+ failed = true;
+ }
+ }
+
+ if (failed)
+ {
+ return false;
+ }
+
+ res.status = CORE_RPC_STATUS_OK;
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
const command_line::arg_descriptor<std::string> core_rpc_server::arg_rpc_bind_port = {
"rpc-bind-port"
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index f8eff5f8c..0aa222c87 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -121,6 +121,7 @@ namespace cryptonote
MAP_JON_RPC_WE("get_coinbase_tx_sum", on_get_coinbase_tx_sum, COMMAND_RPC_GET_COINBASE_TX_SUM)
MAP_JON_RPC_WE("get_fee_estimate", on_get_per_kb_fee_estimate, COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE)
MAP_JON_RPC_WE_IF("get_alternate_chains",on_get_alternate_chains, COMMAND_RPC_GET_ALTERNATE_CHAINS, !m_restricted)
+ MAP_JON_RPC_WE_IF("relay_tx", on_relay_tx, COMMAND_RPC_RELAY_TX, !m_restricted)
END_JSON_RPC_MAP()
END_URI_MAP2()
@@ -174,6 +175,7 @@ namespace cryptonote
bool on_get_coinbase_tx_sum(const COMMAND_RPC_GET_COINBASE_TX_SUM::request& req, COMMAND_RPC_GET_COINBASE_TX_SUM::response& res, epee::json_rpc::error& error_resp);
bool on_get_per_kb_fee_estimate(const COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::request& req, COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::response& res, epee::json_rpc::error& error_resp);
bool on_get_alternate_chains(const COMMAND_RPC_GET_ALTERNATE_CHAINS::request& req, COMMAND_RPC_GET_ALTERNATE_CHAINS::response& res, epee::json_rpc::error& error_resp);
+ bool on_relay_tx(const COMMAND_RPC_RELAY_TX::request& req, COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& error_resp);
//-----------------------
private:
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 6f60093ac..3991fc27b 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -49,7 +49,7 @@ namespace cryptonote
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define CORE_RPC_VERSION_MAJOR 1
-#define CORE_RPC_VERSION_MINOR 8
+#define CORE_RPC_VERSION_MINOR 9
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
@@ -1495,4 +1495,25 @@ namespace cryptonote
END_KV_SERIALIZE_MAP()
};
};
+
+ struct COMMAND_RPC_RELAY_TX
+ {
+ struct request
+ {
+ std::list<std::string> txids;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(txids)
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct response
+ {
+ std::string status;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(status)
+ END_KV_SERIALIZE_MAP()
+ };
+ };
}
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index f5a469af4..e925e81b5 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -101,6 +101,7 @@ enum TransferType {
namespace
{
+ const auto allowed_priority_strings = {"default", "unimportant", "normal", "elevated", "priority"};
const auto arg_wallet_file = wallet_args::arg_wallet_file();
const command_line::arg_descriptor<std::string> arg_generate_new_wallet = {"generate-new-wallet", sw::tr("Generate new wallet and save it to <arg>"), ""};
const command_line::arg_descriptor<std::string> arg_generate_from_view_key = {"generate-from-view-key", sw::tr("Generate incoming-only wallet from view key"), ""};
@@ -559,12 +560,6 @@ bool simple_wallet::set_refresh_type(const std::vector<std::string> &args/* = st
bool simple_wallet::set_confirm_missing_payment_id(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
- if (m_wallet->watch_only())
- {
- fail_msg_writer() << tr("wallet is watch-only and cannot transfer");
- return true;
- }
-
const auto pwd_container = get_and_verify_password();
if (pwd_container)
{
@@ -685,7 +680,7 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("payments", boost::bind(&simple_wallet::show_payments, this, _1), tr("payments <PID_1> [<PID_2> ... <PID_N>] - Show payments for given payment ID[s]"));
m_cmd_binder.set_handler("bc_height", boost::bind(&simple_wallet::show_blockchain_height, this, _1), tr("Show blockchain height"));
m_cmd_binder.set_handler("transfer_original", boost::bind(&simple_wallet::transfer, this, _1), tr("Same as transfer, but using an older transaction building algorithm"));
- m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer_new, this, _1), tr("transfer [<mixin_count>] <address> <amount> [<payment_id>] - Transfer <amount> to <address>. <mixin_count> is the number of extra inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included)"));
+ m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer_new, this, _1), tr("transfer [<priority>] [<mixin_count>] <address> <amount> [<payment_id>] - Transfer <amount> to <address>. <priority> is the priority of the transaction. The higher the priority, the higher the fee of the transaction. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command \"set priority\") is used. <mixin_count> is the number of extra inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included)"));
m_cmd_binder.set_handler("locked_transfer", boost::bind(&simple_wallet::locked_transfer, this, _1), tr("locked_transfer [<mixin_count>] <addr> <amount> <lockblocks>(Number of blocks to lock the transaction for, max 1000000) [<payment_id>]"));
m_cmd_binder.set_handler("sweep_unmixable", boost::bind(&simple_wallet::sweep_unmixable, this, _1), tr("Send all unmixable outputs to yourself with mixin 0"));
m_cmd_binder.set_handler("sweep_all", boost::bind(&simple_wallet::sweep_all, this, _1), tr("sweep_all [mixin] address [payment_id] - Send all unlocked balance to an address"));
@@ -744,6 +739,21 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
}
else
{
+
+#define CHECK_SIMPLE_VARIABLE(name, f, help) do \
+ if (args[0] == name) { \
+ if (args.size() <= 1) \
+ { \
+ fail_msg_writer() << "set " << #name << ": " << tr("needs an argument") << " (" << help << ")"; \
+ return true; \
+ } \
+ else \
+ { \
+ f(args); \
+ return true; \
+ } \
+ } while(0)
+
if (args[0] == "seed")
{
if (args.size() == 1)
@@ -757,176 +767,19 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
return true;
}
}
- else if (args[0] == "always-confirm-transfers")
- {
- if (args.size() <= 1)
- {
- fail_msg_writer() << tr("set always-confirm-transfers: needs an argument (0 or 1)");
- return true;
- }
- else
- {
- set_always_confirm_transfers(args);
- return true;
- }
- }
- else if (args[0] == "print-ring-members")
- {
- if (args.size() <= 1)
- {
- fail_msg_writer() << tr("set print-ring-members: needs an argument (0 or 1)");
- return true;
- }
- else
- {
- set_print_ring_members(args);
- return true;
- }
- }
- else if (args[0] == "store-tx-info")
- {
- if (args.size() <= 1)
- {
- fail_msg_writer() << tr("set store-tx-info: needs an argument (0 or 1)");
- return true;
- }
- else
- {
- set_store_tx_info(args);
- return true;
- }
- }
- else if (args[0] == "default-mixin")
- {
- if (args.size() <= 1)
- {
- fail_msg_writer() << tr("set default-mixin: needs an argument (integer >= 2)");
- return true;
- }
- else
- {
- set_default_mixin(args);
- return true;
- }
- }
- else if (args[0] == "auto-refresh")
- {
- if (args.size() <= 1)
- {
- fail_msg_writer() << tr("set auto-refresh: needs an argument (0 or 1)");
- return true;
- }
- else
- {
- set_auto_refresh(args);
- return true;
- }
- }
- else if (args[0] == "refresh-type")
- {
- if (args.size() <= 1)
- {
- fail_msg_writer() << tr("set refresh-type: needs an argument:") <<
- tr("full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase)");
- return true;
- }
- else
- {
- set_refresh_type(args);
- return true;
- }
- }
- else if (args[0] == "priority")
- {
- if (args.size() <= 1)
- {
- fail_msg_writer() << tr("set priority: needs an argument: 0, 1, 2, 3, or 4");
- return true;
- }
- else
- {
- set_default_priority(args);
- return true;
- }
- }
- else if (args[0] == "confirm-missing-payment-id")
- {
- if (args.size() <= 1)
- {
- fail_msg_writer() << tr("set confirm-missing-payment-id: needs an argument (0 or 1)");
- return true;
- }
- else
- {
- set_confirm_missing_payment_id(args);
- return true;
- }
- }
- else if (args[0] == "ask-password")
- {
- if (args.size() <= 1)
- {
- fail_msg_writer() << tr("set ask-password: needs an argument (0 or 1)");
- return true;
- }
- else
- {
- set_ask_password(args);
- return true;
- }
- }
- else if (args[0] == "unit")
- {
- if (args.size() <= 1)
- {
- fail_msg_writer() << tr("set unit: needs an argument (monero, millinero, micronero, nanop, piconero)");
- return true;
- }
- else
- {
- set_unit(args);
- return true;
- }
- }
- else if (args[0] == "min-outputs-count")
- {
- if (args.size() <= 1)
- {
- fail_msg_writer() << tr("set min-outputs-count: needs an argument (unsigned integer)");
- return true;
- }
- else
- {
- set_min_output_count(args);
- return true;
- }
- }
- else if (args[0] == "min-outputs-value")
- {
- if (args.size() <= 1)
- {
- fail_msg_writer() << tr("set min-outputs-value: needs an argument (unsigned integer)");
- return true;
- }
- else
- {
- set_min_output_value(args);
- return true;
- }
- }
- else if (args[0] == "merge-destinations")
- {
- if (args.size() <= 1)
- {
- fail_msg_writer() << tr("set merge-destinations: needs an argument (0 or 1)");
- return true;
- }
- else
- {
- set_merge_destinations(args);
- return true;
- }
- }
+ CHECK_SIMPLE_VARIABLE("always-confirm-transfers", set_always_confirm_transfers, tr("0 or 1"));
+ CHECK_SIMPLE_VARIABLE("print-ring-members", set_print_ring_members, tr("0 or 1"));
+ CHECK_SIMPLE_VARIABLE("store-tx-info", set_store_tx_info, tr("0 or 1"));
+ CHECK_SIMPLE_VARIABLE("default-mixin", set_default_mixin, tr("integer >= 2"));
+ CHECK_SIMPLE_VARIABLE("auto-refresh", set_auto_refresh, tr("0 or 1"));
+ CHECK_SIMPLE_VARIABLE("refresh-type", set_refresh_type, tr("full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase)"));
+ CHECK_SIMPLE_VARIABLE("priority", set_default_priority, tr("0, 1, 2, 3, or 4"));
+ CHECK_SIMPLE_VARIABLE("confirm-missing-payment-id", set_confirm_missing_payment_id, tr("0 or 1"));
+ CHECK_SIMPLE_VARIABLE("ask-password", set_ask_password, tr("0 or 1"));
+ CHECK_SIMPLE_VARIABLE("unit", set_unit, tr("monero, millinero, micronero, nanop, piconero"));
+ CHECK_SIMPLE_VARIABLE("min-outputs-count", set_min_output_count, tr("unsigned integer"));
+ CHECK_SIMPLE_VARIABLE("min-outputs-value", set_min_output_value, tr("amount"));
+ CHECK_SIMPLE_VARIABLE("merge-destinations", set_merge_destinations, tr("0 or 1"));
}
fail_msg_writer() << tr("set: unrecognized argument(s)");
return true;
@@ -2205,6 +2058,18 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
std::vector<std::string> local_args = args_;
+ int priority = 0;
+ if(local_args.size() > 0) {
+ auto priority_pos = std::find(
+ allowed_priority_strings.begin(),
+ allowed_priority_strings.end(),
+ local_args[0]);
+ if(priority_pos != allowed_priority_strings.end()) {
+ local_args.erase(local_args.begin());
+ priority = std::distance(allowed_priority_strings.begin(), priority_pos);
+ }
+ }
+
size_t fake_outs_count;
if(local_args.size() > 0) {
if(!epee::string_tools::get_xtype_from_string(fake_outs_count, local_args[0]))
@@ -2356,15 +2221,15 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
return true;
}
unlock_block = bc_height + locked_blocks;
- ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, unlock_block /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon);
+ ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_trusted_daemon);
break;
case TransferNew:
- ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon);
+ ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_trusted_daemon);
break;
default:
LOG_ERROR("Unknown transfer method, using original");
case TransferOriginal:
- ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon);
+ ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_trusted_daemon);
break;
}
@@ -2993,7 +2858,6 @@ bool simple_wallet::sweep_all(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::donate(const std::vector<std::string> &args_)
{
- if (m_wallet->ask_password() && !get_and_verify_password()) { return true; }
std::vector<std::string> local_args = args_;
if(local_args.empty() || local_args.size() > 3)
{
@@ -3041,6 +2905,7 @@ bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes,
size_t min_mixin = ~0;
std::unordered_map<std::string, uint64_t> dests;
const std::string wallet_address = m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ int first_known_non_zero_change_index = -1;
for (size_t n = 0; n < get_num_txes(); ++n)
{
const tools::wallet2::tx_construction_data &cd = get_tx(n);
@@ -3075,10 +2940,15 @@ bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes,
fail_msg_writer() << tr("Claimed change is larger than payment to the change address");
return false;
}
- if (memcmp(&cd.change_dts.addr, &get_tx(0).change_dts.addr, sizeof(cd.change_dts.addr)))
+ if (cd.change_dts.amount > 0)
{
- fail_msg_writer() << tr("Change does to more than one address");
- return false;
+ if (first_known_non_zero_change_index == -1)
+ first_known_non_zero_change_index = n;
+ if (memcmp(&cd.change_dts.addr, &get_tx(first_known_non_zero_change_index).change_dts.addr, sizeof(cd.change_dts.addr)))
+ {
+ fail_msg_writer() << tr("Change goes to more than one address");
+ return false;
+ }
}
change += cd.change_dts.amount;
it->second -= cd.change_dts.amount;
diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt
index aed021b9c..2e7610b64 100644
--- a/src/wallet/CMakeLists.txt
+++ b/src/wallet/CMakeLists.txt
@@ -132,8 +132,13 @@ if (BUILD_GUI_DEPS)
list(APPEND objlibs $<TARGET_OBJECTS:obj_${lib}>) # matches naming convention in src/CMakeLists.txt
endforeach()
add_library(wallet_merged STATIC ${objlibs})
+ if(IOS)
+ set(lib_folder lib-${ARCH})
+ else()
+ set(lib_folder lib)
+ endif()
install(TARGETS wallet_merged
- ARCHIVE DESTINATION lib)
+ ARCHIVE DESTINATION ${lib_folder})
install(FILES ${wallet_api_headers}
DESTINATION include/wallet)
diff --git a/src/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp
index b412084b0..1d9ef5d7c 100644
--- a/src/wallet/api/unsigned_transaction.cpp
+++ b/src/wallet/api/unsigned_transaction.cpp
@@ -104,6 +104,7 @@ bool UnsignedTransactionImpl::checkLoadedTx(const std::function<size_t()> get_nu
size_t min_mixin = ~0;
std::unordered_map<std::string, uint64_t> dests;
const std::string wallet_address = m_wallet.m_wallet->get_account().get_public_address_str(m_wallet.m_wallet->testnet());
+ int first_known_non_zero_change_index = -1;
for (size_t n = 0; n < get_num_txes(); ++n)
{
const tools::wallet2::tx_construction_data &cd = get_tx(n);
@@ -140,11 +141,16 @@ bool UnsignedTransactionImpl::checkLoadedTx(const std::function<size_t()> get_nu
m_errorString = tr("Claimed change is larger than payment to the change address");
return false;
}
- if (memcmp(&cd.change_dts.addr, &get_tx(0).change_dts.addr, sizeof(cd.change_dts.addr)))
+ if (cd.change_dts.amount > 0)
{
- m_status = Status_Error;
- m_errorString = tr("Change does to more than one address");
- return false;
+ if (first_known_non_zero_change_index == -1)
+ first_known_non_zero_change_index = n;
+ if (memcmp(&cd.change_dts.addr, &get_tx(first_known_non_zero_change_index).change_dts.addr, sizeof(cd.change_dts.addr)))
+ {
+ m_status = Status_Error;
+ m_errorString = tr("Change goes to more than one address");
+ return false;
+ }
}
change += cd.change_dts.amount;
it->second -= cd.change_dts.amount;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index ed31f34a4..941ee8afb 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -4102,6 +4102,14 @@ static size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs)
return size;
}
+static size_t estimate_tx_size(bool use_rct, int n_inputs, int mixin, int n_outputs)
+{
+ if (use_rct)
+ return estimate_rct_tx_size(n_inputs, mixin, n_outputs + 1);
+ else
+ return n_inputs * (mixin+1) * APPROXIMATE_INPUT_BYTES;
+}
+
std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money) const
{
std::vector<size_t> picks;
@@ -4409,7 +4417,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
}
else
{
- while (!dsts.empty() && dsts[0].amount <= available_amount)
+ while (!dsts.empty() && dsts[0].amount <= available_amount && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()) < TX_SIZE_TARGET(upper_transaction_size_limit))
{
// we can fully pay that destination
LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_testnet, dsts[0].addr) <<
@@ -4420,7 +4428,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
pop_index(dsts, 0);
}
- if (available_amount > 0 && !dsts.empty()) {
+ if (available_amount > 0 && !dsts.empty() && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()) < TX_SIZE_TARGET(upper_transaction_size_limit)) {
// we can partially fill that destination
LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_testnet, dsts[0].addr) <<
" for " << print_money(available_amount) << "/" << print_money(dsts[0].amount));
@@ -4441,11 +4449,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
}
else
{
- size_t estimated_rct_tx_size;
- if (use_rct)
- estimated_rct_tx_size = estimate_rct_tx_size(tx.selected_transfers.size(), fake_outs_count, tx.dsts.size() + 1);
- else
- estimated_rct_tx_size = tx.selected_transfers.size() * (fake_outs_count+1) * APPROXIMATE_INPUT_BYTES;
+ const size_t estimated_rct_tx_size = estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size());
try_tx = dsts.empty() || (estimated_rct_tx_size >= TX_SIZE_TARGET(upper_transaction_size_limit));
}
@@ -4633,11 +4637,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
// here, check if we need to sent tx and start a new one
LOG_PRINT_L2("Considering whether to create a tx now, " << tx.selected_transfers.size() << " inputs, tx limit "
<< upper_transaction_size_limit);
- size_t estimated_rct_tx_size;
- if (use_rct)
- estimated_rct_tx_size = estimate_rct_tx_size(tx.selected_transfers.size(), fake_outs_count, tx.dsts.size() + 1);
- else
- estimated_rct_tx_size = tx.selected_transfers.size() * (fake_outs_count+1) * APPROXIMATE_INPUT_BYTES;
+ const size_t estimated_rct_tx_size = estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size() + 1);
bool try_tx = (unused_dust_indices.empty() && unused_transfers_indices.empty()) || ( estimated_rct_tx_size >= TX_SIZE_TARGET(upper_transaction_size_limit));
if (try_tx) {