#include "coins.h" #include "coins_info.h" #include "wallet.h" #include "crypto/hash.h" #include "wallet/wallet2.h" #include "common_defines.h" #include #include using namespace epee; namespace Monero { Coins::~Coins() = default; CoinsImpl::CoinsImpl(WalletImpl *wallet) : m_wallet(wallet) {} CoinsImpl::~CoinsImpl() { for (auto t : m_rows) delete t; } int CoinsImpl::count() const { boost::shared_lock lock(m_rowsMutex); int result = m_rows.size(); return result; } CoinsInfo *CoinsImpl::coin(int index) const { boost::shared_lock lock(m_rowsMutex); // sanity check if (index < 0) return nullptr; auto index_ = static_cast(index); return index_ < m_rows.size() ? m_rows[index_] : nullptr; } std::vector CoinsImpl::getAll() const { boost::shared_lock lock(m_rowsMutex); return m_rows; } void CoinsImpl::refresh() { LOG_PRINT_L2("Refreshing coins"); boost::unique_lock lock(m_rowsMutex); boost::shared_lock transfers_lock(m_wallet->m_wallet->m_transfers_mutex); // delete old outputs; for (auto t : m_rows) delete t; m_rows.clear(); for (size_t i = 0; i < m_wallet->m_wallet->get_num_transfer_details(); ++i) { const tools::wallet2::transfer_details &td = m_wallet->m_wallet->get_transfer_details(i); auto ci = new CoinsInfoImpl(); ci->m_blockHeight = td.m_block_height; ci->m_hash = string_tools::pod_to_hex(td.m_txid); ci->m_internalOutputIndex = td.m_internal_output_index; ci->m_globalOutputIndex = td.m_global_output_index; ci->m_spent = td.m_spent; ci->m_frozen = td.m_frozen; ci->m_spentHeight = td.m_spent_height; ci->m_amount = td.m_amount; ci->m_rct = td.m_rct; ci->m_keyImageKnown = td.m_key_image_known; ci->m_pkIndex = td.m_pk_index; ci->m_subaddrIndex = td.m_subaddr_index.minor; ci->m_subaddrAccount = td.m_subaddr_index.major; ci->m_address = m_wallet->m_wallet->get_subaddress_as_str(td.m_subaddr_index); // todo: this is expensive, cache maybe? ci->m_addressLabel = m_wallet->m_wallet->get_subaddress_label(td.m_subaddr_index); ci->m_keyImage = string_tools::pod_to_hex(td.m_key_image); ci->m_unlockTime = td.m_tx.unlock_time; ci->m_unlocked = m_wallet->m_wallet->is_transfer_unlocked(td); ci->m_pubKey = string_tools::pod_to_hex(td.get_public_key()); ci->m_coinbase = td.m_tx.vin.size() == 1 && td.m_tx.vin[0].type() == typeid(cryptonote::txin_gen); m_rows.push_back(ci); } } void CoinsImpl::setFrozen(int index) { try { m_wallet->m_wallet->freeze(index); refresh(); } catch (const std::exception& e) { LOG_ERROR("setLabel: " << e.what()); } } void CoinsImpl::thaw(int index) { try { m_wallet->m_wallet->thaw(index); refresh(); } catch (const std::exception& e) { LOG_ERROR("thaw: " << e.what()); } } bool CoinsImpl::isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) { return m_wallet->m_wallet->is_transfer_unlocked(unlockTime, blockHeight); } } // namespace