From 200586592c9a9d23c52046982fc4f5f86ad1978b Mon Sep 17 00:00:00 2001 From: thotbot Date: Sat, 3 Jul 2021 23:05:40 +0200 Subject: [PATCH] Import transaction --- src/wallet/api/wallet.cpp | 18 ++++++++++++- src/wallet/api/wallet.h | 1 + src/wallet/api/wallet2_api.h | 2 ++ src/wallet/wallet2.cpp | 50 ++++++++++++++++++++++++++++++++++++ src/wallet/wallet2.h | 1 + 5 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 29b3bbf12..574dea875 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -1400,7 +1400,7 @@ bool WalletImpl::scanTransactions(const std::vector &txids) setStatusError(string(tr("Failed to scan transaction: ")) + e.what()); return false; } - + return true; } @@ -1473,6 +1473,22 @@ std::string WalletImpl::printScannedPoolTxs() return m_wallet->printScannedPoolTxs(); } +bool WalletImpl::importTransaction(const std::string &txid, std::vector &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen) +{ + try + { + m_wallet->import_tx(txid, o_indices, height, block_version, ts, miner_tx, pool, double_spend_seen); + } + catch (const std::exception &e) + { + LOG_ERROR("Failed to import transaction: " << e.what()); + setStatusError(string(tr("Failed to import transaction: ")) + e.what()); + return false; + } + + return true; +} + void WalletImpl::addSubaddressAccount(const std::string& label) { m_wallet->add_subaddress_account(label); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index b9cbbf921..517f4b01e 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -184,6 +184,7 @@ public: bool importKeyImages(const std::string &filename) override; bool exportOutputs(const std::string &filename, bool all = false) override; bool importOutputs(const std::string &filename) override; + bool importTransaction(const std::string &txid, std::vector &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen) override; bool scanTransactions(const std::vector &txids) override; virtual std::string printBlockchain() override; diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index 4efdc1364..f7cda7315 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -1082,6 +1082,8 @@ struct Wallet virtual std::string printAddressBook() = 0; virtual std::string printScannedPoolTxs() = 0; + virtual bool importTransaction(const std::string &txid, std::vector &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen) = 0; + virtual TransactionHistory * history() = 0; virtual AddressBook * addressBook() = 0; virtual Coins * coins() = 0; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index d13028173..0659e2a74 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2228,6 +2228,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote update_multisig_rescan_info(*m_multisig_rescan_k, *m_multisig_rescan_info, m_transfers.size() - 1); } LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid); + lock.unlock(); + if (0 != m_callback) m_callback->on_money_received(height, txid, tx, td.m_amount, 0, td.m_subaddr_index, spends_one_of_ours(tx), td.m_tx.unlock_time); } @@ -3294,6 +3296,54 @@ void wallet2::update_pool_state(std::vector &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen) +{ + crypto::hash hash; + epee::string_tools::hex_to_pod(txid, hash); + + cryptonote::COMMAND_RPC_GET_TRANSACTIONS::request req; + cryptonote::COMMAND_RPC_GET_TRANSACTIONS::response res; + req.txs_hashes.push_back(epee::string_tools::pod_to_hex(hash)); + + req.decode_as_json = false; + req.prune = true; + + bool r; + { + const boost::lock_guard lock{m_daemon_rpc_mutex}; + uint64_t pre_call_credits = m_rpc_payment_state.credits; + req.client = get_client_signature(); + r = epee::net_utils::invoke_http_json("/gettransactions", req, res, *m_http_client, rpc_timeout); + if (r && res.status == CORE_RPC_STATUS_OK) + check_rpc_cost("/gettransactions", res.credits, pre_call_credits, res.txs.size() * COST_PER_TX); + } + + MDEBUG("Got " << r << " and " << res.status); + if (!(r && res.status == CORE_RPC_STATUS_OK)) { + THROW_WALLET_EXCEPTION(error::wallet_internal_error, "Error calling gettransactions daemon RPC: r " + std::to_string(r) + ", status " + get_rpc_status(res.status)); + } + + if (res.txs.size() != 1) { + THROW_WALLET_EXCEPTION(error::wallet_internal_error, "Expected 1 tx, got " + std::to_string(res.txs.size())); + } + + const auto &tx_entry = res.txs[0]; + cryptonote::transaction tx; + cryptonote::blobdata bd; + crypto::hash tx_hash; + + if (!get_pruned_tx(tx_entry, tx, tx_hash)) { + THROW_WALLET_EXCEPTION(error::wallet_internal_error, "Failed to parse transaction from daemon"); + } + + if (tx_hash != hash) { + THROW_WALLET_EXCEPTION(error::wallet_internal_error, "Got txid " + epee::string_tools::pod_to_hex(tx_hash) + " which we did not ask for"); + } + + process_new_transaction(tx_hash, tx, o_indices, height, block_version, ts, miner_tx, pool, double_spend_seen, {}); +} //---------------------------------------------------------------------------------------------------- void wallet2::process_pool_state(const std::vector> &txs) { diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 6ea348fe4..9afae8267 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1506,6 +1506,7 @@ private: bool import_key_images(std::vector key_images, size_t offset=0, boost::optional> selected_transfers=boost::none); bool import_key_images(signed_tx_set & signed_tx, size_t offset=0, bool only_selected_transfers=false); crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const; + void import_tx(const std::string &txid, std::vector &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen); void update_pool_state(std::vector> &process_txs, bool refreshed = false); void process_pool_state(const std::vector> &txs);