mirror of
https://github.com/monero-project/monero.git
synced 2025-08-09 04:42:21 -04:00
Merge pull request #3780
9c2a7b4
wallet-rpc: watch-only and cold wallet features added (ph4r05)
This commit is contained in:
commit
4e7897e57c
7 changed files with 495 additions and 98 deletions
|
@ -712,7 +712,7 @@ namespace tools
|
|||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
template<typename Ts, typename Tu>
|
||||
bool wallet_rpc_server::fill_response(std::vector<tools::wallet2::pending_tx> &ptx_vector,
|
||||
bool get_tx_key, Ts& tx_key, Tu &amount, Tu &fee, std::string &multisig_txset, bool do_not_relay,
|
||||
bool get_tx_key, Ts& tx_key, Tu &amount, Tu &fee, std::string &multisig_txset, std::string &unsigned_txset, bool do_not_relay,
|
||||
Ts &tx_hash, bool get_tx_hex, Ts &tx_blob, bool get_tx_metadata, Ts &tx_metadata, epee::json_rpc::error &er)
|
||||
{
|
||||
for (const auto & ptx : ptx_vector)
|
||||
|
@ -741,7 +741,16 @@ namespace tools
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!do_not_relay)
|
||||
if (m_wallet->watch_only()){
|
||||
unsigned_txset = epee::string_tools::buff_to_hex_nodelimer(m_wallet->dump_tx_to_str(ptx_vector));
|
||||
if (unsigned_txset.empty())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "Failed to save unsigned tx set after creation";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!do_not_relay)
|
||||
m_wallet->commit_tx(ptx_vector);
|
||||
|
||||
// populate response with tx hashes
|
||||
|
@ -811,7 +820,7 @@ namespace tools
|
|||
return false;
|
||||
}
|
||||
|
||||
return fill_response(ptx_vector, req.get_tx_key, res.tx_key, res.amount, res.fee, res.multisig_txset, req.do_not_relay,
|
||||
return fill_response(ptx_vector, req.get_tx_key, res.tx_key, res.amount, res.fee, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
|
||||
res.tx_hash, req.get_tx_hex, res.tx_blob, req.get_tx_metadata, res.tx_metadata, er);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
@ -858,7 +867,7 @@ namespace tools
|
|||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, m_trusted_daemon);
|
||||
LOG_PRINT_L2("on_transfer_split called create_transactions_2");
|
||||
|
||||
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.multisig_txset, req.do_not_relay,
|
||||
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
|
||||
res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, er);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
@ -869,6 +878,141 @@ namespace tools
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_sign_transfer(const wallet_rpc::COMMAND_RPC_SIGN_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_SIGN_TRANSFER::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
if (m_wallet->restricted())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_DENIED;
|
||||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
if (m_wallet->key_on_device())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "command not supported by HW wallet";
|
||||
return false;
|
||||
}
|
||||
if(m_wallet->watch_only())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WATCH_ONLY;
|
||||
er.message = "command not supported by watch-only wallet";
|
||||
return false;
|
||||
}
|
||||
|
||||
cryptonote::blobdata blob;
|
||||
if (!epee::string_tools::parse_hexstr_to_binbuff(req.unsigned_txset, blob))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_BAD_HEX;
|
||||
er.message = "Failed to parse hex.";
|
||||
return false;
|
||||
}
|
||||
|
||||
tools::wallet2::unsigned_tx_set exported_txs;
|
||||
if(!m_wallet->parse_unsigned_tx_from_str(blob, exported_txs))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
||||
er.message = "cannot load unsigned_txset";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<tools::wallet2::pending_tx> ptxs;
|
||||
try
|
||||
{
|
||||
tools::wallet2::signed_tx_set signed_txs;
|
||||
std::string ciphertext = m_wallet->sign_tx_dump_to_str(exported_txs, ptxs, signed_txs);
|
||||
if (ciphertext.empty())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_SIGN_UNSIGNED;
|
||||
er.message = "Failed to sign unsigned tx";
|
||||
return false;
|
||||
}
|
||||
|
||||
res.signed_txset = epee::string_tools::buff_to_hex_nodelimer(ciphertext);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_SIGN_UNSIGNED;
|
||||
er.message = std::string("Failed to sign unsigned tx: ") + e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto &ptx: ptxs)
|
||||
{
|
||||
res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
|
||||
}
|
||||
|
||||
if (req.export_raw)
|
||||
{
|
||||
for (auto &ptx: ptxs)
|
||||
{
|
||||
res.tx_raw_list.push_back(epee::string_tools::buff_to_hex_nodelimer(cryptonote::tx_to_blob(ptx.tx)));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_submit_transfer(const wallet_rpc::COMMAND_RPC_SUBMIT_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_SUBMIT_TRANSFER::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
if (m_wallet->restricted())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_DENIED;
|
||||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
if (m_wallet->key_on_device())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "command not supported by HW wallet";
|
||||
return false;
|
||||
}
|
||||
|
||||
cryptonote::blobdata blob;
|
||||
if (!epee::string_tools::parse_hexstr_to_binbuff(req.tx_data_hex, blob))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_BAD_HEX;
|
||||
er.message = "Failed to parse hex.";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<tools::wallet2::pending_tx> ptx_vector;
|
||||
try
|
||||
{
|
||||
bool r = m_wallet->parse_tx_from_str(blob, ptx_vector, NULL);
|
||||
if (!r)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_BAD_SIGNED_TX_DATA;
|
||||
er.message = "Failed to parse signed tx data.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_BAD_SIGNED_TX_DATA;
|
||||
er.message = std::string("Failed to parse signed tx: ") + e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
for (auto &ptx: ptx_vector)
|
||||
{
|
||||
m_wallet->commit_tx(ptx);
|
||||
res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_SIGNED_SUBMISSION;
|
||||
er.message = std::string("Failed to submit signed tx: ") + e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_sweep_dust(const wallet_rpc::COMMAND_RPC_SWEEP_DUST::request& req, wallet_rpc::COMMAND_RPC_SWEEP_DUST::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
|
@ -883,7 +1027,7 @@ namespace tools
|
|||
{
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_unmixable_sweep_transactions(m_trusted_daemon);
|
||||
|
||||
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.multisig_txset, req.do_not_relay,
|
||||
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
|
||||
res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, er);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
@ -931,7 +1075,7 @@ namespace tools
|
|||
uint32_t priority = m_wallet->adjust_priority(req.priority);
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_all(req.below_amount, dsts[0].addr, dsts[0].is_subaddress, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, m_trusted_daemon);
|
||||
|
||||
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.multisig_txset, req.do_not_relay,
|
||||
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
|
||||
res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, er);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
@ -1007,7 +1151,7 @@ namespace tools
|
|||
return false;
|
||||
}
|
||||
|
||||
return fill_response(ptx_vector, req.get_tx_key, res.tx_key, res.amount, res.fee, res.multisig_txset, req.do_not_relay,
|
||||
return fill_response(ptx_vector, req.get_tx_key, res.tx_key, res.amount, res.fee, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
|
||||
res.tx_hash, req.get_tx_hex, res.tx_blob, req.get_tx_metadata, res.tx_metadata, er);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
@ -1974,6 +2118,72 @@ namespace tools
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_export_outputs(const wallet_rpc::COMMAND_RPC_EXPORT_OUTPUTS::request& req, wallet_rpc::COMMAND_RPC_EXPORT_OUTPUTS::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
if (m_wallet->restricted())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_DENIED;
|
||||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
if (m_wallet->key_on_device())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "command not supported by HW wallet";
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
res.outputs_data_hex = epee::string_tools::buff_to_hex_nodelimer(m_wallet->export_outputs_to_str());
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_import_outputs(const wallet_rpc::COMMAND_RPC_IMPORT_OUTPUTS::request& req, wallet_rpc::COMMAND_RPC_IMPORT_OUTPUTS::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
if (m_wallet->restricted())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_DENIED;
|
||||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
if (m_wallet->key_on_device())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "command not supported by HW wallet";
|
||||
return false;
|
||||
}
|
||||
|
||||
cryptonote::blobdata blob;
|
||||
if (!epee::string_tools::parse_hexstr_to_binbuff(req.outputs_data_hex, blob))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_BAD_HEX;
|
||||
er.message = "Failed to parse hex.";
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
res.num_imported = m_wallet->import_outputs_from_str(blob);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_export_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue