wallet: make change output address index configurable

This commit is contained in:
WHR 2025-12-23 11:22:50 +08:00
parent 48ad374b0d
commit d288edb696
4 changed files with 37 additions and 4 deletions

View file

@ -3051,6 +3051,22 @@ bool simple_wallet::set_enable_multisig(const std::vector<std::string> &args/* =
return true;
}
bool simple_wallet::set_change_output_index(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
const auto pwd_container = get_and_verify_password();
if (pwd_container)
{
uint32_t index;
if (!epee::string_tools::get_xtype_from_string(index, args[1]))
{
fail_msg_writer() << tr("Invalid index");
return true;
}
m_wallet->set_change_output_address_index(index);
m_wallet->rewrite(m_wallet_file, pwd_container->password());
}
return true;
}
bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
if(args.empty())
@ -3351,6 +3367,8 @@ simple_wallet::simple_wallet()
" Device name for hardware wallet.\n "
"export-format <\"binary\"|\"ascii\">\n "
" Save all exported files as binary (cannot be copied and pasted) or ascii (can be).\n "
"change-output-index <n>\n "
" the destination address index for generating the change output if needed.\n "
"load-deprecated-formats <1|0>\n "
" Whether to enable importing data in deprecated formats.\n "
"show-wallet-name-when-locked <1|0>\n "
@ -3751,6 +3769,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
success_msg_writer() << "setup-background-mining = " << setup_background_mining_string;
success_msg_writer() << "device-name = " << m_wallet->device_name();
success_msg_writer() << "export-format = " << (m_wallet->export_format() == tools::wallet2::ExportFormat::Ascii ? "ascii" : "binary");
success_msg_writer() << "change-output-index = " << m_wallet->change_output_address_index();
success_msg_writer() << "show-wallet-name-when-locked = " << m_wallet->show_wallet_name_when_locked();
success_msg_writer() << "inactivity-lock-timeout = " << m_wallet->inactivity_lock_timeout()
#ifdef _WIN32
@ -3824,6 +3843,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
CHECK_SIMPLE_VARIABLE("export-format", set_export_format, tr("\"binary\" or \"ascii\""));
CHECK_SIMPLE_VARIABLE("load-deprecated-formats", set_load_deprecated_formats, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("enable-multisig-experimental", set_enable_multisig, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("change-output-index", set_change_output_index, tr("unsigned integer"));
}
fail_msg_writer() << tr("set: unrecognized argument(s)");
return true;

View file

@ -155,6 +155,7 @@ namespace cryptonote
bool set_export_format(const std::vector<std::string> &args = std::vector<std::string>());
bool set_load_deprecated_formats(const std::vector<std::string> &args = std::vector<std::string>());
bool set_enable_multisig(const std::vector<std::string> &args = std::vector<std::string>());
bool set_change_output_index(const std::vector<std::string> &args = std::vector<std::string>());
bool help(const std::vector<std::string> &args = std::vector<std::string>());
bool apropos(const std::vector<std::string> &args);
bool scan_tx(const std::vector<std::string> &args);

View file

@ -1253,6 +1253,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_change_output_address_index(0),
m_enable_multisig(false),
m_pool_info_query_time(0),
m_has_ever_refreshed_from_node(false),
@ -4761,6 +4762,9 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const crypt
value2.SetInt(false);
json.AddMember("load_deprecated_formats", value2, json.GetAllocator());
value2.SetInt(m_change_output_address_index);
json.AddMember("change_output_address_index", value2, json.GetAllocator());
value2.SetUint(1);
json.AddMember("encrypted_secret_keys", value2, json.GetAllocator());
@ -5024,6 +5028,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_change_output_address_index = 0;
m_device_name = "";
m_device_derivation_path = "";
m_key_device_type = hw::device::device_type::SOFTWARE;
@ -5208,6 +5213,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, change_output_address_index, uint32_t, Uint, false, 0);
m_change_output_address_index = field_change_output_address_index;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, device_name, std::string, String, false, std::string());
if (m_device_name.empty())
{
@ -9759,8 +9767,8 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
cryptonote::tx_destination_entry change_dts = AUTO_VAL_INIT(change_dts);
if (needed_money < found_money)
{
change_dts.addr = get_subaddress({subaddr_account, 0});
change_dts.is_subaddress = subaddr_account != 0;
change_dts.addr = get_subaddress({subaddr_account, m_change_output_address_index});
change_dts.is_subaddress = subaddr_account != 0 || m_change_output_address_index != 0;
change_dts.amount = found_money - needed_money;
}
@ -10006,8 +10014,8 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
}
else
{
change_dts.addr = get_subaddress({subaddr_account, 0});
change_dts.is_subaddress = subaddr_account != 0;
change_dts.addr = get_subaddress({subaddr_account, m_change_output_address_index});
change_dts.is_subaddress = subaddr_account != 0 || m_change_output_address_index != 0;
splitted_dsts.push_back(change_dts);
}

View file

@ -1485,6 +1485,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; }
uint32_t change_output_address_index() const { return m_change_output_address_index; }
void set_change_output_address_index(uint32_t value) { m_change_output_address_index = value; }
bool is_multisig_enabled() const { return m_enable_multisig; }
void enable_multisig(bool enable) { m_enable_multisig = enable; }
bool is_mismatched_daemon_version_allowed() const { return m_allow_mismatched_daemon_version; }
@ -2045,6 +2047,8 @@ private:
ExportFormat m_export_format;
uint32_t m_change_output_address_index;
bool m_has_ever_refreshed_from_node;
static boost::mutex default_daemon_address_lock;