From 45a63f10bae43560fdf27012935363fe0baeaeca Mon Sep 17 00:00:00 2001 From: thotbot Date: Sat, 3 Jul 2021 22:12:01 +0200 Subject: [PATCH] Coins --- src/wallet/api/CMakeLists.txt | 8 ++- src/wallet/api/coins.cpp | 122 ++++++++++++++++++++++++++++++++++ src/wallet/api/coins.h | 34 ++++++++++ src/wallet/api/coins_info.cpp | 118 ++++++++++++++++++++++++++++++++ src/wallet/api/coins_info.h | 67 +++++++++++++++++++ 5 files changed, 347 insertions(+), 2 deletions(-) create mode 100644 src/wallet/api/coins.cpp create mode 100644 src/wallet/api/coins.h create mode 100644 src/wallet/api/coins_info.cpp create mode 100644 src/wallet/api/coins_info.h diff --git a/src/wallet/api/CMakeLists.txt b/src/wallet/api/CMakeLists.txt index 4245fac7e..630557aaf 100644 --- a/src/wallet/api/CMakeLists.txt +++ b/src/wallet/api/CMakeLists.txt @@ -42,7 +42,9 @@ set(wallet_api_sources address_book.cpp subaddress.cpp subaddress_account.cpp - unsigned_transaction.cpp) + unsigned_transaction.cpp + coins.cpp + coins_info.cpp) set(wallet_api_headers wallet2_api.h) @@ -59,7 +61,9 @@ set(wallet_api_private_headers address_book.h subaddress.h subaddress_account.h - unsigned_transaction.h) + unsigned_transaction.h + coins.h + coins_info.h) monero_private_headers(wallet_api ${wallet_api_private_headers}) diff --git a/src/wallet/api/coins.cpp b/src/wallet/api/coins.cpp new file mode 100644 index 000000000..99c3a51f8 --- /dev/null +++ b/src/wallet/api/coins.cpp @@ -0,0 +1,122 @@ +#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 diff --git a/src/wallet/api/coins.h b/src/wallet/api/coins.h new file mode 100644 index 000000000..3293d8ae9 --- /dev/null +++ b/src/wallet/api/coins.h @@ -0,0 +1,34 @@ +#ifndef WOWLET_COINS_H +#define WOWLET_COINS_H + +#include "wallet/api/wallet2_api.h" +#include "wallet/wallet2.h" + +namespace Monero { + + class WalletImpl; + + class CoinsImpl : public Coins + { + public: + explicit CoinsImpl(WalletImpl * wallet); + ~CoinsImpl() override; + int count() const override; + CoinsInfo * coin(int index) const override; + std::vector getAll() const override; + void refresh() override; + + void setFrozen(int index) override; + void thaw(int index) override; + + bool isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) override; + + private: + WalletImpl *m_wallet; + std::vector m_rows; + mutable boost::shared_mutex m_rowsMutex; + }; + +} + +#endif //WOWLET_COINS_H diff --git a/src/wallet/api/coins_info.cpp b/src/wallet/api/coins_info.cpp new file mode 100644 index 000000000..06d874ddf --- /dev/null +++ b/src/wallet/api/coins_info.cpp @@ -0,0 +1,118 @@ +#include "coins_info.h" + +using namespace std; + +namespace Monero { + + CoinsInfo::~CoinsInfo() = default; + + CoinsInfoImpl::CoinsInfoImpl() + : m_blockHeight(0) + , m_internalOutputIndex(0) + , m_globalOutputIndex(0) + , m_spent(false) + , m_frozen(false) + , m_spentHeight(0) + , m_amount(0) + , m_rct(false) + , m_keyImageKnown(false) + , m_pkIndex(0) + , m_subaddrAccount(0) + , m_subaddrIndex(0) + , m_unlockTime(0) + , m_unlocked(false) + { + + } + + CoinsInfoImpl::~CoinsInfoImpl() = default; + + uint64_t CoinsInfoImpl::blockHeight() const + { + return m_blockHeight; + } + + string CoinsInfoImpl::hash() const + { + return m_hash; + } + + size_t CoinsInfoImpl::internalOutputIndex() const { + return m_internalOutputIndex; + } + + uint64_t CoinsInfoImpl::globalOutputIndex() const + { + return m_globalOutputIndex; + } + + bool CoinsInfoImpl::spent() const + { + return m_spent; + } + + bool CoinsInfoImpl::frozen() const + { + return m_frozen; + } + + uint64_t CoinsInfoImpl::spentHeight() const + { + return m_spentHeight; + } + + uint64_t CoinsInfoImpl::amount() const + { + return m_amount; + } + + bool CoinsInfoImpl::rct() const { + return m_rct; + } + + bool CoinsInfoImpl::keyImageKnown() const { + return m_keyImageKnown; + } + + size_t CoinsInfoImpl::pkIndex() const { + return m_pkIndex; + } + + uint32_t CoinsInfoImpl::subaddrIndex() const { + return m_subaddrIndex; + } + + uint32_t CoinsInfoImpl::subaddrAccount() const { + return m_subaddrAccount; + } + + string CoinsInfoImpl::address() const { + return m_address; + } + + string CoinsInfoImpl::addressLabel() const { + return m_addressLabel; + } + + string CoinsInfoImpl::keyImage() const { + return m_keyImage; + } + + uint64_t CoinsInfoImpl::unlockTime() const { + return m_unlockTime; + } + + bool CoinsInfoImpl::unlocked() const { + return m_unlocked; + } + + string CoinsInfoImpl::pubKey() const { + return m_pubKey; + } + + bool CoinsInfoImpl::coinbase() const { + return m_coinbase; + } +} // namespace + +namespace Bitmonero = Monero; diff --git a/src/wallet/api/coins_info.h b/src/wallet/api/coins_info.h new file mode 100644 index 000000000..c76109334 --- /dev/null +++ b/src/wallet/api/coins_info.h @@ -0,0 +1,67 @@ +#ifndef WOWLET_COINS_INFO_H +#define WOWLET_COINS_INFO_H + +#include "wallet/api/wallet2_api.h" +#include +#include + +namespace Monero { + + class CoinsImpl; + + class CoinsInfoImpl : public CoinsInfo + { + public: + CoinsInfoImpl(); + ~CoinsInfoImpl(); + + virtual uint64_t blockHeight() const override; + virtual std::string hash() const override; + virtual size_t internalOutputIndex() const override; + virtual uint64_t globalOutputIndex() const override; + virtual bool spent() const override; + virtual bool frozen() const override; + virtual uint64_t spentHeight() const override; + virtual uint64_t amount() const override; + virtual bool rct() const override; + virtual bool keyImageKnown() const override; + virtual size_t pkIndex() const override; + virtual uint32_t subaddrIndex() const override; + virtual uint32_t subaddrAccount() const override; + virtual std::string address() const override; + virtual std::string addressLabel() const override; + virtual std::string keyImage() const override; + virtual uint64_t unlockTime() const override; + virtual bool unlocked() const override; + virtual std::string pubKey() const override; + virtual bool coinbase() const override; + + private: + uint64_t m_blockHeight; + std::string m_hash; + size_t m_internalOutputIndex; + uint64_t m_globalOutputIndex; + bool m_spent; + bool m_frozen; + uint64_t m_spentHeight; + uint64_t m_amount; + bool m_rct; + bool m_keyImageKnown; + size_t m_pkIndex; + uint32_t m_subaddrIndex; + uint32_t m_subaddrAccount; + std::string m_address; + std::string m_addressLabel; + std::string m_keyImage; + uint64_t m_unlockTime; + bool m_unlocked; + std::string m_pubKey; + bool m_coinbase; + + friend class CoinsImpl; + + }; + +} // namespace + +#endif //WOWLET_COINS_INFO_H