simplewallet: allow setting tx keys when sending to a subaddress

The tx key derivation is different then
This commit is contained in:
moneromooo-monero 2020-08-10 21:25:51 +00:00
parent e916201f12
commit 85899230d1
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3
3 changed files with 33 additions and 5 deletions

View file

@ -208,7 +208,7 @@ namespace
const char* USAGE_ADDRESS_BOOK("address_book [(add (<address>|<integrated address>) [<description possibly with whitespaces>])|(delete <index>)]"); const char* USAGE_ADDRESS_BOOK("address_book [(add (<address>|<integrated address>) [<description possibly with whitespaces>])|(delete <index>)]");
const char* USAGE_SET_VARIABLE("set <option> [<value>]"); const char* USAGE_SET_VARIABLE("set <option> [<value>]");
const char* USAGE_GET_TX_KEY("get_tx_key <txid>"); const char* USAGE_GET_TX_KEY("get_tx_key <txid>");
const char* USAGE_SET_TX_KEY("set_tx_key <txid> <tx_key>"); const char* USAGE_SET_TX_KEY("set_tx_key <txid> <tx_key> [<subaddress>]");
const char* USAGE_CHECK_TX_KEY("check_tx_key <txid> <txkey> <address>"); const char* USAGE_CHECK_TX_KEY("check_tx_key <txid> <txkey> <address>");
const char* USAGE_GET_TX_PROOF("get_tx_proof <txid> <address> [<message>]"); const char* USAGE_GET_TX_PROOF("get_tx_proof <txid> <address> [<message>]");
const char* USAGE_CHECK_TX_PROOF("check_tx_proof <txid> <address> <signature_file> [<message>]"); const char* USAGE_CHECK_TX_PROOF("check_tx_proof <txid> <address> <signature_file> [<message>]");
@ -7884,11 +7884,27 @@ bool simple_wallet::set_tx_key(const std::vector<std::string> &args_)
{ {
std::vector<std::string> local_args = args_; std::vector<std::string> local_args = args_;
if(local_args.size() != 2) { if(local_args.size() != 2 && local_args.size() != 3) {
PRINT_USAGE(USAGE_SET_TX_KEY); PRINT_USAGE(USAGE_SET_TX_KEY);
return true; return true;
} }
boost::optional<cryptonote::account_public_address> single_destination_subaddress;
if (local_args.size() > 1)
{
cryptonote::address_parse_info info;
if (cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args.back(), oa_prompter))
{
if (!info.is_subaddress)
{
fail_msg_writer() << tr("Last argument is an address, but not a subaddress");
return true;
}
single_destination_subaddress = info.address;
local_args.pop_back();
}
}
crypto::hash txid; crypto::hash txid;
if (!epee::string_tools::hex_to_pod(local_args[0], txid)) if (!epee::string_tools::hex_to_pod(local_args[0], txid))
{ {
@ -7928,12 +7944,14 @@ bool simple_wallet::set_tx_key(const std::vector<std::string> &args_)
try try
{ {
m_wallet->set_tx_key(txid, tx_key, additional_tx_keys); m_wallet->set_tx_key(txid, tx_key, additional_tx_keys, single_destination_subaddress);
success_msg_writer() << tr("Tx key successfully stored."); success_msg_writer() << tr("Tx key successfully stored.");
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {
fail_msg_writer() << tr("Failed to store tx key: ") << e.what(); fail_msg_writer() << tr("Failed to store tx key: ") << e.what();
if (!single_destination_subaddress)
fail_msg_writer() << tr("It could be because the transfer was to a subaddress. If this is the case, pass the subaddress last");
} }
return true; return true;
} }

View file

@ -10915,7 +10915,7 @@ bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, s
return true; return true;
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
void wallet2::set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys) void wallet2::set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const boost::optional<cryptonote::account_public_address> &single_destination_subaddress)
{ {
// fetch tx from daemon and check if secret keys agree with corresponding public keys // fetch tx from daemon and check if secret keys agree with corresponding public keys
COMMAND_RPC_GET_TRANSACTIONS::request req = AUTO_VAL_INIT(req); COMMAND_RPC_GET_TRANSACTIONS::request req = AUTO_VAL_INIT(req);
@ -10956,6 +10956,16 @@ void wallet2::set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_
found = true; found = true;
break; break;
} }
// when sent to a single subaddress, the derivation is different
if (single_destination_subaddress)
{
calculated_pub_key = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(single_destination_subaddress->m_spend_public_key), rct::sk2rct(tx_key)));
if (calculated_pub_key == pub_key_field.pub_key)
{
found = true;
break;
}
}
} }
THROW_WALLET_EXCEPTION_IF(!found, error::wallet_internal_error, "Given tx secret key doesn't agree with the tx public key in the blockchain"); THROW_WALLET_EXCEPTION_IF(!found, error::wallet_internal_error, "Given tx secret key doesn't agree with the tx public key in the blockchain");
tx_extra_additional_pub_keys additional_tx_pub_keys; tx_extra_additional_pub_keys additional_tx_pub_keys;

View file

@ -1106,7 +1106,7 @@ private:
void credits_target(uint64_t threshold) { m_credits_target = threshold; } void credits_target(uint64_t threshold) { m_credits_target = threshold; }
bool get_tx_key_cached(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys) const; bool get_tx_key_cached(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys) const;
void set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys); void set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const boost::optional<cryptonote::account_public_address> &single_destination_subaddress = boost::none);
bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys); bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys);
void check_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations); void check_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations);
void 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); void 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);