From 509699cb09a28d883e80520dc3ba1f26053e7ddf Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sat, 25 Feb 2023 09:45:37 +0100 Subject: [PATCH 01/17] Fix available balance --- src/Wallet/WalletGreen.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index 3cf062eae..15610cceb 100644 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -3674,7 +3674,7 @@ namespace cn bool updated = false; /* First get the available and pending balances from the container */ - uint64_t actual = container->balance(ITransfersContainer::IncludeAllUnlocked); + uint64_t actual = container->balance(ITransfersContainer::IncludeKeyUnlocked); uint64_t pending = container->balance(ITransfersContainer::IncludeKeyNotUnlocked); /* Now update the overall balance (getBalance without parameters) */ @@ -3683,7 +3683,7 @@ namespace cn m_actualBalance += actual - it->actualBalance; updated = true; } - else + else if (it->actualBalance > actual) { m_actualBalance -= it->actualBalance - actual; updated = true; @@ -3694,7 +3694,7 @@ namespace cn m_pendingBalance += pending - it->pendingBalance; updated = true; } - else + else if (it->pendingBalance > pending) { m_pendingBalance -= it->pendingBalance - pending; updated = true; @@ -3706,15 +3706,13 @@ namespace cn container->getOutputs(transfers2, ITransfersContainer::IncludeTypeDeposit | ITransfersContainer::IncludeStateLocked | ITransfersContainer::IncludeStateSoftLocked); std::vector heights2; - for (auto transfer2 : transfers2) + for (const auto &transfer2 : transfers2) { crypto::Hash hash2 = transfer2.transactionHash; TransactionInformation info2; - bool ok2 = container->getTransactionInformation(hash2, info2, NULL, NULL); - if (ok2) + if (container->getTransactionInformation(hash2, info2, nullptr, nullptr)) { heights2.push_back(info2.blockHeight); - updated = true; } } uint64_t locked = calculateDepositsAmount(transfers2, m_currency, heights2); @@ -3725,13 +3723,14 @@ namespace cn container->getOutputs(transfers, ITransfersContainer::IncludeTypeDeposit | ITransfersContainer::IncludeStateUnlocked); std::vector heights; - for (auto transfer : transfers) + for (const auto &transfer : transfers) { crypto::Hash hash = transfer.transactionHash; TransactionInformation info; - bool ok = container->getTransactionInformation(hash, info, NULL, NULL); - assert(ok); - heights.push_back(info.blockHeight); + if (container->getTransactionInformation(hash, info, nullptr, nullptr)) + { + heights.push_back(info.blockHeight); + } } uint64_t unlocked = calculateDepositsAmount(transfers, m_currency, heights); @@ -3741,7 +3740,7 @@ namespace cn m_lockedDepositBalance += locked - it->lockedDepositBalance; updated = true; } - else + else if (it->lockedDepositBalance > locked) { m_lockedDepositBalance -= it->lockedDepositBalance - locked; updated = true; @@ -3752,7 +3751,7 @@ namespace cn m_unlockedDepositBalance += unlocked - it->unlockedDepositBalance; updated = true; } - else + else if (it->unlockedDepositBalance > unlocked) { m_unlockedDepositBalance -= it->unlockedDepositBalance - unlocked; updated = true; From e54a3ec3c6b79b3c77a1e54e9d6c9a280075e2a1 Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sun, 8 Jan 2023 19:44:33 +0100 Subject: [PATCH 02/17] Fix daemon-address usage --- src/Common/CommandLine.h | 6 ++++++ src/ConcealWallet/ConcealWallet.cpp | 6 +++--- src/ConcealWallet/Const.h | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Common/CommandLine.h b/src/Common/CommandLine.h index 4998c8335..2ae9b6122 100644 --- a/src/Common/CommandLine.h +++ b/src/Common/CommandLine.h @@ -159,6 +159,12 @@ namespace command_line return !value.empty(); } + template + bool has_arg_2(const boost::program_options::variables_map &vm, const arg_descriptor &arg) + { + auto value = vm[arg.name]; + return !value.empty() && !value.defaulted(); + } template T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor& arg) diff --git a/src/ConcealWallet/ConcealWallet.cpp b/src/ConcealWallet/ConcealWallet.cpp index 6b116604f..161c0e8c5 100644 --- a/src/ConcealWallet/ConcealWallet.cpp +++ b/src/ConcealWallet/ConcealWallet.cpp @@ -415,12 +415,12 @@ bool key_import = true; //---------------------------------------------------------------------------------------------------- bool conceal_wallet::init(const boost::program_options::variables_map& vm) { - handle_command_line(vm); - - if (!m_daemon_address.empty() && (!m_daemon_host.empty() || 0 != m_daemon_port)) { + if (command_line::has_arg_2(vm, arg_daemon_address) && (command_line::has_arg_2(vm, arg_daemon_host) || command_line::has_arg_2(vm, arg_daemon_port))) + { fail_msg_writer() << "you can't specify daemon host or port several times"; return false; } + handle_command_line(vm); if (m_daemon_host.empty()) { diff --git a/src/ConcealWallet/Const.h b/src/ConcealWallet/Const.h index cd2d6e55d..0fe899680 100644 --- a/src/ConcealWallet/Const.h +++ b/src/ConcealWallet/Const.h @@ -11,7 +11,7 @@ namespace { const command_line::arg_descriptor arg_daemon_address = { "daemon-address", "Use daemon instance at :", "" }; const command_line::arg_descriptor arg_daemon_host = { "daemon-host", "Use daemon instance at host instead of localhost", "" }; const command_line::arg_descriptor arg_password = { "password", "Wallet password", "", true }; - const command_line::arg_descriptor arg_daemon_port = { "daemon-port", "Use daemon instance at port instead of default", 0 }; + const command_line::arg_descriptor arg_daemon_port = { "daemon-port", "Use daemon instance at port instead of default", cn::RPC_DEFAULT_PORT }; const command_line::arg_descriptor arg_log_level = { "set_log", "", logging::INFO, true }; const command_line::arg_descriptor arg_testnet = { "testnet", "Used to deploy test nets. The daemon must be launched with --testnet flag", false }; const command_line::arg_descriptor< std::vector > arg_command = { "command", "" }; From d0ab5a913cfc8e2e6b36d0aabb42bead46600d20 Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sat, 1 Apr 2023 16:56:34 +0200 Subject: [PATCH 03/17] Migrate concealwallet to walletgreen --- include/ITransfersSynchronizer.h | 10 +- include/IWallet.h | 15 + src/ConcealWallet/ClientHelper.cpp | 95 ++-- src/ConcealWallet/ClientHelper.h | 20 +- src/ConcealWallet/ConcealWallet.cpp | 707 ++++++++++---------------- src/ConcealWallet/ConcealWallet.h | 33 +- src/ConcealWallet/TransferCmd.cpp | 17 +- src/ConcealWallet/TransferCmd.h | 12 +- src/ConcealWallet/main.cpp | 8 +- src/NodeRpcProxy/NodeRpcProxy.h | 98 ++-- src/PaymentGate/NodeFactory.cpp | 28 +- src/PaymentGate/WalletService.cpp | 37 -- src/Wallet/WalletGreen.cpp | 405 +++++++++++++-- src/Wallet/WalletGreen.h | 28 +- src/Wallet/WalletIndices.h | 2 + src/Wallet/WalletUtils.cpp | 42 ++ src/Wallet/WalletUtils.h | 2 + tests/UnitTests/TestWalletService.cpp | 10 + 18 files changed, 869 insertions(+), 700 deletions(-) diff --git a/include/ITransfersSynchronizer.h b/include/ITransfersSynchronizer.h index 5b7bf6873..c703c29d3 100644 --- a/include/ITransfersSynchronizer.h +++ b/include/ITransfersSynchronizer.h @@ -31,6 +31,7 @@ class ITransfersSubscription; class ITransfersObserver { public: + virtual ~ITransfersObserver() = default; virtual void onError(ITransfersSubscription* object, uint32_t height, std::error_code ec) { } @@ -53,7 +54,7 @@ class ITransfersObserver { class ITransfersSubscription : public IObservable < ITransfersObserver > { public: - virtual ~ITransfersSubscription() {} + virtual ~ITransfersSubscription() = default; virtual AccountPublicAddress getAddress() = 0; virtual ITransfersContainer& getContainer() = 0; @@ -61,17 +62,18 @@ class ITransfersSubscription : public IObservable < ITransfersObserver > { class ITransfersSynchronizerObserver { public: + virtual ~ITransfersSynchronizerObserver() = default; virtual void onBlocksAdded(const crypto::PublicKey& viewPublicKey, const std::vector& blockHashes) {} virtual void onBlockchainDetach(const crypto::PublicKey& viewPublicKey, uint32_t blockIndex) {} - virtual void onTransactionDeleteBegin(const crypto::PublicKey& viewPublicKey, crypto::Hash transactionHash) {} - virtual void onTransactionDeleteEnd(const crypto::PublicKey& viewPublicKey, crypto::Hash transactionHash) {} + virtual void onTransactionDeleteBegin(const crypto::PublicKey &viewPublicKey, const crypto::Hash &transactionHash) {} + virtual void onTransactionDeleteEnd(const crypto::PublicKey &viewPublicKey, const crypto::Hash &transactionHash) {} virtual void onTransactionUpdated(const crypto::PublicKey& viewPublicKey, const crypto::Hash& transactionHash, const std::vector& containers) {} }; class ITransfersSynchronizer : public IStreamSerializable { public: - virtual ~ITransfersSynchronizer() {} + virtual ~ITransfersSynchronizer() = default; virtual ITransfersSubscription& addSubscription(const AccountSubscription& acc) = 0; virtual bool removeSubscription(const AccountPublicAddress& acc) = 0; diff --git a/include/IWallet.h b/include/IWallet.h index 8a899a028..3d285a7bf 100644 --- a/include/IWallet.h +++ b/include/IWallet.h @@ -171,6 +171,12 @@ struct DepositsInBlockInfo std::vector deposits; }; +struct PaymentIdTransactions +{ + crypto::Hash paymentId; + std::vector transactions; +}; + class IWallet { public: @@ -181,6 +187,7 @@ class IWallet virtual void withdrawDeposit(DepositId depositId, std::string &transactionHash) = 0; virtual Deposit getDeposit(size_t depositIndex) const = 0; virtual void initializeWithViewKey(const std::string& path, const std::string& password, const crypto::SecretKey& viewSecretKey) = 0; + virtual void generateNewWallet(const std::string &path, const std::string &password) = 0; virtual void load(const std::string& path, const std::string& password, std::string& extra) = 0; virtual void load(const std::string& path, const std::string& password) = 0; virtual void shutdown() = 0; @@ -210,6 +217,8 @@ class IWallet virtual uint64_t getActualBalance(const std::string &address) const = 0; virtual uint64_t getPendingBalance() const = 0; virtual uint64_t getPendingBalance(const std::string &address) const = 0; + virtual uint64_t getDustBalance() const = 0; + virtual uint64_t getDustBalance(const std::string &address) const = 0; virtual uint64_t getLockedDepositBalance() const = 0; virtual uint64_t getLockedDepositBalance(const std::string &address) const = 0; @@ -239,6 +248,12 @@ class IWallet virtual void commitTransaction(size_t transactionId) = 0; virtual void rollbackUncommitedTransaction(size_t transactionId) = 0; + virtual std::string getReserveProof(const std::string &address, const uint64_t &reserve, const std::string &message) = 0; + virtual bool getTxProof(const crypto::Hash &transactionHash, const cn::AccountPublicAddress &address, const crypto::SecretKey &tx_key, std::string &signature) = 0; + virtual crypto::SecretKey getTransactionDeterministicSecretKey(crypto::Hash &transactionHash) const = 0; + virtual size_t createOptimizationTransaction(const std::string &address) = 0; + virtual std::vector getTransactionsByPaymentIds(const std::vector &paymentIds) = 0; + virtual void start() = 0; virtual void stop() = 0; diff --git a/src/ConcealWallet/ClientHelper.cpp b/src/ConcealWallet/ClientHelper.cpp index 081908330..14e39d194 100644 --- a/src/ConcealWallet/ClientHelper.cpp +++ b/src/ConcealWallet/ClientHelper.cpp @@ -47,7 +47,7 @@ namespace cn if (deposit.locked) status_str = "Locked"; - else if (deposit.spendingTransactionId == cn::WALLET_LEGACY_INVALID_TRANSACTION_ID) + else if (deposit.spendingTransactionId == cn::WALLET_INVALID_TRANSACTION_ID) status_str = "Unlocked"; else status_str = "Withdrawn"; @@ -65,17 +65,17 @@ namespace cn return deposit.spendingTransactionId; } - std::string client_helper::deposit_unlock_height(const cn::Deposit &deposit, const cn::WalletLegacyTransaction &txInfo) const + std::string client_helper::deposit_unlock_height(const cn::Deposit &deposit, const uint32_t &blockHeight) const { std::string unlock_str = ""; - if (txInfo.blockHeight > cn::parameters::CRYPTONOTE_MAX_BLOCK_NUMBER) + if (blockHeight > cn::parameters::CRYPTONOTE_MAX_BLOCK_NUMBER) { unlock_str = "Please wait."; } else { - unlock_str = std::to_string(txInfo.blockHeight + deposit_term(deposit)); + unlock_str = std::to_string(blockHeight + deposit_term(deposit)); } bool bad_unlock2 = unlock_str == "0"; @@ -87,19 +87,18 @@ namespace cn return unlock_str; } - std::string client_helper::deposit_height(const cn::WalletLegacyTransaction &txInfo) const + std::string client_helper::deposit_height(const uint32_t &blockHeight) const { std::string height_str = ""; - uint64_t deposit_height = txInfo.blockHeight; - bool bad_unlock = deposit_height > cn::parameters::CRYPTONOTE_MAX_BLOCK_NUMBER; + bool bad_unlock = blockHeight > cn::parameters::CRYPTONOTE_MAX_BLOCK_NUMBER; if (bad_unlock) { height_str = "Please wait."; } else { - height_str = std::to_string(deposit_height); + height_str = std::to_string(blockHeight); } bool bad_unlock2 = height_str == "0"; @@ -111,7 +110,7 @@ namespace cn return height_str; } - std::string client_helper::get_deposit_info(const cn::Deposit &deposit, cn::DepositId did, const Currency ¤cy, const cn::WalletLegacyTransaction &txInfo) const + std::string client_helper::get_deposit_info(const cn::Deposit &deposit, cn::DepositId did, const Currency ¤cy, const uint32_t &blockHeight) const { std::stringstream full_info; @@ -119,7 +118,7 @@ namespace cn std::setw(8) << makeCenteredString(8, std::to_string(did)) << " | " << std::setw(20) << makeCenteredString(20, deposit_amount(deposit, currency)) << " | " << std::setw(20) << makeCenteredString(20, deposit_interest(deposit, currency)) << " | " << - std::setw(16) << makeCenteredString(16, deposit_unlock_height(deposit, txInfo)) << " | " << + std::setw(16) << makeCenteredString(16, deposit_unlock_height(deposit, blockHeight)) << " | " << std::setw(12) << makeCenteredString(12, deposit_status(deposit)); std::string as_str = full_info.str(); @@ -127,15 +126,15 @@ namespace cn return as_str; } - std::string client_helper::get_full_deposit_info(const cn::Deposit &deposit, cn::DepositId did, const Currency ¤cy, const cn::WalletLegacyTransaction &txInfo) const + std::string client_helper::get_full_deposit_info(const cn::Deposit &deposit, cn::DepositId did, const Currency ¤cy, const uint32_t &blockHeight) const { std::stringstream full_info; full_info << "ID: " << std::to_string(did) << "\n" << "Amount: " << deposit_amount(deposit, currency) << "\n" << "Interest: " << deposit_interest(deposit, currency) << "\n" - << "Height: " << deposit_height(txInfo) << "\n" - << "Unlock Height: " << deposit_unlock_height(deposit, txInfo) << "\n" + << "Height: " << deposit_height(blockHeight) << "\n" + << "Unlock Height: " << deposit_unlock_height(deposit, blockHeight) << "\n" << "Status: " << deposit_status(deposit) << "\n"; std::string as_str = full_info.str(); @@ -143,7 +142,7 @@ namespace cn return as_str; } - std::string client_helper::list_deposit_item(const WalletLegacyTransaction& txInfo, Deposit deposit, std::string listed_deposit, DepositId id, const Currency ¤cy) + std::string client_helper::list_deposit_item(const WalletTransaction& txInfo, const Deposit& deposit, std::string listed_deposit, DepositId id, const Currency ¤cy) const { std::string format_amount = currency.formatAmount(deposit.amount); std::string format_interest = currency.formatAmount(deposit.interest); @@ -152,8 +151,8 @@ namespace cn std::stringstream ss_id(makeCenteredString(8, std::to_string(id))); std::stringstream ss_amount(makeCenteredString(20, format_amount)); std::stringstream ss_interest(makeCenteredString(20, format_interest)); - std::stringstream ss_height(makeCenteredString(16, deposit_height(txInfo))); - std::stringstream ss_unlockheight(makeCenteredString(16, deposit_unlock_height(deposit, txInfo))); + std::stringstream ss_height(makeCenteredString(16, deposit_height(txInfo.blockHeight))); + std::stringstream ss_unlockheight(makeCenteredString(16, deposit_unlock_height(deposit, txInfo.blockHeight))); std::stringstream ss_status(makeCenteredString(12, deposit_status(deposit))); ss_id >> std::setw(8); @@ -169,7 +168,7 @@ namespace cn return listed_deposit; } - std::string client_helper::list_tx_item(const WalletLegacyTransaction& txInfo, std::string listed_tx, const Currency ¤cy) + std::string client_helper::list_tx_item(const WalletTransaction& txInfo, std::string listed_tx, const Currency ¤cy) const { std::vector extraVec = asBinaryArray(txInfo.extra); @@ -212,7 +211,7 @@ namespace cn return listed_tx; } - bool client_helper::confirm_deposit(uint64_t term, uint64_t amount, bool is_testnet, const Currency& currency, logging::LoggerRef logger) + bool client_helper::confirm_deposit(uint32_t term, uint64_t amount, bool is_testnet, const Currency ¤cy, const logging::LoggerRef &logger) const { uint64_t interest = currency.calculateInterestV3(amount, term); uint64_t min_term = is_testnet ? parameters::TESTNET_DEPOSIT_MIN_TERM_V3 : parameters::DEPOSIT_MIN_TERM_V3; @@ -244,7 +243,7 @@ namespace cn return false; } - JsonValue client_helper::buildLoggerConfiguration(logging::Level level, const std::string& logfile) + JsonValue client_helper::buildLoggerConfiguration(logging::Level level, const std::string& logfile) const { using common::JsonValue; @@ -354,9 +353,9 @@ namespace cn if (initError) throw std::runtime_error("failed to load wallet: " + initError.message()); - logger(logging::INFO) << "Saving wallet..."; - save_wallet(*wallet, walletFileName, logger); - logger(logging::INFO, logging::BRIGHT_GREEN) << "Saving successful"; + // logger(logging::INFO) << "Saving wallet..."; + // save_wallet(*wallet, walletFileName, logger); + // logger(logging::INFO, logging::BRIGHT_GREEN) << "Saving successful"; return walletFileName; } @@ -389,9 +388,9 @@ namespace cn throw std::runtime_error("failed to load wallet: " + initError.message()); } - logger(logging::INFO) << "Saving wallet..."; - save_wallet(*wallet, walletFileName, logger); - logger(logging::INFO, logging::BRIGHT_GREEN) << "Saved successful"; + // logger(logging::INFO) << "Saving wallet..."; + // save_wallet(*wallet, walletFileName, logger); + // logger(logging::INFO, logging::BRIGHT_GREEN) << "Saved successful"; return walletFileName; } @@ -401,43 +400,21 @@ namespace cn } } - void client_helper::save_wallet(cn::IWalletLegacy& wallet, const std::string& walletFilename, logging::LoggerRef& logger) - { - logger(logging::INFO) << "Saving wallet..."; - - try - { - cn::WalletHelper::storeWallet(wallet, walletFilename); - logger(logging::INFO, logging::BRIGHT_GREEN) << "Saved successful"; - } - catch (std::exception& e) - { - logger(logging::ERROR, logging::BRIGHT_RED) << "Failed to store wallet: " << e.what(); - throw std::runtime_error("error saving wallet file '" + walletFilename + "'"); - } - } - - std::stringstream client_helper::balances(std::unique_ptr& wallet, const Currency& currency) + std::stringstream client_helper::balances(const cn::IWallet &wallet, const Currency ¤cy) const { std::stringstream balances; - - uint64_t full_balance = wallet->actualBalance() + wallet->pendingBalance() + wallet->actualDepositBalance() + wallet->pendingDepositBalance(); - std::string full_balance_text = "Total Balance: " + currency.formatAmount(full_balance) + "\n"; - - uint64_t non_deposit_unlocked_balance = wallet->actualBalance(); - std::string non_deposit_unlocked_balance_text = "Available: " + currency.formatAmount(non_deposit_unlocked_balance) + "\n"; - - uint64_t non_deposit_locked_balance = wallet->pendingBalance(); - std::string non_deposit_locked_balance_text = "Locked: " + currency.formatAmount(non_deposit_locked_balance) + "\n"; - - uint64_t deposit_unlocked_balance = wallet->actualDepositBalance(); - std::string deposit_locked_balance_text = "Unlocked Balance: " + currency.formatAmount(deposit_unlocked_balance) + "\n"; - - uint64_t deposit_locked_balance = wallet->pendingDepositBalance(); - std::string deposit_unlocked_balance_text = "Locked Deposits: " + currency.formatAmount(deposit_locked_balance) + "\n"; - balances << full_balance_text << non_deposit_unlocked_balance_text << non_deposit_locked_balance_text - << deposit_unlocked_balance_text << deposit_locked_balance_text; + uint64_t actualBalance = wallet.getActualBalance(); + uint64_t pendingBalance = wallet.getPendingBalance(); + uint64_t unlockedDepositBalance = wallet.getUnlockedDepositBalance(); + uint64_t lockedDepositBalance = wallet.getLockedDepositBalance(); + + uint64_t totalBalance = actualBalance + pendingBalance + unlockedDepositBalance + lockedDepositBalance; + balances << "Total Balance: " + currency.formatAmount(totalBalance) << std::endl + << "Available: " + currency.formatAmount(actualBalance) << std::endl + << "Locked: " + currency.formatAmount(pendingBalance) << std::endl + << "Unlocked Balance: " + currency.formatAmount(unlockedDepositBalance) << std::endl + << "Locked Deposits: " + currency.formatAmount(lockedDepositBalance); return balances; } diff --git a/src/ConcealWallet/ClientHelper.h b/src/ConcealWallet/ClientHelper.h index c94af5daf..26e057150 100644 --- a/src/ConcealWallet/ClientHelper.h +++ b/src/ConcealWallet/ClientHelper.h @@ -55,42 +55,42 @@ namespace cn /** * @return - returns unlock height from transaction blockheight + deposit term **/ - std::string deposit_unlock_height(const cn::Deposit &deposit, const cn::WalletLegacyTransaction &txInfo) const; + std::string deposit_unlock_height(const cn::Deposit &deposit, const uint32_t &blockHeight) const; /** * @return - returns deposit height **/ - std::string deposit_height(const cn::WalletLegacyTransaction &txInfo) const; + std::string deposit_height(const uint32_t &blockHeight) const; /** * @return - returns deposit info string for client output **/ - std::string get_deposit_info(const cn::Deposit &deposit, cn::DepositId did, const Currency ¤cy, const cn::WalletLegacyTransaction &txInfo) const; + std::string get_deposit_info(const cn::Deposit &deposit, cn::DepositId did, const Currency ¤cy, const uint32_t &blockHeight) const; /** * @return - returns full deposit info string for client output **/ - std::string get_full_deposit_info(const cn::Deposit &deposit, cn::DepositId did, const Currency ¤cy, const cn::WalletLegacyTransaction &txInfo) const; + std::string get_full_deposit_info(const cn::Deposit &deposit, cn::DepositId did, const Currency ¤cy, const uint32_t &blockHeight) const; /** * @return - returns deposit info string for file output **/ - std::string list_deposit_item(const WalletLegacyTransaction& txInfo, const Deposit deposit, std::string listed_deposit, DepositId id, const Currency ¤cy); + std::string list_deposit_item(const WalletTransaction& txInfo, const Deposit& deposit, std::string listed_deposit, DepositId id, const Currency ¤cy) const; /** * @return - returns transaction info string for file output **/ - std::string list_tx_item(const WalletLegacyTransaction& txInfo, std::string listed_tx, const Currency ¤cy); + std::string list_tx_item(const WalletTransaction& txInfo, std::string listed_tx, const Currency ¤cy) const; /** * @return - returns false if user rejects deposit */ - bool confirm_deposit(uint64_t term, uint64_t amount, bool is_testnet, const Currency& currency, logging::LoggerRef logger); + bool confirm_deposit(uint32_t term, uint64_t amount, bool is_testnet, const Currency& currency, const logging::LoggerRef& logger) const; /** * @return - returns logging config for file and client output */ - JsonValue buildLoggerConfiguration(logging::Level level, const std::string& logfile); + JsonValue buildLoggerConfiguration(logging::Level level, const std::string& logfile) const; /** * @return - returns a formatted url address @@ -101,11 +101,9 @@ namespace cn std::string tryToOpenWalletOrLoadKeysOrThrow(logging::LoggerRef& logger, std::unique_ptr& wallet, const std::string& walletFile, const std::string& password); - void save_wallet(cn::IWalletLegacy& wallet, const std::string& walletFilename, logging::LoggerRef& logger); - /** * @return - Displays all balances (main + deposits) */ - std::stringstream balances(std::unique_ptr& wallet, const Currency& currency); + std::stringstream balances(const cn::IWallet &wallet, const Currency ¤cy) const; }; } \ No newline at end of file diff --git a/src/ConcealWallet/ConcealWallet.cpp b/src/ConcealWallet/ConcealWallet.cpp index 161c0e8c5..92d44cdf1 100644 --- a/src/ConcealWallet/ConcealWallet.cpp +++ b/src/ConcealWallet/ConcealWallet.cpp @@ -42,9 +42,7 @@ #include "Wallet/WalletRpcServer.h" #include "Wallet/WalletUtils.h" -#include "WalletLegacy/WalletLegacy.h" #include "Wallet/LegacyKeysImporter.h" -#include "WalletLegacy/WalletHelper.h" #include "version.h" @@ -101,7 +99,7 @@ void printListDepositsHeader(LoggerRef& logger) { logger(INFO) << std::string(header.size(), '='); } -void printListTransfersItem(LoggerRef& logger, const WalletLegacyTransaction& txInfo, IWalletLegacy& wallet, const Currency& currency) { +void printListTransfersItem(LoggerRef& logger, const WalletTransaction& txInfo, IWallet& wallet, const Currency& currency, size_t transactionIndex) { std::vector extraVec = common::asBinaryArray(txInfo.extra); crypto::Hash paymentId; @@ -134,12 +132,14 @@ void printListTransfersItem(LoggerRef& logger, const WalletLegacyTransaction& tx logger(INFO, rowColor) << "payment ID: " << paymentIdStr; } - if (txInfo.totalAmount < 0) { - if (txInfo.transferCount > 0) { + if (txInfo.totalAmount < 0) + { + if (wallet.getTransactionTransferCount(transactionIndex) > 0) + { logger(INFO, rowColor) << "transfers:"; - for (TransferId id = txInfo.firstTransferId; id < txInfo.firstTransferId + txInfo.transferCount; ++id) { - WalletLegacyTransfer tr; - wallet.getTransfer(id, tr); + for (size_t id = 0; id < wallet.getTransactionTransferCount(transactionIndex); ++id) + { + WalletTransfer tr = wallet.getTransactionTransfer(transactionIndex, id); logger(INFO, rowColor) << tr.address << " " << std::setw(TOTAL_AMOUNT_MAX_WIDTH) << currency.formatAmount(tr.amount); } } @@ -216,7 +216,7 @@ bool splitUrlToHostAndUri(const std::string& aliasUrl, std::string& host, std::s return true; } -bool askAliasesTransfersConfirmation(const std::map>& aliases, const Currency& currency) { +bool askAliasesTransfersConfirmation(const std::map>& aliases, const Currency& currency) { std::cout << "Would you like to send money to the following addresses?" << std::endl; for (const auto& kv: aliases) { @@ -287,13 +287,15 @@ bool conceal_wallet::extended_help(const std::vector &args/* = std: return true; } -bool conceal_wallet::exit(const std::vector &args) { - m_consoleHandler.requestStop(); +bool conceal_wallet::exit(const std::vector &args) +{ + stop(); return true; } conceal_wallet::conceal_wallet(platform_system::Dispatcher& dispatcher, const cn::Currency& currency, logging::LoggerManager& log) : m_dispatcher(dispatcher), + m_stopEvent(m_dispatcher), m_daemon_port(0), m_currency(currency), logManager(log), @@ -384,9 +386,10 @@ std::string conceal_wallet::wallet_menu(bool do_ext) /* This function shows the number of outputs in the wallet that are below the dust threshold */ -bool conceal_wallet::show_dust(const std::vector& args) { - logger(INFO, BRIGHT_WHITE) << "Dust outputs: " << m_wallet->dustBalance() << std::endl; - return true; +bool conceal_wallet::show_dust(const std::vector &) +{ + logger(INFO, BRIGHT_WHITE) << "Dust outputs: " << m_wallet->getDustBalance(); + return true; } //---------------------------------------------------------------------------------------------------- @@ -546,18 +549,9 @@ bool conceal_wallet::init(const boost::program_options::variables_map& vm) { } this->m_node.reset(new NodeRpcProxy(m_daemon_host, m_daemon_port)); - - std::promise errorPromise; - std::future f_error = errorPromise.get_future(); - auto callback = [&errorPromise](std::error_code e) {errorPromise.set_value(e); }; - - m_node->addObserver(static_cast(this)); - m_node->init(callback); - auto error = f_error.get(); - if (error) { - fail_msg_writer() << "failed to init NodeRPCProxy: " << error.message(); - return false; - } + NodeInitObserver initObserver; + m_node->init(std::bind(&NodeInitObserver::initCompleted, &initObserver, std::placeholders::_1)); + initObserver.waitForInitEnd(); if (!m_generate_new.empty()) { std::string walletAddressFile = prepareWalletAddressFilename(m_generate_new); @@ -572,7 +566,8 @@ bool conceal_wallet::init(const boost::program_options::variables_map& vm) { return false; } - if (!writeAddressFile(walletAddressFile, m_wallet->getAddress())) { + if (!writeAddressFile(walletAddressFile, m_wallet->getAddress(0))) + { logger(WARNING, BRIGHT_RED) << "Couldn't write wallet address file: " + walletAddressFile; } } else if (!m_import_new.empty()) { @@ -641,45 +636,42 @@ bool conceal_wallet::init(const boost::program_options::variables_map& vm) { return false; } - if (!writeAddressFile(walletAddressFile, m_wallet->getAddress())) { + if (!writeAddressFile(walletAddressFile, m_wallet->getAddress(0))) + { logger(WARNING, BRIGHT_RED) << "Couldn't write wallet address file: " + walletAddressFile; } - } else { - m_wallet.reset(new WalletLegacy(m_currency, *m_node, logManager, m_testnet)); + } else { + m_wallet.reset(new WalletGreen(m_dispatcher, m_currency, *m_node, logManager)); - try { - m_wallet_file = m_chelper.tryToOpenWalletOrLoadKeysOrThrow(logger, m_wallet, m_wallet_file_arg, pwd_container.password()); - } catch (const std::exception& e) { + try + { + m_wallet->load(m_wallet_file_arg, pwd_container.password()); + m_wallet_file = m_wallet_file_arg; + success_msg_writer(true) << "Wallet loaded"; + } + catch (const std::exception &e) + { fail_msg_writer() << "failed to load wallet: " << e.what(); return false; } - m_wallet->addObserver(this); - m_node->addObserver(static_cast(this)); - - std::string tmp_str = m_wallet_file; - m_frmt_wallet_file = tmp_str.erase(tmp_str.size() - 7); - - logger(INFO, BRIGHT_WHITE) << "Opened wallet: " << m_wallet->getAddress(); - success_msg_writer() << "**********************************************************************\n" << "Use \"help\" command to see the list of available commands.\n" << "**********************************************************************"; } - + m_wallet->addObserver(this); return true; } //---------------------------------------------------------------------------------------------------- -bool conceal_wallet::deinit() { +bool conceal_wallet::deinit() +{ m_wallet->removeObserver(this); - m_node->removeObserver(static_cast(this)); - m_node->removeObserver(static_cast(this)); - if (!m_wallet.get()) + { return true; - + } return close_wallet(); } //---------------------------------------------------------------------------------------------------- @@ -703,34 +695,19 @@ void conceal_wallet::handle_command_line(const boost::program_options::variables bool conceal_wallet::new_wallet(const std::string &wallet_file, const std::string& password) { m_wallet_file = wallet_file; - m_wallet.reset(new WalletLegacy(m_currency, *m_node, logManager, m_testnet)); - m_node->addObserver(static_cast(this)); - m_wallet->addObserver(this); + m_wallet.reset(new WalletGreen(m_dispatcher, m_currency, *m_node, logManager)); try { - m_initResultPromise.reset(new std::promise()); - std::future f_initError = m_initResultPromise->get_future(); - m_wallet->initAndGenerate(password); - auto initError = f_initError.get(); - m_initResultPromise.reset(nullptr); - if (initError) { - fail_msg_writer() << "failed to generate new wallet: " << initError.message(); - return false; - } - - m_chelper.save_wallet(*m_wallet, m_wallet_file, logger); - - AccountKeys keys; - m_wallet->getAccountKeys(keys); - - std::string secretKeysData = std::string(reinterpret_cast(&keys.spendSecretKey), sizeof(keys.spendSecretKey)) + std::string(reinterpret_cast(&keys.viewSecretKey), sizeof(keys.viewSecretKey)); - std::string guiKeys = tools::base_58::encode_addr(cn::parameters::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX, secretKeysData); + m_wallet->generateNewWallet(wallet_file, password); + KeyPair viewKey = m_wallet->getViewKey(); + KeyPair spendKey = m_wallet->getAddressSpendKey(0); + logger(INFO, BRIGHT_GREEN) << "ConcealWallet is an open-source, client-side, free wallet which allow you to send and receive CCX instantly on the blockchain. You are in control of your funds & your keys. When you generate a new wallet, login, send, receive or deposit $CCX everything happens locally. Your seed is never transmitted, received or stored. That's why its imperative to write, print or save your seed somewhere safe. The backup of keys is your responsibility. If you lose your seed, your account can not be recovered. The Conceal Team doesn't take any responsibility for lost funds due to nonexistent/missing/lost private keys." << std::endl << std::endl; - std::cout << "Wallet Address: " << m_wallet->getAddress() << std::endl; - std::cout << "Private spend key: " << common::podToHex(keys.spendSecretKey) << std::endl; - std::cout << "Private view key: " << common::podToHex(keys.viewSecretKey) << std::endl; - std::cout << "Mnemonic Seed: " << mnemonics::privateKeyToMnemonic(keys.spendSecretKey) << std::endl; + std::cout << "Wallet Address: " << m_wallet->getAddress(0) << std::endl; + std::cout << "Private spend key: " << common::podToHex(spendKey.secretKey) << std::endl; + std::cout << "Private view key: " << common::podToHex(viewKey.secretKey) << std::endl; + std::cout << "Mnemonic Seed: " << mnemonics::privateKeyToMnemonic(spendKey.secretKey) << std::endl; } catch (const std::exception& e) { fail_msg_writer() << "failed to generate new wallet: " << e.what(); @@ -748,39 +725,16 @@ bool conceal_wallet::new_wallet(const std::string &wallet_file, const std::strin return true; } //---------------------------------------------------------------------------------------------------- -bool conceal_wallet::new_wallet(crypto::SecretKey &secret_key, crypto::SecretKey &view_key, const std::string &wallet_file, const std::string& password) { +bool conceal_wallet::new_wallet(const crypto::SecretKey &secret_key, const crypto::SecretKey &view_key, const std::string &wallet_file, const std::string& password) { m_wallet_file = wallet_file; - m_wallet.reset(new WalletLegacy(m_currency, *m_node.get(), logManager, m_testnet)); - m_node->addObserver(static_cast(this)); - m_wallet->addObserver(this); + m_wallet.reset(new WalletGreen(m_dispatcher, m_currency, *m_node, logManager)); try { - m_initResultPromise.reset(new std::promise()); - std::future f_initError = m_initResultPromise->get_future(); - - AccountKeys wallet_keys; - wallet_keys.spendSecretKey = secret_key; - wallet_keys.viewSecretKey = view_key; - crypto::secret_key_to_public_key(wallet_keys.spendSecretKey, wallet_keys.address.spendPublicKey); - crypto::secret_key_to_public_key(wallet_keys.viewSecretKey, wallet_keys.address.viewPublicKey); - - m_wallet->initWithKeys(wallet_keys, password); - auto initError = f_initError.get(); - m_initResultPromise.reset(nullptr); - if (initError) { - fail_msg_writer() << "failed to generate new wallet: " << initError.message(); - return false; - } - - m_chelper.save_wallet(*m_wallet, m_wallet_file, logger); - - AccountKeys keys; - m_wallet->getAccountKeys(keys); - - logger(INFO, BRIGHT_WHITE) << - "Imported wallet: " << m_wallet->getAddress() << std::endl; + m_wallet->initializeWithViewKey(wallet_file, password, view_key); + std::string address = m_wallet->createAddress(secret_key); + logger(INFO, BRIGHT_WHITE) << "Imported wallet: " << address << std::endl; } catch (const std::exception& e) { @@ -802,7 +756,7 @@ bool conceal_wallet::new_wallet(crypto::SecretKey &secret_key, crypto::SecretKey //---------------------------------------------------------------------------------------------------- bool conceal_wallet::close_wallet() { - m_chelper.save_wallet(*m_wallet, m_wallet_file, logger); + m_wallet->save(); logger(logging::INFO, logging::BRIGHT_GREEN) << "Closing wallet..."; m_wallet->removeObserver(this); @@ -812,25 +766,27 @@ bool conceal_wallet::close_wallet() } //---------------------------------------------------------------------------------------------------- -bool conceal_wallet::save(const std::vector &args) +bool conceal_wallet::save(const std::vector &) { - m_chelper.save_wallet(*m_wallet, m_wallet_file, logger); + m_wallet->save(); return true; } -bool conceal_wallet::reset(const std::vector &args) { +bool conceal_wallet::reset(const std::vector &) +{ + m_wallet->removeObserver(this); { std::unique_lock lock(m_walletSynchronizedMutex); m_walletSynchronized = false; } - m_wallet->reset(); + m_wallet->reset(0); + m_wallet->addObserver(this); success_msg_writer(true) << "Reset completed successfully."; std::unique_lock lock(m_walletSynchronizedMutex); - while (!m_walletSynchronized) { - m_walletSynchronizedCV.wait(lock); - } + m_walletSynchronizedCV.wait(lock, [this] + { return m_walletSynchronized; }); std::cout << std::endl; @@ -852,13 +808,13 @@ bool conceal_wallet::get_reserve_proof(const std::vector &args) return true; } } else { - reserve = m_wallet->actualBalance(); + reserve = m_wallet->getActualBalance(); } try { - const std::string sig_str = m_wallet->getReserveProof(reserve, args.size() == 2 ? args[1] : ""); + const std::string sig_str = m_wallet->getReserveProof(m_wallet->getAddress(0), reserve, args.size() == 2 ? args[1] : ""); - //logger(INFO, BRIGHT_WHITE) << "\n\n" << sig_str << "\n\n" << std::endl; + logger(INFO, BRIGHT_WHITE) << "\n\n" << sig_str << "\n\n" << std::endl; const std::string filename = "balance_proof_" + args[0] + "_CCX.txt"; boost::system::error_code ec; @@ -904,104 +860,67 @@ bool conceal_wallet::get_tx_proof(const std::vector &args) } std::string sig_str; - crypto::SecretKey tx_key, tx_key2; - bool r = m_wallet->get_tx_key(txid, tx_key); + crypto::SecretKey tx_key = m_wallet->getTransactionDeterministicSecretKey(txid); + bool r = tx_key != NULL_SECRET_KEY; + crypto::SecretKey tx_key2; - if (args.size() == 3) { + if (args.size() == 3) + { crypto::Hash tx_key_hash; size_t size; - if (!common::fromHex(args[2], &tx_key_hash, sizeof(tx_key_hash), size) || size != sizeof(tx_key_hash)) { + if (!common::fromHex(args[2], &tx_key_hash, sizeof(tx_key_hash), size) || size != sizeof(tx_key_hash)) + { fail_msg_writer() << "failed to parse tx_key"; return true; } - tx_key2 = *(struct crypto::SecretKey *) &tx_key_hash; + tx_key2 = *(struct crypto::SecretKey *)&tx_key_hash; - if (r) { - if (args.size() == 3 && tx_key != tx_key2) { - fail_msg_writer() << "Tx secret key was found for the given txid, but you've also provided another tx secret key which doesn't match the found one."; - return true; - } - } - tx_key = tx_key2; - } else { - if (!r) { - fail_msg_writer() << "Tx secret key wasn't found in the wallet file. Provide it as the optional third parameter if you have it elsewhere."; + if (r && args.size() == 3 && tx_key != tx_key2) + { + fail_msg_writer() << "Tx secret key was found for the given txid, but you've also provided another tx secret key which doesn't match the found one."; return true; } + + tx_key = tx_key2; + } + else if (!r) + { + fail_msg_writer() << "Tx secret key wasn't found in the wallet file. Provide it as the optional third parameter if you have it elsewhere."; + return true; } - if (m_wallet->getTxProof(txid, address, tx_key, sig_str)) { + if (m_wallet->getTxProof(txid, address, tx_key, sig_str)) + { success_msg_writer() << "Signature: " << sig_str << std::endl; } return true; } -//---------------------------------------------------------------------------------------------------- -void conceal_wallet::initCompleted(std::error_code result) { - if (m_initResultPromise.get() != nullptr) { - m_initResultPromise->set_value(result); - } -} -//---------------------------------------------------------------------------------------------------- -void conceal_wallet::connectionStatusUpdated(bool connected) { - if (connected) { - logger(INFO, GREEN) << "Wallet connected to daemon."; - } else { - printConnectionError(); - } -} -//---------------------------------------------------------------------------------------------------- -void conceal_wallet::externalTransactionCreated(cn::TransactionId transactionId) { - WalletLegacyTransaction txInfo; - m_wallet->getTransaction(transactionId, txInfo); - - std::stringstream logPrefix; - if (txInfo.blockHeight == WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT) { - logPrefix << "Unconfirmed"; - } else { - logPrefix << "Height " << txInfo.blockHeight << ','; - } - - if (txInfo.totalAmount >= 0) { - logger(INFO, GREEN) << - logPrefix.str() << " transaction " << common::podToHex(txInfo.hash) << - ", received " << m_currency.formatAmount(txInfo.totalAmount); - } else { - logger(INFO, MAGENTA) << - logPrefix.str() << " transaction " << common::podToHex(txInfo.hash) << - ", spent " << m_currency.formatAmount(static_cast(-txInfo.totalAmount)); - } - - if (txInfo.blockHeight == WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT) { - m_refresh_progress_reporter.update(m_node->getLastLocalBlockHeight(), true); - } else { - m_refresh_progress_reporter.update(txInfo.blockHeight, true); - } -} -//---------------------------------------------------------------------------------------------------- -void conceal_wallet::synchronizationCompleted(std::error_code result) { +void conceal_wallet::synchronizationCompleted(std::error_code result) +{ std::unique_lock lock(m_walletSynchronizedMutex); m_walletSynchronized = true; m_walletSynchronizedCV.notify_one(); } -void conceal_wallet::synchronizationProgressUpdated(uint32_t current, uint32_t total) { +void conceal_wallet::synchronizationProgressUpdated(uint32_t processedBlockCount, uint32_t totalBlockCount) +{ std::unique_lock lock(m_walletSynchronizedMutex); - if (!m_walletSynchronized) { - m_refresh_progress_reporter.update(current, false); + if (!m_walletSynchronized) + { + m_refresh_progress_reporter.update(processedBlockCount, false); } } -bool conceal_wallet::show_balance(const std::vector& args/* = std::vector()*/) +bool conceal_wallet::show_balance(const std::vector &args) { if (!args.empty()) { logger(ERROR) << "Usage: balance"; return true; } - - std::stringstream balances = m_chelper.balances(m_wallet, m_currency); + std::stringstream balances = m_chelper.balances(*m_wallet, m_currency); logger(INFO) << balances.str(); return true; @@ -1015,13 +934,12 @@ bool conceal_wallet::sign_message(const std::vector& args) return true; } - AccountKeys keys; - m_wallet->getAccountKeys(keys); + KeyPair keys = m_wallet->getAddressSpendKey(0); crypto::Hash message_hash; crypto::Signature sig; crypto::cn_fast_hash(args[0].data(), args[0].size(), message_hash); - crypto::generate_signature(message_hash, keys.address.spendPublicKey, keys.spendSecretKey, sig); + crypto::generate_signature(message_hash, keys.publicKey, keys.secretKey, sig); success_msg_writer() << "Sig" << tools::base_58::encode(std::string(reinterpret_cast(&sig))); @@ -1070,7 +988,7 @@ bool conceal_wallet::verify_signature(const std::vector& args) /* CREATE INTEGRATED ADDRESS */ /* take a payment Id as an argument and generate an integrated wallet address */ -bool conceal_wallet::create_integrated(const std::vector& args/* = std::vector()*/) +bool conceal_wallet::create_integrated(const std::vector& args) { /* check if there is a payment id */ @@ -1089,7 +1007,7 @@ bool conceal_wallet::create_integrated(const std::vector& args/* = return true; } - std::string address = m_wallet->getAddress(); + std::string address = m_wallet->getAddress(0); uint64_t prefix; cn::AccountPublicAddress addr; @@ -1116,48 +1034,32 @@ bool conceal_wallet::create_integrated(const std::vector& args/* = /* ---------------------------------------------------------------------------------------- */ - -bool conceal_wallet::export_keys(const std::vector& args/* = std::vector()*/) { - AccountKeys keys; - m_wallet->getAccountKeys(keys); - - std::string secretKeysData = std::string(reinterpret_cast(&keys.spendSecretKey), sizeof(keys.spendSecretKey)) + std::string(reinterpret_cast(&keys.viewSecretKey), sizeof(keys.viewSecretKey)); - std::string guiKeys = tools::base_58::encode_addr(cn::parameters::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX, secretKeysData); - - logger(INFO, BRIGHT_GREEN) << std::endl << "ConcealWallet is an open-source, client-side, free wallet which allow you to send and receive CCX instantly on the blockchain. You are in control of your funds & your keys. When you generate a new wallet, login, send, receive or deposit $CCX everything happens locally. Your seed is never transmitted, received or stored. That's why its imperative to write, print or save your seed somewhere safe. The backup of keys is your responsibility. If you lose your seed, your account can not be recovered. The Conceal Team doesn't take any responsibility for lost funds due to nonexistent/missing/lost private keys." << std::endl << std::endl; - - std::cout << "Private spend key: " << common::podToHex(keys.spendSecretKey) << std::endl; - std::cout << "Private view key: " << common::podToHex(keys.viewSecretKey) << std::endl; - - crypto::PublicKey unused_dummy_variable; - crypto::SecretKey deterministic_private_view_key; - - AccountBase::generateViewFromSpend(keys.spendSecretKey, deterministic_private_view_key, unused_dummy_variable); - - bool deterministic_private_keys = deterministic_private_view_key == keys.viewSecretKey; - - /* dont show a mnemonic seed if it is an old non-deterministic wallet */ - if (deterministic_private_keys) { - std::cout << "Mnemonic seed: " << mnemonics::privateKeyToMnemonic(keys.spendSecretKey) << std::endl << std::endl; - } - +bool conceal_wallet::export_keys(const std::vector &) +{ + std::cout << get_wallet_keys(); return true; } //---------------------------------------------------------------------------------------------------- -bool conceal_wallet::show_incoming_transfers(const std::vector& args) { +bool conceal_wallet::show_incoming_transfers(const std::vector &) +{ bool hasTransfers = false; size_t transactionsCount = m_wallet->getTransactionCount(); - for (size_t trantransactionNumber = 0; trantransactionNumber < transactionsCount; ++trantransactionNumber) { - WalletLegacyTransaction txInfo; - m_wallet->getTransaction(trantransactionNumber, txInfo); - if (txInfo.totalAmount < 0) continue; + for (size_t trantransactionNumber = 0; trantransactionNumber < transactionsCount; ++trantransactionNumber) + { + WalletTransaction txInfo = m_wallet->getTransaction(trantransactionNumber); + if (txInfo.totalAmount < 0) + { + continue; + } hasTransfers = true; logger(INFO) << " amount \t tx id"; - logger(INFO, GREEN) << - std::setw(21) << m_currency.formatAmount(txInfo.totalAmount) << '\t' << common::podToHex(txInfo.hash); + logger(INFO, GREEN) << std::setw(21) << m_currency.formatAmount(txInfo.totalAmount) << '\t' << common::podToHex(txInfo.hash); } - if (!hasTransfers) success_msg_writer() << "No incoming transfers"; + if (!hasTransfers) + { + success_msg_writer() << "No incoming transfers"; + } return true; } @@ -1166,8 +1068,6 @@ bool conceal_wallet::listTransfers(const std::vector& args) { bool haveBlockHeight = false; std::string blockHeightString = ""; uint32_t blockHeight = 0; - WalletLegacyTransaction txInfo; - /* get block height from arguments */ if (args.empty()) @@ -1180,11 +1080,11 @@ bool conceal_wallet::listTransfers(const std::vector& args) { } size_t transactionsCount = m_wallet->getTransactionCount(); - for (size_t trantransactionNumber = 0; trantransactionNumber < transactionsCount; ++trantransactionNumber) + for (size_t transactionIndex = 0; transactionIndex < transactionsCount; ++transactionIndex) { - m_wallet->getTransaction(trantransactionNumber, txInfo); - if (txInfo.state != WalletLegacyTransactionState::Active || txInfo.blockHeight == WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT) { + WalletTransaction transaction = m_wallet->getTransaction(transactionIndex); + if (transaction.state != WalletTransactionState::SUCCEEDED || transaction.blockHeight == WALLET_UNCONFIRMED_TRANSACTION_HEIGHT) { continue; } @@ -1194,10 +1094,10 @@ bool conceal_wallet::listTransfers(const std::vector& args) { } if (haveBlockHeight == false) { - printListTransfersItem(logger, txInfo, *m_wallet, m_currency); + printListTransfersItem(logger, transaction, *m_wallet, m_currency, transactionIndex); } else { - if (txInfo.blockHeight >= blockHeight) { - printListTransfersItem(logger, txInfo, *m_wallet, m_currency); + if (transaction.blockHeight >= blockHeight) { + printListTransfersItem(logger, transaction, *m_wallet, m_currency, transactionIndex); } @@ -1238,8 +1138,8 @@ bool conceal_wallet::show_payments(const std::vector &args) { auto payments = m_wallet->getTransactionsByPaymentIds(paymentIds); - for (auto& payment : payments) { - for (auto& transaction : payment.transactions) { + for (const auto& payment : payments) { + for (const auto& transaction : payment.transactions) { success_msg_writer(true) << common::podToHex(payment.paymentId) << '\t' << common::podToHex(transaction.hash) << '\t' << @@ -1269,59 +1169,45 @@ bool conceal_wallet::show_blockchain_height(const std::vector& args return true; } //---------------------------------------------------------------------------------------------------- -bool conceal_wallet::show_num_unlocked_outputs(const std::vector& args) { - try { +bool conceal_wallet::show_num_unlocked_outputs(const std::vector &) +{ + try + { std::vector unlocked_outputs = m_wallet->getUnspentOutputs(); success_msg_writer() << "Count: " << unlocked_outputs.size(); - for (const auto& out : unlocked_outputs) { + for (const auto &out : unlocked_outputs) + { success_msg_writer() << "Key: " << out.transactionPublicKey << " amount: " << m_currency.formatAmount(out.amount); } - } catch (std::exception &e) { + } + catch (std::exception &e) + { fail_msg_writer() << "failed to get outputs: " << e.what(); } - return true; } //---------------------------------------------------------------------------------------------------- bool conceal_wallet::optimize_outputs(const std::vector& args) { - try { - cn::WalletHelper::SendCompleteResultObserver sent; - WalletHelper::IWalletRemoveObserverGuard removeGuard(*m_wallet, sent); - - std::vector transfers; - std::vector messages; - std::string extraString; - uint64_t fee = cn::parameters::MINIMUM_FEE_V2; - uint64_t mixIn = 0; - uint64_t unlockTimestamp = 0; - uint64_t ttl = 0; - crypto::SecretKey transactionSK; - cn::TransactionId tx = m_wallet->sendTransaction(transactionSK, transfers, fee, extraString, mixIn, unlockTimestamp, messages, ttl); - if (tx == WALLET_LEGACY_INVALID_TRANSACTION_ID) { + try + { + cn::TransactionId tx = m_wallet->createOptimizationTransaction(m_wallet->getAddress(0)); + if (tx == WALLET_INVALID_TRANSACTION_ID) + { fail_msg_writer() << "Can't send money"; - return true; - } - - std::error_code sendError = sent.wait(tx); - removeGuard.removeObserver(); - - if (sendError) { - fail_msg_writer() << sendError.message(); - return true; + return false; } - - cn::WalletLegacyTransaction txInfo; - m_wallet->getTransaction(tx, txInfo); + cn::WalletTransaction txInfo = m_wallet->getTransaction(tx); success_msg_writer(true) << "Money successfully sent, transaction " << common::podToHex(txInfo.hash); - success_msg_writer(true) << "Transaction secret key " << common::podToHex(transactionSK); - - m_chelper.save_wallet(*m_wallet, m_wallet_file, logger); - } catch (const std::system_error& e) { + } + catch (const std::system_error &e) + { fail_msg_writer() << e.what(); - } catch (const std::exception& e) { + return false; + } + catch (const std::exception &e) + { fail_msg_writer() << e.what(); - } catch (...) { - fail_msg_writer() << "unknown error"; + return false; } return true; @@ -1335,56 +1221,17 @@ bool conceal_wallet::optimize_all_outputs(const std::vector& args) uint64_t num_unlocked_outputs = 0; try { - num_unlocked_outputs = m_wallet->getNumUnlockedOutputs(); + num_unlocked_outputs = m_wallet->getUnspentOutputsCount(); success_msg_writer() << "Total outputs: " << num_unlocked_outputs; } catch (std::exception &e) { fail_msg_writer() << "failed to get outputs: " << e.what(); } - uint64_t remainder = num_unlocked_outputs % 100; - uint64_t rounds = (num_unlocked_outputs - remainder) / 100; - success_msg_writer() << "Total optimization rounds: " << rounds; - for(uint64_t a = 1; a < rounds; a = a + 1 ) { - - try { - cn::WalletHelper::SendCompleteResultObserver sent; - WalletHelper::IWalletRemoveObserverGuard removeGuard(*m_wallet, sent); - - std::vector transfers; - std::vector messages; - std::string extraString; - uint64_t fee = cn::parameters::MINIMUM_FEE_V2; - uint64_t mixIn = 0; - uint64_t unlockTimestamp = 0; - uint64_t ttl = 0; - crypto::SecretKey transactionSK; - cn::TransactionId tx = m_wallet->sendTransaction(transactionSK, transfers, fee, extraString, mixIn, unlockTimestamp, messages, ttl); - if (tx == WALLET_LEGACY_INVALID_TRANSACTION_ID) { - fail_msg_writer() << "Can't send money"; - return true; - } - - std::error_code sendError = sent.wait(tx); - removeGuard.removeObserver(); - - if (sendError) { - fail_msg_writer() << sendError.message(); - return true; - } - - cn::WalletLegacyTransaction txInfo; - m_wallet->getTransaction(tx, txInfo); - success_msg_writer(true) << a << ". Optimization transaction successfully sent, transaction " << common::podToHex(txInfo.hash); - - m_chelper.save_wallet(*m_wallet, m_wallet_file, logger); - } catch (const std::system_error& e) { - fail_msg_writer() << e.what(); - } catch (const std::exception& e) { - fail_msg_writer() << e.what(); - } catch (...) { - fail_msg_writer() << "unknown error"; - } + bool success = true; + while (success && m_wallet->getUnspentOutputsCount() > 100) + { + success = optimize_outputs({}); } return true; } @@ -1482,16 +1329,18 @@ bool conceal_wallet::transfer(const std::vector &args) { } for (auto& kv: cmd.aliases) { - std::copy(std::move_iterator::iterator>(kv.second.begin()), - std::move_iterator::iterator>(kv.second.end()), + std::copy(std::move_iterator::iterator>(kv.second.begin()), + std::move_iterator::iterator>(kv.second.end()), std::back_inserter(cmd.dsts)); } } - std::vector messages; - for (auto dst : cmd.dsts) { - for (auto msg : cmd.messages) { - messages.emplace_back(TransactionMessage{ msg, dst.address }); + std::vector messages; + for (const auto &dst : cmd.dsts) + { + for (const auto &msg : cmd.messages) + { + messages.emplace_back(WalletMessage{dst.address, msg}); } } @@ -1505,9 +1354,6 @@ bool conceal_wallet::transfer(const std::vector &args) { std::string extraString; std::copy(cmd.extra.begin(), cmd.extra.end(), std::back_inserter(extraString)); - WalletHelper::IWalletRemoveObserverGuard removeGuard(*m_wallet, sent); - - /* set static mixin of 4*/ cmd.fake_outs_count = cn::parameters::MINIMUM_MIXIN; /* force minimum fee */ @@ -1515,27 +1361,19 @@ bool conceal_wallet::transfer(const std::vector &args) { cmd.fee = cn::parameters::MINIMUM_FEE_V2; } - crypto::SecretKey transactionSK; - cn::TransactionId tx = m_wallet->sendTransaction(transactionSK, cmd.dsts, cmd.fee, extraString, cmd.fake_outs_count, 0, messages, ttl); - if (tx == WALLET_LEGACY_INVALID_TRANSACTION_ID) { - fail_msg_writer() << "Can't send money"; - return true; - } + cn::TransactionParameters sendParams; + sendParams.destinations = cmd.dsts; + sendParams.messages = messages; + sendParams.extra = extraString; + sendParams.unlockTimestamp = ttl; + sendParams.changeDestination = m_wallet->getAddress(0); - std::error_code sendError = sent.wait(tx); - removeGuard.removeObserver(); - - if (sendError) { - fail_msg_writer() << sendError.message(); - return true; - } + crypto::SecretKey transactionSK; + size_t transactionId = m_wallet->transfer(sendParams, transactionSK); - cn::WalletLegacyTransaction txInfo; - m_wallet->getTransaction(tx, txInfo); + cn::WalletTransaction txInfo = m_wallet->getTransaction(transactionId); success_msg_writer(true) << "Money successfully sent, transaction hash: " << common::podToHex(txInfo.hash); - success_msg_writer(true) << "Transaction secret key " << common::podToHex(transactionSK); - - m_chelper.save_wallet(*m_wallet, m_wallet_file, logger); + success_msg_writer(true) << "Transaction secret key " << common::podToHex(transactionSK); } catch (const std::system_error& e) { fail_msg_writer() << e.what(); } catch (const std::exception& e) { @@ -1547,27 +1385,35 @@ bool conceal_wallet::transfer(const std::vector &args) { return true; } //---------------------------------------------------------------------------------------------------- -bool conceal_wallet::run() { +bool conceal_wallet::run() +{ { std::unique_lock lock(m_walletSynchronizedMutex); - while (!m_walletSynchronized) { - m_walletSynchronizedCV.wait(lock); + while (!m_walletSynchronized) + { + m_walletSynchronizedCV.wait(lock, [this] + { return m_walletSynchronized; }); } } std::cout << std::endl; - std::string addr_start = m_wallet->getAddress().substr(0, 10); - m_consoleHandler.start(false, "[" + addr_start + "]: ", common::console::Color::BrightYellow); + std::string addr_start = m_wallet->getAddress(0).substr(0, 10); + m_consoleHandler.start(true, "[" + addr_start + "]: ", common::console::Color::BrightYellow); + m_stopEvent.wait(); return true; } //---------------------------------------------------------------------------------------------------- -void conceal_wallet::stop() { +void conceal_wallet::stop() +{ + m_dispatcher.remoteSpawn([this] + { m_stopEvent.set(); }); m_consoleHandler.requestStop(); } //---------------------------------------------------------------------------------------------------- -bool conceal_wallet::print_address(const std::vector &args/* = std::vector()*/) { - success_msg_writer() << m_wallet->getAddress(); +bool conceal_wallet::print_address(const std::vector &) +{ + success_msg_writer() << m_wallet->getAddress(0); return true; } //---------------------------------------------------------------------------------------------------- @@ -1579,40 +1425,51 @@ void conceal_wallet::printConnectionError() const { fail_msg_writer() << "wallet failed to connect to daemon (" << m_daemon_address << ")."; } -bool conceal_wallet::save_keys_to_file(const std::vector& args) +std::string conceal_wallet::get_wallet_keys() const { - if (!args.empty()) - { - logger(ERROR) << "Usage: \"export_keys\""; - return true; - } + KeyPair viewKey = m_wallet->getViewKey(); + KeyPair spendKey = m_wallet->getAddressSpendKey(0); + std::stringstream stream; - std::string formatted_wal_str = m_frmt_wallet_file + "_conceal_backup.txt"; - std::ofstream backup_file(formatted_wal_str); + stream << std::endl + << "ConcealWallet is an open-source, client-side, free wallet which allow you to send and receive CCX instantly on the blockchain. You are in control of your funds & your keys. When you generate a new wallet, login, send, receive or deposit $CCX everything happens locally. Your seed is never transmitted, received or stored. That's why its imperative to write, print or save your seed somewhere safe. The backup of keys is your responsibility. If you lose your seed, your account can not be recovered. The Conceal Team doesn't take any responsibility for lost funds due to nonexistent/missing/lost private keys." << std::endl + << std::endl; - AccountKeys keys; - m_wallet->getAccountKeys(keys); - - std::string priv_key = "\t\tConceal Keys Backup\n\n"; - priv_key += "Wallet file name: " + m_wallet_file + "\n"; - priv_key += "Private spend key: " + common::podToHex(keys.spendSecretKey) + "\n"; - priv_key += "Private view key: " + common::podToHex(keys.viewSecretKey) + "\n"; + stream << "Private spend key: " << common::podToHex(spendKey.secretKey) << std::endl; + stream << "Private view key: " << common::podToHex(viewKey.secretKey) << std::endl; crypto::PublicKey unused_dummy_variable; crypto::SecretKey deterministic_private_view_key; - AccountBase::generateViewFromSpend(keys.spendSecretKey, deterministic_private_view_key, unused_dummy_variable); - bool deterministic_private_keys = deterministic_private_view_key == keys.viewSecretKey; + AccountBase::generateViewFromSpend(spendKey.secretKey, deterministic_private_view_key, unused_dummy_variable); + + bool deterministic_private_keys = deterministic_private_view_key == viewKey.secretKey; /* dont show a mnemonic seed if it is an old non-deterministic wallet */ - if (deterministic_private_keys) { - std::cout << "Mnemonic seed: " << mnemonics::privateKeyToMnemonic(keys.spendSecretKey) << std::endl << std::endl; + if (deterministic_private_keys) + { + stream << "Mnemonic seed: " << mnemonics::privateKeyToMnemonic(spendKey.secretKey) << std::endl + << std::endl; } + return stream.str(); +} - backup_file << priv_key; +bool conceal_wallet::save_keys_to_file(const std::vector& args) +{ + if (!args.empty()) + { + logger(ERROR) << "Usage: \"save_keys\""; + return true; + } + + std::string backup_filename = common::RemoveExtension(m_wallet_file) + "_conceal_backup.txt"; + std::ofstream backup_file(backup_filename); + + backup_file << "Conceal Keys Backup" << std::endl + << get_wallet_keys(); logger(INFO, BRIGHT_GREEN) << "Wallet keys have been saved to the current folder where \"concealwallet\" is located as \"" - << formatted_wal_str << "."; + << backup_filename << "\"."; return true; } @@ -1651,8 +1508,8 @@ bool conceal_wallet::save_all_txs_to_file(const std::vector &args) logger(INFO) << "Preparing file and transactions..."; /* create filename and file */ - std::string formatted_wal_str = m_frmt_wallet_file + "_conceal_transactions.txt"; - std::ofstream tx_file(formatted_wal_str); + std::string tx_filename = common::RemoveExtension(m_wallet_file) + "_conceal_transactions.txt"; + std::ofstream tx_file(tx_filename); /* create header for listed txs */ std::string header = common::makeCenteredString(32, "timestamp (UTC)") + " | "; @@ -1672,17 +1529,16 @@ bool conceal_wallet::save_all_txs_to_file(const std::vector &args) /* create line from string */ std::string listed_tx; - /* get tx struct */ - WalletLegacyTransaction txInfo; - /* go through tx ids for the amount of transactions in wallet */ for (TransactionId i = 0; i < tx_count; ++i) { + /* get tx struct */ + WalletTransaction txInfo; /* get tx to list from i */ - m_wallet->getTransaction(i, txInfo); + txInfo = m_wallet->getTransaction(i); /* check tx state */ - if (txInfo.state != WalletLegacyTransactionState::Active || txInfo.blockHeight == WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT) { + if (txInfo.state != WalletTransactionState::SUCCEEDED || txInfo.blockHeight == WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT) { continue; } @@ -1693,18 +1549,18 @@ bool conceal_wallet::save_all_txs_to_file(const std::vector &args) tx_file << formatted_item_tx; /* tell user about progress */ - logger(INFO) << "Transaction: " << i << " was pushed to " << formatted_wal_str; + logger(INFO) << "Transaction: " << i << " was pushed to " << tx_filename; } /* tell user job complete */ logger(INFO, BRIGHT_GREEN) << "All transactions have been saved to the current folder where \"concealwallet\" is located as \"" - << formatted_wal_str << "\"."; + << tx_filename << "\"."; /* if user uses "save_txs_to_file true" then we go through the deposits */ if (include_deposits == true) { /* get total deposits in wallet */ - size_t deposit_count = m_wallet->getDepositCount(); + size_t deposit_count = m_wallet->getWalletDepositCount(); /* check wallet txs before doing work */ if (deposit_count == 0) { @@ -1737,11 +1593,11 @@ bool conceal_wallet::save_all_txs_to_file(const std::vector &args) for (DepositId id = 0; id < deposit_count; ++id) { /* get deposit info from id and store it to deposit */ - Deposit deposit = m_wallet->get_deposit(id); - cn::WalletLegacyTransaction txInfo; + Deposit deposit = m_wallet->getDeposit(id); + cn::WalletTransaction txInfo; /* get deposit info and use its transaction in the chain */ - m_wallet->getTransaction(deposit.creatingTransactionId, txInfo); + txInfo = m_wallet->getTransaction(deposit.creatingTransactionId); /* grab deposit info */ std::string formatted_item_d = m_chelper.list_deposit_item(txInfo, deposit, listed_deposit, id, m_currency); @@ -1750,20 +1606,20 @@ bool conceal_wallet::save_all_txs_to_file(const std::vector &args) tx_file << formatted_item_d; /* tell user about progress */ - logger(INFO) << "Deposit: " << id << " was pushed to " << formatted_wal_str; + logger(INFO) << "Deposit: " << id << " was pushed to " << tx_filename; } /* tell user job complete */ logger(INFO, BRIGHT_GREEN) << "All deposits have been saved to the end of the file current folder where \"concealwallet\" is located as \"" - << formatted_wal_str << "\"."; + << tx_filename << "\"."; } return true; } -bool conceal_wallet::list_deposits(const std::vector &args) +bool conceal_wallet::list_deposits(const std::vector &) { - bool haveDeposits = m_wallet->getDepositCount() > 0; + bool haveDeposits = m_wallet->getWalletDepositCount() > 0; if (!haveDeposits) { @@ -1774,14 +1630,13 @@ bool conceal_wallet::list_deposits(const std::vector &args) printListDepositsHeader(logger); /* go through deposits ids for the amount of deposits in wallet */ - for (DepositId id = 0; id < m_wallet->getDepositCount(); ++id) + for (DepositId id = 0; id < m_wallet->getWalletDepositCount(); ++id) { /* get deposit info from id and store it to deposit */ - Deposit deposit = m_wallet->get_deposit(id); - cn::WalletLegacyTransaction txInfo; - m_wallet->getTransaction(deposit.creatingTransactionId, txInfo); + Deposit deposit = m_wallet->getDeposit(id); + cn::WalletTransaction txInfo = m_wallet->getTransaction(deposit.creatingTransactionId); - logger(INFO) << m_chelper.get_deposit_info(deposit, id, m_currency, txInfo); + logger(INFO) << m_chelper.get_deposit_info(deposit, id, m_currency, txInfo.blockHeight); } return true; @@ -1803,7 +1658,7 @@ bool conceal_wallet::deposit(const std::vector &args) **/ uint64_t min_term = m_currency.depositMinTermV3(); uint64_t max_term = m_currency.depositMaxTermV3(); - uint64_t deposit_term = boost::lexical_cast(args[0]) * min_term; + uint64_t deposit_term = boost::lexical_cast(args[0]) * min_term; /* Now validate the deposit term and the amount */ if (deposit_term < min_term) @@ -1841,38 +1696,12 @@ bool conceal_wallet::deposit(const std::vector &args) return true; } + std::string address = m_wallet->getAddress(0); + std::string tx_hash; logger(INFO) << "Creating deposit..."; - /* Use defaults for fee + mix in */ - uint64_t deposit_fee = cn::parameters::MINIMUM_FEE_V2; - uint64_t deposit_mix_in = cn::parameters::MINIMUM_MIXIN; - - cn::WalletHelper::SendCompleteResultObserver sent; - WalletHelper::IWalletRemoveObserverGuard removeGuard(*m_wallet, sent); - - cn::TransactionId tx = m_wallet->deposit(deposit_term, deposit_amount, deposit_fee, deposit_mix_in); - - if (tx == WALLET_LEGACY_INVALID_DEPOSIT_ID) - { - fail_msg_writer() << "Can't deposit money"; - return true; - } - - std::error_code sendError = sent.wait(tx); - removeGuard.removeObserver(); - - if (sendError) - { - fail_msg_writer() << sendError.message(); - return true; - } - - cn::WalletLegacyTransaction d_info; - m_wallet->getTransaction(tx, d_info); - success_msg_writer(true) << "Money successfully sent, transaction hash: " << common::podToHex(d_info.hash) - << "\n\tID: " << d_info.firstDepositId; - - m_chelper.save_wallet(*m_wallet, m_wallet_file, logger); + m_wallet->createDeposit(deposit_amount, deposit_term, address, address, tx_hash); + success_msg_writer(true) << "Money successfully sent, transaction hash: " << tx_hash; } catch (const std::system_error& e) { @@ -1900,44 +1729,20 @@ bool conceal_wallet::withdraw(const std::vector &args) try { - if (m_wallet->getDepositCount() == 0) + if (m_wallet->getWalletDepositCount() == 0) { logger(ERROR) << "No deposits have been made in this wallet."; return true; } uint64_t deposit_id = boost::lexical_cast(args[0]); - uint64_t deposit_fee = cn::parameters::MINIMUM_FEE_V2; - - cn::WalletHelper::SendCompleteResultObserver sent; - WalletHelper::IWalletRemoveObserverGuard removeGuard(*m_wallet, sent); - - cn::TransactionId tx = m_wallet->withdrawDeposit(deposit_id, deposit_fee); - - if (tx == WALLET_LEGACY_INVALID_DEPOSIT_ID) - { - fail_msg_writer() << "Can't withdraw money"; - return true; - } - - std::error_code sendError = sent.wait(tx); - removeGuard.removeObserver(); - - if (sendError) - { - fail_msg_writer() << sendError.message(); - return true; - } - - cn::WalletLegacyTransaction d_info; - m_wallet->getTransaction(tx, d_info); - success_msg_writer(true) << "Money successfully sent, transaction hash: " << common::podToHex(d_info.hash); - - m_chelper.save_wallet(*m_wallet, m_wallet_file, logger); + std::string tx_hash; + m_wallet->withdrawDeposit(deposit_id, tx_hash); + success_msg_writer(true) << "Money successfully sent, transaction hash: " << tx_hash; } catch (std::exception &e) { - fail_msg_writer() << "failed to withdraw deposit: " << e.what(); + fail_msg_writer() << "Failed to withdraw deposit: " << e.what(); } return true; @@ -1950,18 +1755,20 @@ bool conceal_wallet::deposit_info(const std::vector &args) logger(ERROR) << "Usage: withdraw "; return true; } - uint64_t deposit_id = boost::lexical_cast(args[0]); cn::Deposit deposit; - if (!m_wallet->getDeposit(deposit_id, deposit)) + try + { + deposit = m_wallet->getDeposit(deposit_id); + } + catch (const std::exception &e) { - logger(ERROR, BRIGHT_RED) << "Error: Invalid deposit id: " << deposit_id; + logger(ERROR, BRIGHT_RED) << "Error: " << e.what(); return false; } - cn::WalletLegacyTransaction txInfo; - m_wallet->getTransaction(deposit.creatingTransactionId, txInfo); + cn::WalletTransaction txInfo = m_wallet->getTransaction(deposit.creatingTransactionId); - logger(INFO) << m_chelper.get_full_deposit_info(deposit, deposit_id, m_currency, txInfo); + logger(INFO) << m_chelper.get_full_deposit_info(deposit, deposit_id, m_currency, txInfo.blockHeight); return true; } diff --git a/src/ConcealWallet/ConcealWallet.h b/src/ConcealWallet/ConcealWallet.h index 02aedb0c2..bb5e2847e 100644 --- a/src/ConcealWallet/ConcealWallet.h +++ b/src/ConcealWallet/ConcealWallet.h @@ -14,7 +14,7 @@ #include -#include "IWalletLegacy.h" +#include "Wallet/WalletGreen.h" #include "PasswordContainer.h" #include "ClientHelper.h" @@ -35,7 +35,7 @@ namespace cn /************************************************************************/ /* */ /************************************************************************/ - class conceal_wallet : public cn::INodeObserver, public cn::IWalletLegacyObserver, public cn::INodeRpcProxyObserver { + class conceal_wallet : public IBlockchainSynchronizerObserver { public: conceal_wallet(platform_system::Dispatcher& dispatcher, const cn::Currency& currency, logging::LoggerManager& log); @@ -55,7 +55,7 @@ namespace cn private: - logging::LoggerMessage success_msg_writer(bool color = false) { + logging::LoggerMessage success_msg_writer(bool color = false) const{ return logger(logging::INFO, color ? logging::GREEN : logging::DEFAULT); } @@ -70,7 +70,7 @@ namespace cn bool run_console_handler(); bool new_wallet(const std::string &wallet_file, const std::string& password); - bool new_wallet(crypto::SecretKey &secret_key, crypto::SecretKey &view_key, const std::string &wallet_file, const std::string& password); + bool new_wallet(const crypto::SecretKey &secret_key, const crypto::SecretKey &view_key, const std::string &wallet_file, const std::string& password); bool open_wallet(const std::string &wallet_file, const std::string& password); bool close_wallet(); @@ -111,28 +111,18 @@ namespace cn std::string resolveAlias(const std::string& aliasUrl); void printConnectionError() const; + std::string get_wallet_keys() const; - //---------------- IWalletLegacyObserver ------------------------- - virtual void initCompleted(std::error_code result) override; - virtual void externalTransactionCreated(cn::TransactionId transactionId) override; - virtual void synchronizationCompleted(std::error_code result) override; - virtual void synchronizationProgressUpdated(uint32_t current, uint32_t total) override; - //---------------------------------------------------------- - - //----------------- INodeRpcProxyObserver -------------------------- - virtual void connectionStatusUpdated(bool connected) override; - //---------------------------------------------------------- + void synchronizationCompleted(std::error_code result) override; + void synchronizationProgressUpdated(uint32_t processedBlockCount, uint32_t totalBlockCount) override; friend class refresh_progress_reporter_t; class refresh_progress_reporter_t { public: - refresh_progress_reporter_t(cn::conceal_wallet& conceal_wallet) + explicit refresh_progress_reporter_t(cn::conceal_wallet& conceal_wallet) : m_conceal_wallet(conceal_wallet) - , m_blockchain_height(0) - , m_blockchain_height_update_time() - , m_print_time() { } @@ -159,14 +149,12 @@ namespace cn m_blockchain_height_update_time = std::chrono::system_clock::now(); } - private: cn::conceal_wallet& m_conceal_wallet; - uint64_t m_blockchain_height; + uint64_t m_blockchain_height = 0; std::chrono::system_clock::time_point m_blockchain_height_update_time; std::chrono::system_clock::time_point m_print_time; }; - private: std::string m_wallet_file_arg; std::string m_generate_new; std::string m_import_new; @@ -185,11 +173,12 @@ namespace cn const cn::Currency& m_currency; logging::LoggerManager& logManager; platform_system::Dispatcher& m_dispatcher; + platform_system::Event m_stopEvent; logging::LoggerRef logger; cn::client_helper m_chelper; std::unique_ptr m_node; - std::unique_ptr m_wallet; + std::unique_ptr m_wallet; refresh_progress_reporter_t m_refresh_progress_reporter; bool m_walletSynchronized; diff --git a/src/ConcealWallet/TransferCmd.cpp b/src/ConcealWallet/TransferCmd.cpp index 5f6ea3a28..14b2ce0e0 100644 --- a/src/ConcealWallet/TransferCmd.cpp +++ b/src/ConcealWallet/TransferCmd.cpp @@ -9,19 +9,20 @@ #include "Common/StringTools.h" #include "CryptoNoteCore/CryptoNoteTools.h" #include "CryptoNoteCore/CryptoNoteBasicImpl.h" +#include "CryptoNoteCore/TransactionExtra.h" +#include "CryptoNoteCore/CryptoNoteFormatUtils.h" using namespace logging; namespace cn { - transfer_cmd::transfer_cmd(const cn::Currency& currency, std::string remote_fee_address) : + transfer_cmd::transfer_cmd(const cn::Currency& currency, const std::string& remote_fee_address) : m_currency(currency), - m_remote_address(remote_fee_address), - fake_outs_count(0), - fee(currency.minimumFeeV2()) { + fee(currency.minimumFeeV2()), + m_remote_address(remote_fee_address) { } - bool transfer_cmd::parseTx(LoggerRef& logger, const std::vector &args) + bool transfer_cmd::parseTx(const LoggerRef& logger, const std::vector &args) { ArgumentReader::const_iterator> ar(args.begin(), args.end()); @@ -89,8 +90,8 @@ namespace cn arg = address; } - WalletLegacyTransfer destination; - WalletLegacyTransfer feeDestination; + WalletOrder destination; + WalletOrder feeDestination; cn::TransactionDestinationEntry de; std::string aliasUrl; @@ -115,7 +116,7 @@ namespace cn } else { - aliases[aliasUrl].emplace_back(WalletLegacyTransfer{"", static_cast(de.amount)}); + aliases[aliasUrl].emplace_back(WalletOrder{"", de.amount}); } /* Remote node transactions fees are 10000 X */ diff --git a/src/ConcealWallet/TransferCmd.h b/src/ConcealWallet/TransferCmd.h index cb49042b7..026fa926f 100644 --- a/src/ConcealWallet/TransferCmd.h +++ b/src/ConcealWallet/TransferCmd.h @@ -5,8 +5,8 @@ #pragma once +#include "IWallet.h" #include "CryptoNoteCore/Currency.h" -#include "WalletLegacy/WalletLegacy.h" #include "Common/StringTools.h" #include @@ -19,18 +19,18 @@ namespace cn { public: const cn::Currency& m_currency; - size_t fake_outs_count; - std::vector dsts; + size_t fake_outs_count = 0; + std::vector dsts; std::vector extra; uint64_t fee; - std::map> aliases; + std::map> aliases; std::vector messages; uint64_t ttl = 0; std::string m_remote_address; - transfer_cmd(const cn::Currency& currency, std::string remote_fee_address); + transfer_cmd(const cn::Currency& currency, const std::string& remote_fee_address); - bool parseTx(LoggerRef& logger, const std::vector &args); + bool parseTx(const LoggerRef& logger, const std::vector &args); }; template diff --git a/src/ConcealWallet/main.cpp b/src/ConcealWallet/main.cpp index 55b8f7590..417aa1ffd 100644 --- a/src/ConcealWallet/main.cpp +++ b/src/ConcealWallet/main.cpp @@ -89,7 +89,7 @@ int main(int argc, char* argv[]) return 1; //set up logging options - Level logLevel = DEBUGGING; + Level logLevel = INFO; if (command_line::has_arg(vm, arg_log_level)) logLevel = static_cast(command_line::get_arg(vm, arg_log_level)); @@ -166,8 +166,8 @@ int main(int argc, char* argv[]) { walletFileName = m_chelper.tryToOpenWalletOrLoadKeysOrThrow(logger, wallet, wallet_file, wallet_password); - std::stringstream balances = m_chelper.balances(wallet, currency); - logger(INFO) << balances.str(); + // std::stringstream balances = m_chelper.balances(wallet, currency); + // logger(INFO) << balances.str(); logger(INFO, BRIGHT_GREEN) << "Loaded ok"; } @@ -195,7 +195,7 @@ int main(int argc, char* argv[]) logger(INFO) << "Stopped wallet rpc server"; logger(logging::INFO) << "Saving wallet..."; - m_chelper.save_wallet(*wallet, walletFileName, logger); + // m_chelper.save_wallet(*wallet, walletFileName, logger); logger(logging::INFO, logging::BRIGHT_GREEN) << "Saving successful"; } else diff --git a/src/NodeRpcProxy/NodeRpcProxy.h b/src/NodeRpcProxy/NodeRpcProxy.h index 4e724fc73..9ba9ca419 100644 --- a/src/NodeRpcProxy/NodeRpcProxy.h +++ b/src/NodeRpcProxy/NodeRpcProxy.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "Common/ObserverManager.h" #include "INode.h" @@ -29,47 +30,75 @@ class HttpClient; class INodeRpcProxyObserver { public: - virtual ~INodeRpcProxyObserver() {} + virtual ~INodeRpcProxyObserver() = default; virtual void connectionStatusUpdated(bool connected) {} }; +class NodeInitObserver +{ +public: + NodeInitObserver() + { + initFuture = initPromise.get_future(); + } + + void initCompleted(std::error_code result) + { + initPromise.set_value(result); + } + + void waitForInitEnd() + { + std::error_code ec = initFuture.get(); + if (ec) + { + throw std::system_error(ec); + } + return; + } + +private: + std::promise initPromise; + std::future initFuture; +}; + class NodeRpcProxy : public cn::INode { public: NodeRpcProxy(const std::string& nodeHost, unsigned short nodePort); - virtual ~NodeRpcProxy(); + ~NodeRpcProxy() override; - virtual bool addObserver(cn::INodeObserver* observer) override; - virtual bool removeObserver(cn::INodeObserver* observer) override; + bool addObserver(cn::INodeObserver* observer) override; + bool removeObserver(cn::INodeObserver* observer) override; virtual bool addObserver(cn::INodeRpcProxyObserver* observer); virtual bool removeObserver(cn::INodeRpcProxyObserver* observer); - virtual void init(const Callback& callback) override; - virtual bool shutdown() override; - - virtual size_t getPeerCount() const override; - virtual uint32_t getLastLocalBlockHeight() const override; - virtual uint32_t getLastKnownBlockHeight() const override; - virtual uint32_t getLocalBlockCount() const override; - virtual uint32_t getKnownBlockCount() const override; - virtual uint64_t getLastLocalBlockTimestamp() const override; - - virtual void relayTransaction(const cn::Transaction& transaction, const Callback& callback) override; - virtual void getRandomOutsByAmounts(std::vector&& amounts, uint64_t outsCount, std::vector& result, const Callback& callback) override; - virtual void getNewBlocks(std::vector&& knownBlockIds, std::vector& newBlocks, uint32_t& startHeight, const Callback& callback) override; - virtual void getTransactionOutsGlobalIndices(const crypto::Hash& transactionHash, std::vector& outsGlobalIndices, const Callback& callback) override; - virtual void queryBlocks(std::vector&& knownBlockIds, uint64_t timestamp, std::vector& newBlocks, uint32_t& startHeight, const Callback& callback) override; - virtual void getPoolSymmetricDifference(std::vector&& knownPoolTxIds, crypto::Hash knownBlockId, bool& isBcActual, + void init(const Callback& callback) override; + bool shutdown() override; + + size_t getPeerCount() const override; + uint32_t getLastLocalBlockHeight() const override; + uint32_t getLastKnownBlockHeight() const override; + uint32_t getLocalBlockCount() const override; + uint32_t getKnownBlockCount() const override; + uint64_t getLastLocalBlockTimestamp() const override; + + void relayTransaction(const cn::Transaction& transaction, const Callback& callback) override; + void getRandomOutsByAmounts(std::vector&& amounts, uint64_t outsCount, std::vector& result, const Callback& callback) override; + void getNewBlocks(std::vector&& knownBlockIds, std::vector& newBlocks, uint32_t& startHeight, const Callback& callback) override; + void getTransactionOutsGlobalIndices(const crypto::Hash& transactionHash, std::vector& outsGlobalIndices, const Callback& callback) override; + void queryBlocks(std::vector&& knownBlockIds, uint64_t timestamp, std::vector& newBlocks, uint32_t& startHeight, const Callback& callback) override; + void getPoolSymmetricDifference(std::vector&& knownPoolTxIds, crypto::Hash knownBlockId, bool& isBcActual, std::vector>& newTxs, std::vector& deletedTxIds, const Callback& callback) override; - virtual void getMultisignatureOutputByGlobalIndex(uint64_t amount, uint32_t gindex, MultisignatureOutput& out, const Callback& callback) override; - virtual void getBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) override; + void getMultisignatureOutputByGlobalIndex(uint64_t amount, uint32_t gindex, MultisignatureOutput& out, const Callback& callback) override; + void getBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) override; - virtual void getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) override; - virtual void getBlocks(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t blocksNumberLimit, std::vector& blocks, uint32_t& blocksNumberWithinTimestamps, const Callback& callback) override; - virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) override; - virtual void getTransactionsByPaymentId(const crypto::Hash& paymentId, std::vector& transactions, const Callback& callback) override; - virtual void getPoolTransactions(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t transactionsNumberLimit, std::vector& transactions, uint64_t& transactionsNumberWithinTimestamps, const Callback& callback) override; - virtual void isSynchronized(bool& syncStatus, const Callback& callback) override; + void getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) override; + void getBlocks(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t blocksNumberLimit, std::vector& blocks, uint32_t& blocksNumberWithinTimestamps, const Callback& callback) override; + void getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) override; + void getTransactionsByPaymentId(const crypto::Hash& paymentId, std::vector& transactions, const Callback& callback) override; + void getPoolTransactions(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t transactionsNumberLimit, std::vector& transactions, uint64_t& transactionsNumberWithinTimestamps, const Callback& callback) override; + void isSynchronized(bool& syncStatus, const Callback& callback) override; unsigned int rpcTimeout() const { return m_rpcTimeout; } void rpcTimeout(unsigned int val) { m_rpcTimeout = val; } @@ -98,16 +127,16 @@ class NodeRpcProxy : public cn::INode { std::vector& newBlocks, uint32_t& startHeight); std::error_code doGetPoolSymmetricDifference(std::vector&& knownPoolTxIds, crypto::Hash knownBlockId, bool& isBcActual, std::vector>& newTxs, std::vector& deletedTxIds); - virtual void getTransaction(const crypto::Hash &transactionHash, cn::Transaction &transaction, const Callback &callback) override; + void getTransaction(const crypto::Hash &transactionHash, cn::Transaction &transaction, const Callback &callback) override; std::error_code doGetTransaction(const crypto::Hash &transactionHash, cn::Transaction &transaction); - void scheduleRequest(std::function&& procedure, const Callback& callback); -template - std::error_code binaryCommand(const std::string& url, const Request& req, Response& res); + void scheduleRequest(std::function &&procedure, const Callback &callback); + template + std::error_code binaryCommand(const std::string &url, const Request &req, Response &res); template - std::error_code jsonCommand(const std::string& url, const Request& req, Response& res); + std::error_code jsonCommand(const std::string &url, const Request &req, Response &res); template - std::error_code jsonRpcCommand(const std::string& method, const Request& req, Response& res); + std::error_code jsonRpcCommand(const std::string &method, const Request &req, Response &res); enum State { STATE_NOT_INITIALIZED, @@ -115,7 +144,6 @@ template STATE_INITIALIZED }; -private: State m_state = STATE_NOT_INITIALIZED; std::mutex m_mutex; std::condition_variable m_cv_initialized; diff --git a/src/PaymentGate/NodeFactory.cpp b/src/PaymentGate/NodeFactory.cpp index b99629362..925a09517 100644 --- a/src/PaymentGate/NodeFactory.cpp +++ b/src/PaymentGate/NodeFactory.cpp @@ -77,30 +77,6 @@ class NodeRpcStub: public cn::INode { }; - -class NodeInitObserver { -public: - NodeInitObserver() { - initFuture = initPromise.get_future(); - } - - void initCompleted(std::error_code result) { - initPromise.set_value(result); - } - - void waitForInitEnd() { - std::error_code ec = initFuture.get(); - if (ec) { - throw std::system_error(ec); - } - return; - } - -private: - std::promise initPromise; - std::future initFuture; -}; - NodeFactory::NodeFactory() = default; NodeFactory::~NodeFactory() = default; @@ -108,8 +84,8 @@ NodeFactory::~NodeFactory() = default; cn::INode* NodeFactory::createNode(const std::string& daemonAddress, uint16_t daemonPort) { std::unique_ptr node(new cn::NodeRpcProxy(daemonAddress, daemonPort)); - NodeInitObserver initObserver; - node->init(std::bind(&NodeInitObserver::initCompleted, &initObserver, std::placeholders::_1)); + cn::NodeInitObserver initObserver; + node->init(std::bind(&cn::NodeInitObserver::initCompleted, &initObserver, std::placeholders::_1)); initObserver.waitForInitEnd(); return node.release(); diff --git a/src/PaymentGate/WalletService.cpp b/src/PaymentGate/WalletService.cpp index 97ce49086..9f580f322 100644 --- a/src/PaymentGate/WalletService.cpp +++ b/src/PaymentGate/WalletService.cpp @@ -34,7 +34,6 @@ #include "NodeFactory.h" #include "Wallet/WalletGreen.h" -#include "Wallet/LegacyKeysImporter.h" #include "Wallet/WalletErrors.h" #include "Wallet/WalletUtils.h" #include "WalletServiceErrorCategory.h" @@ -385,28 +384,6 @@ namespace payment_service } // namespace - void createWalletFile(std::fstream &walletFile, const std::string &filename) - { - boost::filesystem::path pathToWalletFile(filename); - boost::filesystem::path directory = pathToWalletFile.parent_path(); - if (!directory.empty() && !tools::directoryExists(directory.string())) - { - throw std::runtime_error("Directory does not exist: " + directory.string()); - } - - walletFile.open(filename.c_str(), std::fstream::in | std::fstream::out | std::fstream::binary); - if (walletFile) - { - walletFile.close(); - throw std::runtime_error("Wallet file already exists"); - } - - walletFile.open(filename.c_str(), std::fstream::out); - walletFile.close(); - - walletFile.open(filename.c_str(), std::fstream::in | std::fstream::out | std::fstream::binary); - } - void saveWallet(cn::IWallet &wallet, std::fstream &walletFile, bool saveDetailed = true, bool saveCache = true) { wallet.save(); @@ -517,20 +494,6 @@ namespace payment_service log(logging::INFO) << "Wallet is saved"; } // namespace payment_service - void importLegacyKeys(const std::string &legacyKeysFile, const WalletConfiguration &conf) - { - std::stringstream archive; - - cn::importLegacyKeys(legacyKeysFile, conf.walletPassword, archive); - - std::fstream walletFile; - createWalletFile(walletFile, conf.walletFile); - - archive.flush(); - walletFile << archive.rdbuf(); - walletFile.flush(); - } - WalletService::WalletService( const cn::Currency ¤cy, platform_system::Dispatcher &sys, diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index 15610cceb..ca976e522 100644 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -21,6 +21,7 @@ #include "ITransaction.h" +#include "Common/Base58.h" #include "Common/ScopeExit.h" #include "Common/ShuffleGenerator.h" #include "Common/StdInputStream.h" @@ -422,7 +423,7 @@ namespace cn auto getTransactionCompleted = std::promise(); auto getTransactionWaitFuture = getTransactionCompleted.get_future(); cn::Transaction tx; - m_node.getTransaction(std::move(transactionHash), std::ref(tx), + m_node.getTransaction(transactionHash, std::ref(tx), [&getTransactionCompleted](std::error_code ec) { auto detachedPromise = std::move(getTransactionCompleted); detachedPromise.set_value(ec); @@ -756,6 +757,21 @@ namespace cn m_logger(INFO, BRIGHT_WHITE) << "Container initialized with view secret key, public view key " << common::podToHex(viewPublicKey); } + void WalletGreen::generateNewWallet(const std::string &path, const std::string &password) + { + crypto::SecretKey viewSecretKey; + cn::KeyPair spendKey; + + crypto::generate_keys(spendKey.publicKey, spendKey.secretKey); + + crypto::PublicKey viewPublicKey; + + cn::AccountBase::generateViewFromSpend(spendKey.secretKey, viewSecretKey, viewPublicKey); + + initializeWithViewKey(path, password, viewSecretKey); + createAddress(spendKey.secretKey); + } + void WalletGreen::shutdown() { throwIfNotInitialized(); @@ -1831,6 +1847,49 @@ namespace cn return wallet.pendingBalance; } + uint64_t WalletGreen::getDustBalance() const + { + throwIfNotInitialized(); + throwIfStopped(); + + const auto &walletsIndex = m_walletsContainer.get(); + uint64_t money = 0; + for (const auto &wallet : walletsIndex) + { + const ITransfersContainer *container = wallet.container; + std::vector outputs; + container->getOutputs(outputs, ITransfersContainer::IncludeKeyUnlocked); + for (const auto &output : outputs) + { + if (output.amount < m_currency.defaultDustThreshold()) + { + money += output.amount; + } + } + } + return money; + } + + uint64_t WalletGreen::getDustBalance(const std::string &address) const + { + throwIfNotInitialized(); + throwIfStopped(); + + const auto &wallet = getWalletRecord(address); + uint64_t money = 0; + const ITransfersContainer *container = wallet.container; + std::vector outputs; + container->getOutputs(outputs, ITransfersContainer::IncludeKeyUnlocked); + for (const auto &output : outputs) + { + if (output.amount < m_currency.defaultDustThreshold()) + { + money += output.amount; + } + } + return money; + } + size_t WalletGreen::getTransactionCount() const { throwIfNotInitialized(); @@ -1862,7 +1921,15 @@ namespace cn throw std::system_error(make_error_code(cn::error::DEPOSIT_DOESNOT_EXIST)); } - return m_deposits.get()[depositIndex]; + Deposit deposit = m_deposits.get()[depositIndex]; + + uint32_t knownBlockHeight = m_node.getLastKnownBlockHeight(); + if (knownBlockHeight > deposit.unlockHeight) + { + deposit.locked = false; + } + + return deposit; } size_t WalletGreen::getTransactionTransferCount(size_t transactionIndex) const @@ -2702,15 +2769,16 @@ namespace cn void WalletGreen::sendTransaction(const cn::Transaction &cryptoNoteTransaction) { - platform_system::Event completion(m_dispatcher); std::error_code ec; - throwIfStopped(); - m_node.relayTransaction(cryptoNoteTransaction, [&ec, &completion, this](std::error_code error) { - ec = error; - this->m_dispatcher.remoteSpawn(std::bind(asyncRequestCompletion, std::ref(completion))); - }); - completion.wait(); + auto relayTransactionCompleted = std::promise(); + auto relayTransactionWaitFuture = relayTransactionCompleted.get_future(); + m_node.relayTransaction(cryptoNoteTransaction, [&ec, &relayTransactionCompleted, this](std::error_code error) + { + auto detachedPromise = std::move(relayTransactionCompleted); + detachedPromise.set_value(ec); + }); + ec = relayTransactionWaitFuture.get(); if (ec) { @@ -2807,17 +2875,18 @@ namespace cn amounts.push_back(out.out.amount); } - platform_system::Event requestFinished(m_dispatcher); std::error_code mixinError; throwIfStopped(); - m_node.getRandomOutsByAmounts(std::move(amounts), mixIn, mixinResult, [&requestFinished, &mixinError, this](std::error_code ec) { - mixinError = ec; - this->m_dispatcher.remoteSpawn(std::bind(asyncRequestCompletion, std::ref(requestFinished))); - }); + auto getRandomOutsByAmountsCompleted = std::promise(); + auto getRandomOutsByAmountsWaitFuture = getRandomOutsByAmountsCompleted.get_future(); - requestFinished.wait(); + m_node.getRandomOutsByAmounts(std::move(amounts), mixIn, mixinResult, [&getRandomOutsByAmountsCompleted, &mixinError, this](std::error_code ec) { + auto detachedPromise = std::move(getRandomOutsByAmountsCompleted); + detachedPromise.set_value(ec); + }); + mixinError = getRandomOutsByAmountsWaitFuture.get(); checkIfEnoughMixins(mixinResult, mixIn); @@ -3282,23 +3351,23 @@ namespace cn blockHeightIndex.erase(std::next(blockHeightIndex.begin(), blockIndex), blockHeightIndex.end()); } - void WalletGreen::onTransactionDeleteBegin(const crypto::PublicKey &viewPublicKey, crypto::Hash transactionHash) + void WalletGreen::onTransactionDeleteBegin(const crypto::PublicKey &viewPublicKey, const crypto::Hash &transactionHash) { m_dispatcher.remoteSpawn([=]() { transactionDeleteBegin(transactionHash); }); } // TODO remove - void WalletGreen::transactionDeleteBegin(crypto::Hash /*transactionHash*/) + void WalletGreen::transactionDeleteBegin(const crypto::Hash& /*transactionHash*/) { } - void WalletGreen::onTransactionDeleteEnd(const crypto::PublicKey &viewPublicKey, crypto::Hash transactionHash) + void WalletGreen::onTransactionDeleteEnd(const crypto::PublicKey &viewPublicKey, const crypto::Hash &transactionHash) { m_dispatcher.remoteSpawn([=]() { transactionDeleteEnd(transactionHash); }); } // TODO remove - void WalletGreen::transactionDeleteEnd(crypto::Hash transactionHash) + void WalletGreen::transactionDeleteEnd(const crypto::Hash &transactionHash) { } @@ -3414,6 +3483,184 @@ namespace cn return id; } + std::vector WalletGreen::getUnspentOutputs() + { + std::vector unspentOutputs; + const auto &walletsIndex = m_walletsContainer.get(); + + std::vector walletOuts; + for (const auto &wallet : walletsIndex) + { + const ITransfersContainer *container = wallet.container; + + std::vector outputs; + container->getOutputs(outputs, ITransfersContainer::IncludeKeyUnlocked); + unspentOutputs.insert(unspentOutputs.end(), outputs.begin(), outputs.end()); + } + return unspentOutputs; + } + + size_t WalletGreen::getUnspentOutputsCount() + { + + return getUnspentOutputs().size(); + } + + std::string WalletGreen::getReserveProof(const std::string &address, const uint64_t &reserve, const std::string &message) + { + const WalletRecord& wallet = getWalletRecord(address); + const AccountKeys& keys = makeAccountKeys(wallet); + + if (keys.spendSecretKey == NULL_SECRET_KEY) + { + throw std::runtime_error("Reserve proof can only be generated by a full wallet"); + } + uint64_t actualBalance = getActualBalance(); + if (actualBalance == 0) + { + throw std::runtime_error("Zero balance"); + } + + if (actualBalance < reserve) + { + throw std::runtime_error("Not enough balance for the requested minimum reserve amount"); + } + + // determine which outputs to include in the proof + std::vector selected_transfers; + wallet.container->getOutputs(selected_transfers, ITransfersContainer::IncludeKeyUnlocked); + + // minimize the number of outputs included in the proof, by only picking the N largest outputs that can cover the requested min reserve amount + auto compareTransactionOutputInformationByAmount = [](const TransactionOutputInformation &a, const TransactionOutputInformation &b) + { return a.amount < b.amount; }; + std::sort(selected_transfers.begin(), selected_transfers.end(), compareTransactionOutputInformationByAmount); + while (selected_transfers.size() >= 2 && selected_transfers[1].amount >= reserve) + { + selected_transfers.erase(selected_transfers.begin()); + } + size_t sz = 0; + uint64_t total = 0; + while (total < reserve) + { + total += selected_transfers[sz].amount; + ++sz; + } + selected_transfers.resize(sz); + + // compute signature prefix hash + std::string prefix_data = message; + prefix_data.append((const char *)&keys.address, sizeof(cn::AccountPublicAddress)); + + std::vector kimages; + cn::KeyPair ephemeral; + + for (const auto &td : selected_transfers) + { + // derive ephemeral secret key + crypto::KeyImage ki; + const bool r = cn::generate_key_image_helper(keys, td.transactionPublicKey, td.outputInTransaction, ephemeral, ki); + if (!r) + { + throw std::runtime_error("Failed to generate key image"); + } + // now we can insert key image + prefix_data.append((const char *)&ki, sizeof(crypto::PublicKey)); + kimages.push_back(ki); + } + + crypto::Hash prefix_hash; + crypto::cn_fast_hash(prefix_data.data(), prefix_data.size(), prefix_hash); + + // generate proof entries + std::vector proofs(selected_transfers.size()); + + for (size_t i = 0; i < selected_transfers.size(); ++i) + { + const TransactionOutputInformation &td = selected_transfers[i]; + reserve_proof_entry &proof = proofs[i]; + proof.key_image = kimages[i]; + proof.txid = td.transactionHash; + proof.index_in_tx = td.outputInTransaction; + + auto txPubKey = td.transactionPublicKey; + + for (int i = 0; i < 2; ++i) + { + crypto::KeyImage sk = crypto::scalarmultKey(*reinterpret_cast(&txPubKey), *reinterpret_cast(&keys.viewSecretKey)); + proof.shared_secret = *reinterpret_cast(&sk); + + crypto::KeyDerivation derivation; + if (!crypto::generate_key_derivation(proof.shared_secret, keys.viewSecretKey, derivation)) + { + throw std::runtime_error("Failed to generate key derivation"); + } + } + + // generate signature for shared secret + crypto::generate_tx_proof(prefix_hash, keys.address.viewPublicKey, txPubKey, proof.shared_secret, keys.viewSecretKey, proof.shared_secret_sig); + + // derive ephemeral secret key + crypto::KeyImage ki; + cn::KeyPair ephemeral; + + const bool r = cn::generate_key_image_helper(keys, td.transactionPublicKey, td.outputInTransaction, ephemeral, ki); + if (!r) + { + throw std::runtime_error("Failed to generate key image"); + } + + if (ephemeral.publicKey != td.outputKey) + { + throw std::runtime_error("Derived public key doesn't agree with the stored one"); + } + + // generate signature for key image + const std::vector &pubs = {&ephemeral.publicKey}; + + crypto::generate_ring_signature(prefix_hash, proof.key_image, &pubs[0], 1, ephemeral.secretKey, 0, &proof.key_image_sig); + } + // generate signature for the spend key that received those outputs + crypto::Signature signature; + crypto::generate_signature(prefix_hash, keys.address.spendPublicKey, keys.spendSecretKey, signature); + + // serialize & encode + reserve_proof p; + p.proofs.assign(proofs.begin(), proofs.end()); + memcpy(&p.signature, &signature, sizeof(signature)); + + BinaryArray ba = toBinaryArray(p); + std::string ret = common::toHex(ba); + + ret = "ReserveProofV1" + tools::base_58::encode(ret); + + return ret; + } + + bool WalletGreen::getTxProof(const crypto::Hash &transactionHash, const cn::AccountPublicAddress &address, const crypto::SecretKey &tx_key, std::string &signature) + { + const crypto::KeyImage p = *reinterpret_cast(&address.viewPublicKey); + const crypto::KeyImage k = *reinterpret_cast(&tx_key); + crypto::KeyImage pk = crypto::scalarmultKey(p, k); + crypto::PublicKey R; + crypto::PublicKey rA = reinterpret_cast(pk); + crypto::secret_key_to_public_key(tx_key, R); + crypto::Signature sig; + try + { + crypto::generate_tx_proof(transactionHash, R, address.viewPublicKey, rA, tx_key, sig); + } + catch (std::runtime_error) + { + return false; + } + + signature = std::string("ProofV1") + + tools::base_58::encode(std::string((const char *)&rA, sizeof(crypto::PublicKey))) + + tools::base_58::encode(std::string((const char *)&sig, sizeof(crypto::Signature))); + + return true; + } + /* Process transactions, this covers both new transactions AND confirmed transactions */ void WalletGreen::transactionUpdated( TransactionInformation transactionInfo, @@ -3642,11 +3889,12 @@ namespace cn void WalletGreen::addUnconfirmedTransaction(const ITransactionReader &transaction) { - platform_system::RemoteContext context(m_dispatcher, [this, &transaction] { - return m_blockchainSynchronizer.addUnconfirmedTransaction(transaction).get(); - }); + auto addUnconfirmedTransactionCompleted = std::promise(); + auto addUnconfirmedTransactionWaitFuture = addUnconfirmedTransactionCompleted.get_future(); + + addUnconfirmedTransactionWaitFuture = m_blockchainSynchronizer.addUnconfirmedTransaction(transaction); - auto ec = context.get(); + std::error_code ec = addUnconfirmedTransactionWaitFuture.get(); if (ec) { throw std::system_error(ec, "Failed to add unconfirmed transaction"); @@ -3899,7 +4147,7 @@ namespace cn return WALLET_INVALID_TRANSACTION_ID; } - typedef cn::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount outs_for_amount; + using outs_for_amount = cn::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount; std::vector mixinResult; if (mixin != 0) { @@ -3914,7 +4162,6 @@ namespace cn std::unique_ptr fusionTransaction; size_t transactionSize; int round = 0; - uint64_t transactionAmount; do { if (round != 0) @@ -3927,8 +4174,6 @@ namespace cn return amount + input.out.amount; }); - transactionAmount = inputsAmount; - ReceiverAmounts decomposedOutputs = decomposeFusionOutputs(destination, inputsAmount); assert(decomposedOutputs.amounts.size() <= MAX_FUSION_OUTPUT_COUNT); @@ -3938,13 +4183,16 @@ namespace cn transactionSize = getTransactionSize(*fusionTransaction); ++round; - } while ((transactionSize > m_currency.fusionTxMaxSize()) && (fusionInputs.size() >= m_currency.fusionTxMinInputCount())); + } while (transactionSize > m_currency.fusionTxMaxSize() && fusionInputs.size() >= m_currency.fusionTxMinInputCount()); if (fusionInputs.size() < m_currency.fusionTxMinInputCount()) { throw std::system_error(make_error_code(error::MINIMUM_INPUT_COUNT)); } - + if (fusionTransaction->getOutputCount() == 0) + { + throw std::system_error(make_error_code(error::WRONG_AMOUNT)); + } id = validateSaveAndSendTransaction(*fusionTransaction, {}, true, true); return id; } @@ -3953,9 +4201,11 @@ namespace cn { WalletGreen::ReceiverAmounts outputs; outputs.receiver = address; - - decomposeAmount(inputsAmount, 0, outputs.amounts); - std::sort(outputs.amounts.begin(), outputs.amounts.end()); + if (inputsAmount > m_currency.minimumFeeV2()) + { + decomposeAmount(inputsAmount - m_currency.minimumFeeV2(), 0, outputs.amounts); + std::sort(outputs.amounts.begin(), outputs.amounts.end()); + } return outputs; } @@ -4037,6 +4287,35 @@ namespace cn } } + size_t WalletGreen::createOptimizationTransaction(const std::string &address) + { + if (getUnspentOutputsCount() < 100) + { + throw std::system_error(make_error_code(error::NOTHING_TO_OPTIMIZE)); + return WALLET_INVALID_TRANSACTION_ID; + } + + uint64_t balance = getActualBalance(address); + uint64_t threshold = 100; + bool fusionReady = false; + while (threshold <= balance && !fusionReady) + { + EstimateResult estimation = estimate(threshold, {address}); + if (estimation.fusionReadyCount > 50) + { + fusionReady = true; + break; + } + threshold *= 10; + } + if (fusionReady) + { + return createFusionTransaction(threshold, cn::parameters::MINIMUM_MIXIN, {address}, address); + } + throw std::system_error(make_error_code(error::NOTHING_TO_OPTIMIZE)); + return WALLET_INVALID_TRANSACTION_ID; + } + void WalletGreen::validateChangeDestination(const std::vector &sourceAddresses, const std::string &changeDestination, bool isFusion) const { std::string message; @@ -4541,4 +4820,66 @@ namespace cn shutdown(); } + bool canInsertTransactionToIndex(const WalletTransaction &transaction) + { + return transaction.state == WalletTransactionState::SUCCEEDED && transaction.blockHeight != WALLET_UNCONFIRMED_TRANSACTION_HEIGHT && + transaction.totalAmount > 0 && !transaction.extra.empty(); + } + + void WalletGreen::pushToPaymentsIndex(const crypto::Hash &paymentId, size_t txId) + { + m_paymentIds[paymentId].push_back(txId); + } + + void WalletGreen::buildPaymentIds() + { + size_t begin = 0; + size_t end = getTransactionCount(); + std::vector extra; + for (auto txId = begin; txId != end; ++txId) + { + const WalletTransaction& tx = getTransaction(txId); + PaymentId paymentId; + extra.insert(extra.begin(), tx.extra.begin(), tx.extra.end()); + if (canInsertTransactionToIndex(tx) && getPaymentIdFromTxExtra(extra, paymentId)) + { + pushToPaymentsIndex(paymentId, txId); + } + extra.clear(); + } + } + + std::vector WalletGreen::getTransactionsByPaymentIds(const std::vector &paymentIds) + { + buildPaymentIds(); + std::vector payments(paymentIds.size()); + auto payment = payments.begin(); + for (auto &key : paymentIds) + { + payment->paymentId = key; + auto it = m_paymentIds.find(key); + if (it != m_paymentIds.end()) + { + std::transform(it->second.begin(), it->second.end(), std::back_inserter(payment->transactions), + [this](size_t txId) + { + return getTransaction(txId); + }); + } + + ++payment; + } + return payments; + } + + void WalletGreen::addObserver(IBlockchainSynchronizerObserver *observer) + { + m_blockchainSynchronizer.addObserver(observer); + } + + void WalletGreen::removeObserver(IBlockchainSynchronizerObserver *observer) + { + m_blockchainSynchronizer.removeObserver(observer); + } + } //namespace cn diff --git a/src/Wallet/WalletGreen.h b/src/Wallet/WalletGreen.h index 3ee8bcec7..a1e9b0fb8 100644 --- a/src/Wallet/WalletGreen.h +++ b/src/Wallet/WalletGreen.h @@ -42,6 +42,7 @@ class WalletGreen : public IWallet, void initialize(const std::string& path, const std::string& password) override; void initializeWithViewKey(const std::string& path, const std::string& password, const crypto::SecretKey& viewSecretKey) override; + void generateNewWallet(const std::string &path, const std::string &password) override; void load(const std::string& path, const std::string& password, std::string& extra) override; void load(const std::string& path, const std::string& password) override; void shutdown() override; @@ -74,6 +75,8 @@ class WalletGreen : public IWallet, uint64_t getLockedDepositBalance(const std::string &address) const override; uint64_t getUnlockedDepositBalance() const override; uint64_t getUnlockedDepositBalance(const std::string &address) const override; + uint64_t getDustBalance() const override; + uint64_t getDustBalance(const std::string &address) const override; size_t getTransactionCount() const override; WalletTransaction getTransaction(size_t transactionIndex) const override; @@ -114,6 +117,17 @@ class WalletGreen : public IWallet, TransactionId creatingTransactionId, const Currency ¤cy, uint32_t height); + std::vector getUnspentOutputs(); + size_t getUnspentOutputsCount(); + std::string getReserveProof(const std::string &address, const uint64_t &reserve, const std::string &message) override; + bool getTxProof(const crypto::Hash &transactionHash, const cn::AccountPublicAddress &address, const crypto::SecretKey &tx_key, std::string &signature) override; + crypto::SecretKey getTransactionDeterministicSecretKey(crypto::Hash &transactionHash) const override; + size_t createOptimizationTransaction(const std::string &address) override; + std::vector getTransactionsByPaymentIds(const std::vector &paymentIds) override; + + void addObserver(IBlockchainSynchronizerObserver *observer); + void removeObserver(IBlockchainSynchronizerObserver *observer); + protected: struct NewAddressData { @@ -142,7 +156,6 @@ class WalletGreen : public IWallet, void initWithKeys(const std::string& path, const std::string& password, const crypto::PublicKey& viewPublicKey, const crypto::SecretKey& viewSecretKey); std::string doCreateAddress(const crypto::PublicKey &spendPublicKey, const crypto::SecretKey &spendSecretKey, uint64_t creationTimestamp); std::vector doCreateAddressList(const std::vector &addressDataList); - crypto::SecretKey getTransactionDeterministicSecretKey(crypto::Hash &transactionHash) const; uint64_t scanHeightToTimestamp(const uint32_t scanHeight); uint64_t getCurrentTimestampAdjusted(); @@ -218,11 +231,11 @@ class WalletGreen : public IWallet, void onBlockchainDetach(const crypto::PublicKey &viewPublicKey, uint32_t blockIndex) override; void blocksRollback(uint32_t blockIndex); - void onTransactionDeleteBegin(const crypto::PublicKey &viewPublicKey, crypto::Hash transactionHash) override; - void transactionDeleteBegin(crypto::Hash transactionHash); + void onTransactionDeleteBegin(const crypto::PublicKey &viewPublicKey, const crypto::Hash &transactionHash) override; + void transactionDeleteBegin(const crypto::Hash &transactionHash); - void onTransactionDeleteEnd(const crypto::PublicKey &viewPublicKey, crypto::Hash transactionHash) override; - void transactionDeleteEnd(crypto::Hash transactionHash); + void onTransactionDeleteEnd(const crypto::PublicKey &viewPublicKey, const crypto::Hash &transactionHash) override; + void transactionDeleteEnd(const crypto::Hash &transactionHash); std::vector pickWalletsWithMoney() const; WalletOuts pickWallet(const std::string &address) const; @@ -338,7 +351,7 @@ class WalletGreen : public IWallet, std::vector pickRandomFusionInputs(const std::vector &addresses, uint64_t threshold, size_t minInputCount, size_t maxInputCount); - static ReceiverAmounts decomposeFusionOutputs(const AccountPublicAddress &address, uint64_t inputsAmount); + ReceiverAmounts decomposeFusionOutputs(const AccountPublicAddress &address, uint64_t inputsAmount); enum class WalletState { @@ -370,6 +383,8 @@ class WalletGreen : public IWallet, void deleteContainerFromUnlockTransactionJobs(const ITransfersContainer *container); std::vector deleteTransfersForAddress(const std::string &address, std::vector &deletedTransactions); void deleteFromUncommitedTransactions(const std::vector &deletedTransactions); + void pushToPaymentsIndex(const crypto::Hash &paymentId, size_t txId); + void buildPaymentIds(); private: platform_system::Dispatcher &m_dispatcher; @@ -413,6 +428,7 @@ class WalletGreen : public IWallet, uint32_t m_transactionSoftLockTime; BlockHashesContainer m_blockchain; + WalletPaymentIds m_paymentIds; }; } //namespace cn diff --git a/src/Wallet/WalletIndices.h b/src/Wallet/WalletIndices.h index 246cb878d..67399172c 100644 --- a/src/Wallet/WalletIndices.h +++ b/src/Wallet/WalletIndices.h @@ -140,5 +140,7 @@ struct EncryptedWalletRecord { boost::multi_index::tag, boost::multi_index::identity>>> BlockHashesContainer; + + using WalletPaymentIds = std::unordered_map, boost::hash>; } // namespace cn diff --git a/src/Wallet/WalletUtils.cpp b/src/Wallet/WalletUtils.cpp index e0ae5dc3f..3c5544cb4 100644 --- a/src/Wallet/WalletUtils.cpp +++ b/src/Wallet/WalletUtils.cpp @@ -7,9 +7,16 @@ #include "WalletUtils.h" +#include + +#include + +#include "Common/Util.h" #include "CryptoNote.h" #include "crypto/crypto.h" #include "Wallet/WalletErrors.h" +#include "Wallet/LegacyKeysImporter.h" + namespace cn { @@ -26,4 +33,39 @@ void throwIfKeysMissmatch(const crypto::SecretKey& secretKey, const crypto::Publ } } + void importLegacyKeys(const std::string &legacyKeysFile, const std::string &filename, const std::string &password) + { + std::stringstream archive; + + cn::importLegacyKeys(legacyKeysFile, password, archive); + + std::fstream walletFile; + createWalletFile(walletFile, filename); + + archive.flush(); + walletFile << archive.rdbuf(); + walletFile.flush(); + } + + void createWalletFile(std::fstream &walletFile, const std::string &filename) + { + boost::filesystem::path pathToWalletFile(filename); + boost::filesystem::path directory = pathToWalletFile.parent_path(); + if (!directory.empty() && !tools::directoryExists(directory.string())) + { + throw std::runtime_error("Directory does not exist: " + directory.string()); + } + + walletFile.open(filename.c_str(), std::fstream::in | std::fstream::out | std::fstream::binary); + if (walletFile) + { + walletFile.close(); + throw std::runtime_error("Wallet file already exists"); + } + + walletFile.open(filename.c_str(), std::fstream::out); + walletFile.close(); + + walletFile.open(filename.c_str(), std::fstream::in | std::fstream::out | std::fstream::binary); + } } diff --git a/src/Wallet/WalletUtils.h b/src/Wallet/WalletUtils.h index 0caac4399..756f6dac9 100644 --- a/src/Wallet/WalletUtils.h +++ b/src/Wallet/WalletUtils.h @@ -15,4 +15,6 @@ namespace cn { bool validateAddress(const std::string& address, const cn::Currency& currency); void throwIfKeysMissmatch(const crypto::SecretKey& secretKey, const crypto::PublicKey& expectedPublicKey, const std::string& message = ""); +void importLegacyKeys(const std::string &legacyKeysFile, const std::string &filename, const std::string &password); +void createWalletFile(std::fstream &walletFile, const std::string &filename); } diff --git a/tests/UnitTests/TestWalletService.cpp b/tests/UnitTests/TestWalletService.cpp index 74c64be98..27c410335 100644 --- a/tests/UnitTests/TestWalletService.cpp +++ b/tests/UnitTests/TestWalletService.cpp @@ -42,6 +42,7 @@ struct IWalletBaseStub : public cn::IWallet, public cn::IFusionManager { virtual void initialize(const std::string& path, const std::string& password) override { } virtual void initializeWithViewKey(const std::string& path, const std::string& password, const crypto::SecretKey& viewSecretKey) override { } + virtual void generateNewWallet(const std::string &path, const std::string &password) override { }; virtual void load(const std::string& path, const std::string& password) override { } virtual void shutdown() override { } @@ -62,6 +63,8 @@ struct IWalletBaseStub : public cn::IWallet, public cn::IFusionManager { virtual uint64_t getActualBalance(const std::string& address) const override { return 0; } virtual uint64_t getPendingBalance() const override { return 0; } virtual uint64_t getPendingBalance(const std::string& address) const override { return 0; } + virtual uint64_t getDustBalance() const override { return 0; }; + virtual uint64_t getDustBalance(const std::string &address) const override { return 0; } virtual size_t getTransactionCount() const override { return 0; } virtual WalletTransaction getTransaction(size_t transactionIndex) const override { return WalletTransaction(); } @@ -82,6 +85,13 @@ struct IWalletBaseStub : public cn::IWallet, public cn::IFusionManager { virtual void commitTransaction(size_t transactionId) override { } virtual void rollbackUncommitedTransaction(size_t transactionId) override { } + virtual std::string getReserveProof(const std::string &address, const uint64_t &reserve, const std::string &message) override { return ""; } + virtual bool getTxProof(const crypto::Hash &transactionHash, const cn::AccountPublicAddress &address, const crypto::SecretKey &tx_key, std::string &signature) override { return true; } + + virtual crypto::SecretKey getTransactionDeterministicSecretKey(crypto::Hash &transactionHash) const { return cn::NULL_SECRET_KEY; } + virtual size_t createOptimizationTransaction(const std::string &address) {return 0; }; + virtual std::vector getTransactionsByPaymentIds(const std::vector &paymentIds) { return std::vector{}; }; + virtual void start() override { m_stopped = false; } virtual void stop() override { m_stopped = true; m_eventOccurred.set(); } From 5668b5056c7d6b8b74e89f3a4a5449e0deee853d Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sat, 1 Apr 2023 17:42:51 +0200 Subject: [PATCH 04/17] Migrate concealwallet to walletgreen --- include/IWallet.h | 8 ++++++++ src/ConcealWallet/ConcealWallet.cpp | 1 + src/ConcealWallet/ConcealWallet.h | 6 ++++-- src/Wallet/WalletGreen.h | 8 ++++---- tests/UnitTests/TestWalletService.cpp | 6 ++++++ 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/include/IWallet.h b/include/IWallet.h index 3d285a7bf..19de73502 100644 --- a/include/IWallet.h +++ b/include/IWallet.h @@ -177,6 +177,9 @@ struct PaymentIdTransactions std::vector transactions; }; +class TransactionOutputInformation; +class IBlockchainSynchronizerObserver; + class IWallet { public: @@ -248,12 +251,17 @@ class IWallet virtual void commitTransaction(size_t transactionId) = 0; virtual void rollbackUncommitedTransaction(size_t transactionId) = 0; + virtual std::vector getUnspentOutputs() = 0; + virtual size_t getUnspentOutputsCount() = 0; virtual std::string getReserveProof(const std::string &address, const uint64_t &reserve, const std::string &message) = 0; virtual bool getTxProof(const crypto::Hash &transactionHash, const cn::AccountPublicAddress &address, const crypto::SecretKey &tx_key, std::string &signature) = 0; virtual crypto::SecretKey getTransactionDeterministicSecretKey(crypto::Hash &transactionHash) const = 0; virtual size_t createOptimizationTransaction(const std::string &address) = 0; virtual std::vector getTransactionsByPaymentIds(const std::vector &paymentIds) = 0; + virtual void addObserver(IBlockchainSynchronizerObserver *observer) = 0; + virtual void removeObserver(IBlockchainSynchronizerObserver *observer) = 0; + virtual void start() = 0; virtual void stop() = 0; diff --git a/src/ConcealWallet/ConcealWallet.cpp b/src/ConcealWallet/ConcealWallet.cpp index 92d44cdf1..f8b53fe04 100644 --- a/src/ConcealWallet/ConcealWallet.cpp +++ b/src/ConcealWallet/ConcealWallet.cpp @@ -40,6 +40,7 @@ #include "Rpc/HttpClient.h" #include "CryptoNoteCore/CryptoNoteTools.h" +#include "Wallet/WalletGreen.h" #include "Wallet/WalletRpcServer.h" #include "Wallet/WalletUtils.h" #include "Wallet/LegacyKeysImporter.h" diff --git a/src/ConcealWallet/ConcealWallet.h b/src/ConcealWallet/ConcealWallet.h index bb5e2847e..c5253d2d7 100644 --- a/src/ConcealWallet/ConcealWallet.h +++ b/src/ConcealWallet/ConcealWallet.h @@ -14,7 +14,7 @@ #include -#include "Wallet/WalletGreen.h" +#include "IWallet.h" #include "PasswordContainer.h" #include "ClientHelper.h" @@ -23,10 +23,12 @@ #include "CryptoNoteCore/Currency.h" #include "NodeRpcProxy/NodeRpcProxy.h" #include "WalletLegacy/WalletHelper.h" +#include "Transfers/IBlockchainSynchronizer.h" #include #include +#include #include #include @@ -178,7 +180,7 @@ namespace cn cn::client_helper m_chelper; std::unique_ptr m_node; - std::unique_ptr m_wallet; + std::unique_ptr m_wallet; refresh_progress_reporter_t m_refresh_progress_reporter; bool m_walletSynchronized; diff --git a/src/Wallet/WalletGreen.h b/src/Wallet/WalletGreen.h index a1e9b0fb8..b65508006 100644 --- a/src/Wallet/WalletGreen.h +++ b/src/Wallet/WalletGreen.h @@ -117,16 +117,16 @@ class WalletGreen : public IWallet, TransactionId creatingTransactionId, const Currency ¤cy, uint32_t height); - std::vector getUnspentOutputs(); - size_t getUnspentOutputsCount(); + std::vector getUnspentOutputs() override; + size_t getUnspentOutputsCount() override; std::string getReserveProof(const std::string &address, const uint64_t &reserve, const std::string &message) override; bool getTxProof(const crypto::Hash &transactionHash, const cn::AccountPublicAddress &address, const crypto::SecretKey &tx_key, std::string &signature) override; crypto::SecretKey getTransactionDeterministicSecretKey(crypto::Hash &transactionHash) const override; size_t createOptimizationTransaction(const std::string &address) override; std::vector getTransactionsByPaymentIds(const std::vector &paymentIds) override; - void addObserver(IBlockchainSynchronizerObserver *observer); - void removeObserver(IBlockchainSynchronizerObserver *observer); + void addObserver(IBlockchainSynchronizerObserver *observer) override; + void removeObserver(IBlockchainSynchronizerObserver *observer) override; protected: struct NewAddressData diff --git a/tests/UnitTests/TestWalletService.cpp b/tests/UnitTests/TestWalletService.cpp index 27c410335..4b3041350 100644 --- a/tests/UnitTests/TestWalletService.cpp +++ b/tests/UnitTests/TestWalletService.cpp @@ -20,6 +20,7 @@ #include "PaymentGate/WalletServiceErrorCategory.h" #include "INodeStubs.h" #include "Wallet/WalletErrors.h" +#include "ITransfersContainer.h" using namespace cn; using namespace payment_service; @@ -85,6 +86,8 @@ struct IWalletBaseStub : public cn::IWallet, public cn::IFusionManager { virtual void commitTransaction(size_t transactionId) override { } virtual void rollbackUncommitedTransaction(size_t transactionId) override { } + std::vector getUnspentOutputs() override { return std::vector{}; }; + size_t getUnspentOutputsCount() override { return 0; }; virtual std::string getReserveProof(const std::string &address, const uint64_t &reserve, const std::string &message) override { return ""; } virtual bool getTxProof(const crypto::Hash &transactionHash, const cn::AccountPublicAddress &address, const crypto::SecretKey &tx_key, std::string &signature) override { return true; } @@ -92,6 +95,9 @@ struct IWalletBaseStub : public cn::IWallet, public cn::IFusionManager { virtual size_t createOptimizationTransaction(const std::string &address) {return 0; }; virtual std::vector getTransactionsByPaymentIds(const std::vector &paymentIds) { return std::vector{}; }; + virtual void addObserver(IBlockchainSynchronizerObserver *observer) override{}; + virtual void removeObserver(IBlockchainSynchronizerObserver *observer) override{}; + virtual void start() override { m_stopped = false; } virtual void stop() override { m_stopped = true; m_eventOccurred.set(); } From b5f9481e2c7465e495352adcbc85b02c3cf89c4a Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sun, 2 Apr 2023 19:28:58 +0200 Subject: [PATCH 05/17] Observable wallet --- include/IWallet.h | 31 +++++++-- src/ConcealWallet/ConcealWallet.cpp | 53 ++++++++++++++++ src/ConcealWallet/ConcealWallet.h | 17 ++++- src/Transfers/IObservableImpl.h | 4 +- src/Wallet/WalletGreen.cpp | 91 +++++++++++++-------------- src/Wallet/WalletGreen.h | 11 +++- tests/UnitTests/TestWalletService.cpp | 4 +- 7 files changed, 150 insertions(+), 61 deletions(-) diff --git a/include/IWallet.h b/include/IWallet.h index 19de73502..d975060b5 100644 --- a/include/IWallet.h +++ b/include/IWallet.h @@ -13,11 +13,13 @@ #include #include "CryptoNote.h" #include "CryptoNoteConfig.h" +#include "IObservable.h" namespace cn { -typedef size_t DepositId; +using DepositId = size_t; +using TransactionId = size_t; const size_t WALLET_INVALID_TRANSACTION_ID = std::numeric_limits::max(); const size_t WALLET_INVALID_TRANSFER_ID = std::numeric_limits::max(); @@ -180,7 +182,29 @@ struct PaymentIdTransactions class TransactionOutputInformation; class IBlockchainSynchronizerObserver; -class IWallet +class IWalletObserver +{ +public: + virtual ~IWalletObserver() = default; + + virtual void initCompleted(std::error_code result) = 0; + virtual void saveCompleted(std::error_code result) = 0; + virtual void synchronizationProgressUpdated(uint32_t current, uint32_t total) = 0; + virtual void synchronizationCompleted(std::error_code result) = 0; + virtual void actualBalanceUpdated(uint64_t balance) = 0; + virtual void pendingBalanceUpdated(uint64_t balance) = 0; + virtual void actualDepositBalanceUpdated(uint64_t balance) = 0; + virtual void pendingDepositBalanceUpdated(uint64_t balance) = 0; + virtual void actualInvestmentBalanceUpdated(uint64_t balance) = 0; + virtual void pendingInvestmentBalanceUpdated(uint64_t balance) = 0; + virtual void externalTransactionCreated(TransactionId transactionId) = 0; + virtual void sendTransactionCompleted(TransactionId transactionId, std::error_code result) = 0; + virtual void transactionUpdated(TransactionId transactionId) = 0; + virtual void depositUpdated(DepositId depositId) = 0; + virtual void depositsUpdated(const std::vector &depositIds) = 0; +}; + +class IWallet : public IObservable { public: virtual ~IWallet() = default; @@ -259,9 +283,6 @@ class IWallet virtual size_t createOptimizationTransaction(const std::string &address) = 0; virtual std::vector getTransactionsByPaymentIds(const std::vector &paymentIds) = 0; - virtual void addObserver(IBlockchainSynchronizerObserver *observer) = 0; - virtual void removeObserver(IBlockchainSynchronizerObserver *observer) = 0; - virtual void start() = 0; virtual void stop() = 0; diff --git a/src/ConcealWallet/ConcealWallet.cpp b/src/ConcealWallet/ConcealWallet.cpp index f8b53fe04..06f7bb1cd 100644 --- a/src/ConcealWallet/ConcealWallet.cpp +++ b/src/ConcealWallet/ConcealWallet.cpp @@ -1793,4 +1793,57 @@ bool conceal_wallet::check_address(const std::vector &args) logger(INFO) << "The wallet " << addr << " seems to be valid, please still be cautious still."; return true; +} + +void conceal_wallet::initCompleted(std::error_code result) +{ + // Nothing to do here +} +void conceal_wallet::saveCompleted(std::error_code result) +{ + // Nothing to do here +} +void conceal_wallet::actualBalanceUpdated(uint64_t balance) +{ + // Nothing to do here +} +void conceal_wallet::pendingBalanceUpdated(uint64_t balance) +{ + // Nothing to do here +} +void conceal_wallet::actualDepositBalanceUpdated(uint64_t balance) +{ + // Nothing to do here +} +void conceal_wallet::pendingDepositBalanceUpdated(uint64_t balance) +{ + // Nothing to do here +} +void conceal_wallet::actualInvestmentBalanceUpdated(uint64_t balance) +{ + // Nothing to do here +} +void conceal_wallet::pendingInvestmentBalanceUpdated(uint64_t balance) +{ + // Nothing to do here +} +void conceal_wallet::externalTransactionCreated(TransactionId transactionId) +{ + // Nothing to do here +} +void conceal_wallet::sendTransactionCompleted(TransactionId transactionId, std::error_code result) +{ + // Nothing to do here +} +void conceal_wallet::transactionUpdated(TransactionId transactionId) +{ + // Nothing to do here +} +void conceal_wallet::depositUpdated(DepositId depositId) +{ + // Nothing to do here +} +void conceal_wallet::depositsUpdated(const std::vector &depositIds) +{ + // Nothing to do here } \ No newline at end of file diff --git a/src/ConcealWallet/ConcealWallet.h b/src/ConcealWallet/ConcealWallet.h index c5253d2d7..ae3f87d07 100644 --- a/src/ConcealWallet/ConcealWallet.h +++ b/src/ConcealWallet/ConcealWallet.h @@ -37,7 +37,7 @@ namespace cn /************************************************************************/ /* */ /************************************************************************/ - class conceal_wallet : public IBlockchainSynchronizerObserver { + class conceal_wallet : public IWalletObserver { public: conceal_wallet(platform_system::Dispatcher& dispatcher, const cn::Currency& currency, logging::LoggerManager& log); @@ -115,8 +115,21 @@ namespace cn void printConnectionError() const; std::string get_wallet_keys() const; + void initCompleted(std::error_code result) override; + void saveCompleted(std::error_code result) override; + void synchronizationProgressUpdated(uint32_t current, uint32_t total) override; void synchronizationCompleted(std::error_code result) override; - void synchronizationProgressUpdated(uint32_t processedBlockCount, uint32_t totalBlockCount) override; + void actualBalanceUpdated(uint64_t balance) override; + void pendingBalanceUpdated(uint64_t balance) override; + void actualDepositBalanceUpdated(uint64_t balance) override; + void pendingDepositBalanceUpdated(uint64_t balance) override; + void actualInvestmentBalanceUpdated(uint64_t balance) override; + void pendingInvestmentBalanceUpdated(uint64_t balance) override; + void externalTransactionCreated(TransactionId transactionId) override; + void sendTransactionCompleted(TransactionId transactionId, std::error_code result) override; + void transactionUpdated(TransactionId transactionId) override; + void depositUpdated(DepositId depositId) override; + void depositsUpdated(const std::vector &depositIds) override; friend class refresh_progress_reporter_t; diff --git a/src/Transfers/IObservableImpl.h b/src/Transfers/IObservableImpl.h index fd94aa2d4..43b7ba772 100644 --- a/src/Transfers/IObservableImpl.h +++ b/src/Transfers/IObservableImpl.h @@ -15,11 +15,11 @@ template class IObservableImpl : public Base { public: - virtual void addObserver(Observer* observer) override { + void addObserver(Observer* observer) override { m_observerManager.add(observer); } - virtual void removeObserver(Observer* observer) override { + void removeObserver(Observer* observer) override { m_observerManager.remove(observer); } diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index ca976e522..37ba81c77 100644 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -137,49 +137,6 @@ namespace } } - cn::WalletEvent makeTransactionUpdatedEvent(size_t id) - { - cn::WalletEvent event; - event.type = cn::WalletEventType::TRANSACTION_UPDATED; - event.transactionUpdated.transactionIndex = id; - - return event; - } - - cn::WalletEvent makeTransactionCreatedEvent(size_t id) - { - cn::WalletEvent event; - event.type = cn::WalletEventType::TRANSACTION_CREATED; - event.transactionCreated.transactionIndex = id; - - return event; - } - - cn::WalletEvent makeMoneyUnlockedEvent() - { - cn::WalletEvent event; - event.type = cn::WalletEventType::BALANCE_UNLOCKED; - - return event; - } - - cn::WalletEvent makeSyncProgressUpdatedEvent(uint32_t current, uint32_t total) - { - cn::WalletEvent event; - event.type = cn::WalletEventType::SYNC_PROGRESS_UPDATED; - event.synchronizationProgressUpdated.processedBlockCount = current; - event.synchronizationProgressUpdated.totalBlockCount = total; - return event; - } - - cn::WalletEvent makeSyncCompletedEvent() - { - cn::WalletEvent event; - event.type = cn::WalletEventType::SYNC_COMPLETED; - - return event; - } - size_t getTransactionSize(const ITransactionReader &transaction) { return transaction.getTransactionData().size(); @@ -943,12 +900,14 @@ namespace cn catch (const std::exception &e) { m_logger(ERROR, BRIGHT_RED) << "Failed to save container: " << e.what(); + m_observerManager.notify(&IWalletObserver::saveCompleted, make_error_code(cn::error::INTERNAL_WALLET_ERROR)); startBlockchainSynchronizer(); throw; } startBlockchainSynchronizer(); m_logger(INFO, BRIGHT_WHITE) << "Container saved"; + m_observerManager.notify(&IWalletObserver::saveCompleted, std::error_code()); } void WalletGreen::copyContainerStorageKeys(ContainerStorage &src, const chacha8_key &srcKey, ContainerStorage &dst, const chacha8_key &dstKey) @@ -3285,6 +3244,7 @@ namespace cn void WalletGreen::synchronizationCompleted(std::error_code result) { + m_observerManager.notify(&IWalletObserver::synchronizationCompleted, result); m_dispatcher.remoteSpawn([this]() { onSynchronizationCompleted(); }); } @@ -4025,6 +3985,10 @@ namespace cn << m_currency.formatAmount(m_pendingBalance) << ", locked deposits " << m_currency.formatAmount(m_lockedDepositBalance) << ",unlocked deposits " << m_currency.formatAmount(m_unlockedDepositBalance); + m_observerManager.notify(&IWalletObserver::actualBalanceUpdated, actual); + m_observerManager.notify(&IWalletObserver::pendingBalanceUpdated, pending); + m_observerManager.notify(&IWalletObserver::actualDepositBalanceUpdated, locked); + m_observerManager.notify(&IWalletObserver::pendingDepositBalanceUpdated, unlocked); } } @@ -4872,14 +4836,47 @@ namespace cn return payments; } - void WalletGreen::addObserver(IBlockchainSynchronizerObserver *observer) + cn::WalletEvent WalletGreen::makeTransactionUpdatedEvent(size_t id) { - m_blockchainSynchronizer.addObserver(observer); + cn::WalletEvent event; + event.type = cn::WalletEventType::TRANSACTION_UPDATED; + event.transactionUpdated.transactionIndex = id; + m_observerManager.notify(&IWalletObserver::transactionUpdated, id); + return event; } - void WalletGreen::removeObserver(IBlockchainSynchronizerObserver *observer) + cn::WalletEvent WalletGreen::makeTransactionCreatedEvent(size_t id) { - m_blockchainSynchronizer.removeObserver(observer); + cn::WalletEvent event; + event.type = cn::WalletEventType::TRANSACTION_CREATED; + event.transactionCreated.transactionIndex = id; + m_observerManager.notify(&IWalletObserver::sendTransactionCompleted, id, std::error_code()); + return event; + } + + cn::WalletEvent WalletGreen::makeMoneyUnlockedEvent() + { + cn::WalletEvent event; + event.type = cn::WalletEventType::BALANCE_UNLOCKED; + + return event; + } + + cn::WalletEvent WalletGreen::makeSyncProgressUpdatedEvent(uint32_t current, uint32_t total) + { + cn::WalletEvent event; + event.type = cn::WalletEventType::SYNC_PROGRESS_UPDATED; + event.synchronizationProgressUpdated.processedBlockCount = current; + event.synchronizationProgressUpdated.totalBlockCount = total; + m_observerManager.notify(&IWalletObserver::synchronizationProgressUpdated, current, total); + return event; + } + + cn::WalletEvent WalletGreen::makeSyncCompletedEvent() + { + cn::WalletEvent event; + event.type = cn::WalletEventType::SYNC_COMPLETED; + return event; } } //namespace cn diff --git a/src/Wallet/WalletGreen.h b/src/Wallet/WalletGreen.h index b65508006..854d4f188 100644 --- a/src/Wallet/WalletGreen.h +++ b/src/Wallet/WalletGreen.h @@ -20,11 +20,12 @@ #include #include "Transfers/TransfersSynchronizer.h" #include "Transfers/BlockchainSynchronizer.h" +#include "Transfers/IObservableImpl.h" namespace cn { -class WalletGreen : public IWallet, +class WalletGreen : public IObservableImpl, public ITransfersObserver, public IBlockchainSynchronizerObserver, public ITransfersSynchronizerObserver, @@ -125,8 +126,6 @@ class WalletGreen : public IWallet, size_t createOptimizationTransaction(const std::string &address) override; std::vector getTransactionsByPaymentIds(const std::vector &paymentIds) override; - void addObserver(IBlockchainSynchronizerObserver *observer) override; - void removeObserver(IBlockchainSynchronizerObserver *observer) override; protected: struct NewAddressData @@ -386,6 +385,12 @@ class WalletGreen : public IWallet, void pushToPaymentsIndex(const crypto::Hash &paymentId, size_t txId); void buildPaymentIds(); + cn::WalletEvent makeTransactionUpdatedEvent(size_t id); + cn::WalletEvent makeTransactionCreatedEvent(size_t id); + cn::WalletEvent makeMoneyUnlockedEvent(); + cn::WalletEvent makeSyncProgressUpdatedEvent(uint32_t current, uint32_t total); + cn::WalletEvent makeSyncCompletedEvent(); + private: platform_system::Dispatcher &m_dispatcher; const Currency &m_currency; diff --git a/tests/UnitTests/TestWalletService.cpp b/tests/UnitTests/TestWalletService.cpp index 4b3041350..326a3601d 100644 --- a/tests/UnitTests/TestWalletService.cpp +++ b/tests/UnitTests/TestWalletService.cpp @@ -95,8 +95,8 @@ struct IWalletBaseStub : public cn::IWallet, public cn::IFusionManager { virtual size_t createOptimizationTransaction(const std::string &address) {return 0; }; virtual std::vector getTransactionsByPaymentIds(const std::vector &paymentIds) { return std::vector{}; }; - virtual void addObserver(IBlockchainSynchronizerObserver *observer) override{}; - virtual void removeObserver(IBlockchainSynchronizerObserver *observer) override{}; + virtual void addObserver(IWalletObserver *observer) override{}; + virtual void removeObserver(IWalletObserver *observer) override{}; virtual void start() override { m_stopped = false; } virtual void stop() override { m_stopped = true; m_eventOccurred.set(); } From f27c97df395cdf4f303d898b0bbb3119190e9260 Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sat, 8 Apr 2023 10:17:46 +0200 Subject: [PATCH 06/17] Format timestamp as string --- src/Common/StringTools.cpp | 15 +++++++++- src/Common/StringTools.h | 2 ++ src/ConcealWallet/ClientHelper.cpp | 15 +--------- src/ConcealWallet/ConcealWallet.cpp | 15 +--------- src/CryptoNoteCore/TransactionPool.cpp | 38 ++------------------------ src/CryptoNoteCore/UpgradeDetector.h | 16 ++--------- 6 files changed, 22 insertions(+), 79 deletions(-) diff --git a/src/Common/StringTools.cpp b/src/Common/StringTools.cpp index 34375b760..accf28829 100644 --- a/src/Common/StringTools.cpp +++ b/src/Common/StringTools.cpp @@ -7,6 +7,7 @@ #include "StringTools.h" #include +#include namespace common { @@ -348,5 +349,17 @@ std::string makeCenteredString(size_t width, const std::string& text) { return std::string(offset, ' ') + text + std::string(width - text.size() - offset, ' '); } - +std::string formatTimestamp(time_t timestamp) +{ + std::string buffer(32, '\0'); + struct tm time_info; +#ifdef _WIN32 + gmtime_s(&time_info, ×tamp); +#else + gmtime_r(×tamp, &time_info); +#endif + std::strftime(&buffer[0], buffer.size(), "%c", &time_info); + buffer += " UTC"; + return buffer; +} } diff --git a/src/Common/StringTools.h b/src/Common/StringTools.h index 89ff42111..47aadec32 100644 --- a/src/Common/StringTools.h +++ b/src/Common/StringTools.h @@ -108,4 +108,6 @@ std::string timeIntervalToString(uint64_t intervalInSeconds); std::string makeCenteredString(size_t width, const std::string& text); +std::string formatTimestamp(time_t timestamp); + } \ No newline at end of file diff --git a/src/ConcealWallet/ClientHelper.cpp b/src/ConcealWallet/ClientHelper.cpp index 14e39d194..4f594d81e 100644 --- a/src/ConcealWallet/ClientHelper.cpp +++ b/src/ConcealWallet/ClientHelper.cpp @@ -3,7 +3,6 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include #include #include #include @@ -175,19 +174,7 @@ namespace cn crypto::Hash paymentId; std::string paymentIdStr = (cn::getPaymentIdFromTxExtra(extraVec, paymentId) && paymentId != NULL_HASH ? podToHex(paymentId) : ""); - char timeString[32 + 1]; - time_t timestamp = static_cast(txInfo.timestamp); - struct tm time; -#ifdef _WIN32 - gmtime_s(&time, ×tamp); -#else - gmtime_r(×tamp, &time); -#endif - - if (!std::strftime(timeString, sizeof(timeString), "%c", &time)) - { - throw std::runtime_error("time buffer is too small"); - } + std::string timeString = formatTimestamp(static_cast(txInfo.timestamp)); std::string format_amount = currency.formatAmount(txInfo.totalAmount); diff --git a/src/ConcealWallet/ConcealWallet.cpp b/src/ConcealWallet/ConcealWallet.cpp index 06f7bb1cd..36982953d 100644 --- a/src/ConcealWallet/ConcealWallet.cpp +++ b/src/ConcealWallet/ConcealWallet.cpp @@ -9,7 +9,6 @@ #include "TransferCmd.h" #include "Const.h" -#include #include #include #include @@ -106,19 +105,7 @@ void printListTransfersItem(LoggerRef& logger, const WalletTransaction& txInfo, crypto::Hash paymentId; std::string paymentIdStr = (getPaymentIdFromTxExtra(extraVec, paymentId) && paymentId != NULL_HASH ? common::podToHex(paymentId) : ""); - char timeString[TIMESTAMP_MAX_WIDTH + 1]; - time_t timestamp = static_cast(txInfo.timestamp); - struct tm time; -#ifdef _WIN32 - gmtime_s(&time, ×tamp); -#else - gmtime_r(×tamp, &time); -#endif - - if (!std::strftime(timeString, sizeof(timeString), "%c", &time)) - { - throw std::runtime_error("time buffer is too small"); - } + std::string timeString = formatTimestamp(static_cast(txInfo.timestamp)); std::string rowColor = txInfo.totalAmount < 0 ? MAGENTA : GREEN; logger(INFO, rowColor) diff --git a/src/CryptoNoteCore/TransactionPool.cpp b/src/CryptoNoteCore/TransactionPool.cpp index ea75c48e7..d5beffd82 100644 --- a/src/CryptoNoteCore/TransactionPool.cpp +++ b/src/CryptoNoteCore/TransactionPool.cpp @@ -8,7 +8,6 @@ #include "TransactionPool.h" #include -#include #include #include @@ -451,45 +450,12 @@ namespace cn ss << "blobSize: " << txd.blobSize << std::endl << "fee: " << m_currency.formatAmount(txd.fee) << std::endl - << "received: "; - - char receivedTimeStr[32]; - struct tm receivedTimeTm; -#ifdef _WIN32 - gmtime_s(&receivedTimeTm, &txd.receiveTime); -#else - gmtime_r(&txd.receiveTime, &receivedTimeTm); -#endif - if (std::strftime(receivedTimeStr, sizeof(receivedTimeStr), "%c", &receivedTimeTm)) - { - ss << receivedTimeStr << " UTC"; - } - else - { - ss << "unable to get time"; - } - ss << std::endl; + << "received: " << common::formatTimestamp(txd.receiveTime) << std::endl; auto ttlIt = m_ttlIndex.find(txd.id); if (ttlIt != m_ttlIndex.end()) { - char ttlTimeStr[32]; - struct tm ttlTimeTm; - time_t timestamp = reinterpret_cast(&ttlIt->second); -#ifdef _WIN32 - gmtime_s(&ttlTimeTm, ×tamp); -#else - gmtime_r(×tamp, &ttlTimeTm); -#endif - if (std::strftime(ttlTimeStr, sizeof(ttlTimeStr), "%c", &ttlTimeTm)) - { - ss << "TTL: " << ttlTimeStr << " UTC"; - } - else - { - ss << "TTL failed"; - } - ss << std::endl; + ss << "TTL: " << common::formatTimestamp(static_cast(ttlIt->second)) << std::endl; } } return ss.str(); diff --git a/src/CryptoNoteCore/UpgradeDetector.h b/src/CryptoNoteCore/UpgradeDetector.h index 9c432da59..4ebd1b57e 100644 --- a/src/CryptoNoteCore/UpgradeDetector.h +++ b/src/CryptoNoteCore/UpgradeDetector.h @@ -9,7 +9,6 @@ #include #include -#include #include "Common/StringTools.h" #include "CryptoNoteCore/CryptoNoteBasicImpl.h" @@ -126,21 +125,10 @@ namespace cn { if (m_blockchain.size() % (60 * 60 / m_currency.difficultyTarget()) == 0) { auto interval = m_currency.difficultyTarget() * (upgradeHeight() - m_blockchain.size() + 2); - char upgradeTimeStr[32]; - struct tm upgradeTimeTm; time_t upgradeTimestamp = time(nullptr) + static_cast(interval); -#ifdef _WIN32 - gmtime_s(&upgradeTimeTm, &upgradeTimestamp); -#else - gmtime_r(&upgradeTimestamp, &upgradeTimeTm); -#endif - if (!std::strftime(upgradeTimeStr, sizeof(upgradeTimeStr), "%c", &upgradeTimeTm)) - { - throw std::runtime_error("time buffer is too small"); - } - + std::string upgradeTime = common::formatTimestamp(upgradeTimestamp); logger(logging::TRACE, logging::BRIGHT_GREEN) << "###### UPGRADE is going to happen after block index " << upgradeHeight() << " at about " << - upgradeTimeStr << " UTC" << " (in " << common::timeIntervalToString(interval) << ")! Current last block index " << (m_blockchain.size() - 1) << + upgradeTime << " (in " << common::timeIntervalToString(interval) << ")! Current last block index " << (m_blockchain.size() - 1) << ", hash " << get_block_hash(m_blockchain.back().bl); } } else if (m_blockchain.size() == upgradeHeight() + 1) { From c5b35b891795ffac6d75451e5b517e7fc2a20ffb Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sun, 9 Apr 2023 14:47:03 +0200 Subject: [PATCH 07/17] Include system_error --- include/IWallet.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/IWallet.h b/include/IWallet.h index 4183bb112..02a2586b7 100644 --- a/include/IWallet.h +++ b/include/IWallet.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include "CryptoNote.h" From 52ae8391c66824218a6085a8248f0496cb7a0058 Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sun, 9 Apr 2023 16:07:37 +0200 Subject: [PATCH 08/17] Fix WalletGreen warnings --- include/IWallet.h | 2 +- src/Wallet/WalletGreen.cpp | 231 +++++++++++--------------- src/Wallet/WalletGreen.h | 44 ++--- src/Wallet/WalletSerializationV1.cpp | 2 +- src/Wallet/WalletSerializationV1.h | 2 +- tests/UnitTests/TestWalletService.cpp | 2 +- 6 files changed, 122 insertions(+), 161 deletions(-) diff --git a/include/IWallet.h b/include/IWallet.h index 02a2586b7..867e60838 100644 --- a/include/IWallet.h +++ b/include/IWallet.h @@ -211,7 +211,7 @@ class IWallet : public IObservable virtual ~IWallet() = default; virtual void initialize(const std::string& path, const std::string& password) = 0; - virtual void createDeposit(uint64_t amount, uint64_t term, std::string sourceAddress, std::string destinationAddress, std::string &transactionHash) = 0; + virtual void createDeposit(uint64_t amount, uint32_t term, std::string sourceAddress, std::string destinationAddress, std::string &transactionHash) = 0; virtual void withdrawDeposit(DepositId depositId, std::string &transactionHash) = 0; virtual Deposit getDeposit(size_t depositIndex) const = 0; virtual void initializeWithViewKey(const std::string& path, const std::string& password, const crypto::SecretKey& viewSecretKey) = 0; diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index 010757ef8..97cf7bf97 100644 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -54,8 +54,8 @@ namespace decompose_amount_into_digits( amount, dustThreshold, - [&](uint64_t chunk) { amounts.push_back(chunk); }, - [&](uint64_t dust) { amounts.push_back(dust); }); + [&amounts](uint64_t chunk) { amounts.push_back(chunk); }, + [&amounts](uint64_t dust) { amounts.push_back(dust); }); return amounts; } @@ -63,10 +63,10 @@ namespace uint64_t calculateDepositsAmount( const std::vector &transfers, const cn::Currency ¤cy, - const std::vector heights) + const std::vector &heights) { int index = 0; - return std::accumulate(transfers.begin(), transfers.end(), static_cast(0), [¤cy, &index, heights](uint64_t sum, const cn::TransactionOutputInformation &deposit) { + return std::accumulate(transfers.begin(), transfers.end(), static_cast(0), [¤cy, &index, &heights](uint64_t sum, const cn::TransactionOutputInformation &deposit) { return sum + deposit.amount + currency.calculateInterest(deposit.amount, deposit.term, heights[index++]); }); } @@ -104,9 +104,9 @@ namespace } //to supress warning - uint64_t uamount = static_cast(transfer.amount); - neededMoney += uamount; - if (neededMoney < uamount) + auto amount = static_cast(transfer.amount); + neededMoney += amount; + if (neededMoney < amount) { throw std::system_error(make_error_code(cn::error::SUM_OVERFLOW)); } @@ -121,10 +121,10 @@ namespace return neededMoney; } - void checkIfEnoughMixins(std::vector &mixinResult, uint64_t mixIn) + void checkIfEnoughMixins(std::vector &mixinResult, uint64_t mixIn) { auto notEnoughIt = std::find_if(mixinResult.begin(), mixinResult.end(), - [mixIn](const cn::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount &ofa) { return ofa.outs.size() < mixIn; }); + [mixIn](const outs_for_amount &ofa) { return ofa.outs.size() < mixIn; }); if (mixIn == 0 && mixinResult.empty()) { @@ -233,17 +233,10 @@ namespace cn m_currency(currency), m_node(node), m_logger(logger, "WalletGreen"), - m_stopped(false), - m_blockchainSynchronizerStarted(false), m_blockchainSynchronizer(node, currency.genesisBlockHash()), m_synchronizer(currency, logger, m_blockchainSynchronizer, node), m_eventOccurred(m_dispatcher), m_readyEvent(m_dispatcher), - m_state(WalletState::NOT_INITIALIZED), - m_actualBalance(0), - m_pendingBalance(0), - m_lockedDepositBalance(0), - m_unlockedDepositBalance(0), m_transactionSoftLockTime(transactionSoftLockTime) { m_upperTransactionSizeLimit = m_currency.transactionMaxSize(); @@ -305,7 +298,7 @@ namespace cn std::vector selectedTransfers; const auto &wallet = getWalletRecord(address); - ITransfersContainer *container = wallet.container; + const ITransfersContainer *container = wallet.container; AccountKeys account = makeAccountKeys(wallet); ITransfersContainer::TransferState state; TransactionOutputInformation transfer; @@ -367,7 +360,7 @@ namespace cn } transactionHash = common::podToHex(transaction->getTransactionHash()); - size_t id = validateSaveAndSendTransaction(*transaction, {}, false, true); + validateSaveAndSendTransaction(*transaction, {}, false, true); } crypto::SecretKey WalletGreen::getTransactionDeterministicSecretKey(crypto::Hash &transactionHash) const @@ -401,7 +394,7 @@ namespace cn return txKey; } - std::vector WalletGreen::prepareMultisignatureInputs(const std::vector &selectedTransfers) + std::vector WalletGreen::prepareMultisignatureInputs(const std::vector &selectedTransfers) const { std::vector inputs; inputs.reserve(selectedTransfers.size()); @@ -413,7 +406,7 @@ namespace cn MultisignatureInput input; input.amount = output.amount; - input.signatureCount = output.requiredSignatures; + input.signatureCount = static_cast(output.requiredSignatures); input.outputIndex = output.globalOutputIndex; input.term = output.term; @@ -425,7 +418,7 @@ namespace cn void WalletGreen::createDeposit( uint64_t amount, - uint64_t term, + uint32_t term, std::string sourceAddress, std::string destinationAddress, std::string &transactionHash) @@ -467,7 +460,7 @@ namespace cn std::vector selectedTransfers; uint64_t foundMoney = selectTransfers(neededMoney, m_currency.defaultDustThreshold(), - std::move(wallets), + wallets, selectedTransfers); /* Do we have enough funds */ @@ -480,27 +473,18 @@ namespace cn which includes the term, and then after that the change outputs */ /* Add the deposit outputs to the transaction */ - auto depositIndex = transaction->addOutput( + transaction->addOutput( neededMoney - fee, {destAddr}, 1, term); /* Let's add the change outputs to the transaction */ - - std::vector amounts; - - /* Breakdown the change into specific amounts */ - decompose_amount_into_digits( - foundMoney - neededMoney, - m_currency.defaultDustThreshold(), - [&](uint64_t chunk) { amounts.push_back(chunk); }, - [&](uint64_t dust) { amounts.push_back(dust); }); - std::vector decomposedChange = amounts; + std::vector decomposedChange = split(foundMoney - neededMoney, m_currency.defaultDustThreshold()); /* Now pair each of those amounts to the change address which in the case of a deposit is the source address */ - typedef std::pair AmountToAddress; + using AmountToAddress = std::pair; std::vector amountsToAddresses; for (const auto &output : decomposedChange) { @@ -555,7 +539,6 @@ namespace cn /* Prepare the inputs */ /* Get additional inputs for the mixin */ - typedef cn::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount outs_for_amount; std::vector mixinResult; requestMixinOuts(selectedTransfers, cn::parameters::MINIMUM_MIXIN, mixinResult); std::vector keysInfo; @@ -570,14 +553,14 @@ namespace cn /* Now sign the inputs so we can proceed with the transaction */ size_t i = 0; - for (auto &input : keysInfo) + for (const auto &input : keysInfo) { transaction->signInputKey(i++, input.keyInfo, input.ephKeys); } /* Return the transaction hash */ transactionHash = common::podToHex(transaction->getTransactionHash()); - size_t id = validateSaveAndSendTransaction(*transaction, {}, false, true); + validateSaveAndSendTransaction(*transaction, {}, false, true); } void WalletGreen::validateOrders(const std::vector &orders) const @@ -739,13 +722,13 @@ namespace cn void WalletGreen::initBlockchain(const crypto::PublicKey &viewPublicKey) { - std::vector blockchain = m_synchronizer.getViewKeyKnownBlocks(m_viewPublicKey); + std::vector blockchain = m_synchronizer.getViewKeyKnownBlocks(viewPublicKey); m_blockchain.insert(m_blockchain.end(), blockchain.begin(), blockchain.end()); } void WalletGreen::deleteOrphanTransactions(const std::unordered_set &deletedKeys) { - for (auto spendPublicKey : deletedKeys) + for (const auto &spendPublicKey : deletedKeys) { AccountPublicAddress deletedAccountAddress; deletedAccountAddress.spendPublicKey = spendPublicKey; @@ -857,7 +840,7 @@ namespace cn ContainerStorage newStorage(path, common::FileMappedVectorOpenMode::CREATE, sizeof(ContainerStoragePrefix)); ContainerStoragePrefix *prefix = reinterpret_cast(newStorage.prefix()); - prefix->version = static_cast(WalletSerializerV2::SERIALIZATION_VERSION); + prefix->version = WalletSerializerV2::SERIALIZATION_VERSION; prefix->nextIv = crypto::rand(); crypto::cn_context cnContext; @@ -910,7 +893,7 @@ namespace cn m_observerManager.notify(&IWalletObserver::saveCompleted, std::error_code()); } - void WalletGreen::copyContainerStorageKeys(ContainerStorage &src, const chacha8_key &srcKey, ContainerStorage &dst, const chacha8_key &dstKey) + void WalletGreen::copyContainerStorageKeys(const ContainerStorage &src, const chacha8_key &srcKey, ContainerStorage &dst, const chacha8_key &dstKey) const { dst.reserve(src.size()); @@ -920,9 +903,7 @@ namespace cn dst.flush(); }); - size_t counter = 0; - - for (auto &encryptedSpendKeys : src) + for (const auto &encryptedSpendKeys : src) { crypto::PublicKey publicKey; crypto::SecretKey secretKey; @@ -940,7 +921,7 @@ namespace cn void WalletGreen::copyContainerStoragePrefix(ContainerStorage &src, const chacha8_key &srcKey, ContainerStorage &dst, const chacha8_key &dstKey) { - ContainerStoragePrefix *srcPrefix = reinterpret_cast(src.prefix()); + const ContainerStoragePrefix *srcPrefix = reinterpret_cast(src.prefix()); ContainerStoragePrefix *dstPrefix = reinterpret_cast(dst.prefix()); dstPrefix->version = srcPrefix->version; dstPrefix->nextIv = crypto::randomChachaIV(); @@ -1045,7 +1026,7 @@ namespace cn prefix->nextIv = crypto::randomChachaIV(); uint64_t creationTimestamp = time(nullptr); prefix->encryptedViewKeys = encryptKeyPair(m_viewPublicKey, m_viewSecretKey, creationTimestamp); - for (auto spendKeys : m_walletsContainer.get()) + for (const auto &spendKeys : m_walletsContainer.get()) { m_containerStorage.push_back(encryptKeyPair(spendKeys.spendPublicKey, spendKeys.spendSecretKey, spendKeys.creationTimestamp)); incNextIv(); @@ -1126,7 +1107,7 @@ namespace cn { m_containerStorage.open(path, FileMappedVectorOpenMode::OPEN, sizeof(ContainerStoragePrefix)); - ContainerStoragePrefix *prefix = reinterpret_cast(m_containerStorage.prefix()); + const ContainerStoragePrefix *prefix = reinterpret_cast(m_containerStorage.prefix()); assert(prefix->version >= WalletSerializerV2::MIN_VERSION); uint64_t creationTimestamp; @@ -1266,16 +1247,16 @@ namespace cn { std::vector subscriptionList; m_synchronizer.getSubscriptions(subscriptionList); - for (auto &addr : subscriptionList) + for (const auto &addr : subscriptionList) { auto sub = m_synchronizer.getSubscription(addr); if (sub != nullptr) { std::vector allTransfers; - ITransfersContainer *container = &sub->getContainer(); + const ITransfersContainer *container = &sub->getContainer(); container->getOutputs(allTransfers, ITransfersContainer::IncludeAll); m_logger(INFO, BRIGHT_WHITE) << "Known Transfers " << allTransfers.size(); - for (auto &o : allTransfers) + for (const auto &o : allTransfers) { if (o.type != transaction_types::OutputType::Invalid) { @@ -1386,10 +1367,8 @@ namespace cn auto &subscription = m_synchronizer.addSubscription(sub); bool r = index.modify(it, [&subscription](WalletRecord &rec) { rec.container = &subscription.getContainer(); }); + (void)r; assert(r); - if (r) - { - }; subscription.addObserver(this); } } @@ -1399,7 +1378,7 @@ namespace cn std::vector subscriptionList; m_synchronizer.getSubscriptions(subscriptionList); - for (auto &subscription : subscriptionList) + for (const auto &subscription : subscriptionList) { m_synchronizer.removeSubscription(subscription); } @@ -1499,7 +1478,7 @@ namespace cn { KeyPair spendKey; crypto::generate_keys(spendKey.publicKey, spendKey.secretKey); - uint64_t creationTimestamp = static_cast(time(nullptr)); + auto creationTimestamp = static_cast(time(nullptr)); return doCreateAddress(spendKey.publicKey, spendKey.secretKey, creationTimestamp); } @@ -1511,7 +1490,7 @@ namespace cn { throw std::system_error(make_error_code(cn::error::KEY_GENERATION_ERROR)); } - uint64_t creationTimestamp = static_cast(time(nullptr)); + auto creationTimestamp = static_cast(time(nullptr)); return doCreateAddress(spendPublicKey, spendSecretKey, creationTimestamp); } @@ -1521,7 +1500,7 @@ namespace cn { throw std::system_error(make_error_code(error::WRONG_PARAMETERS), "Wrong public key format"); } - uint64_t creationTimestamp = static_cast(time(nullptr)); + auto creationTimestamp = static_cast(time(nullptr)); return doCreateAddress(spendPublicKey, NULL_SECRET_KEY, creationTimestamp); } @@ -1959,14 +1938,13 @@ namespace cn preparedTransaction.neededMoney = countNeededMoney(preparedTransaction.destinations, fee); std::vector selectedTransfers; - uint64_t foundMoney = selectTransfers(preparedTransaction.neededMoney, m_currency.defaultDustThreshold(), std::move(wallets), selectedTransfers); + uint64_t foundMoney = selectTransfers(preparedTransaction.neededMoney, m_currency.defaultDustThreshold(), wallets, selectedTransfers); if (foundMoney < preparedTransaction.neededMoney) { throw std::system_error(make_error_code(error::WRONG_AMOUNT), "Not enough money"); } - typedef cn::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount outs_for_amount; std::vector mixinResult; if (mixIn != 0) @@ -2048,13 +2026,8 @@ namespace cn size_t WalletGreen::makeTransaction(const TransactionParameters &sendingTransaction) { size_t id = WALLET_INVALID_TRANSACTION_ID; - tools::ScopeExit releaseContext([this, &id] { + tools::ScopeExit releaseContext([this] { m_dispatcher.yield(); - - if (id != WALLET_INVALID_TRANSACTION_ID) - { - auto &tx = m_transactions[id]; - } }); platform_system::EventLock lk(m_readyEvent); @@ -2228,7 +2201,7 @@ namespace cn updated = true; } }); - + (void)r; assert(r); return updated; @@ -2292,7 +2265,7 @@ namespace cn updated = true; } }); - + (void)r; assert(r); return updated; @@ -2330,7 +2303,7 @@ namespace cn return txId; } - uint64_t WalletGreen::scanHeightToTimestamp(const uint32_t scanHeight) + uint64_t WalletGreen::scanHeightToTimestamp(const uint32_t scanHeight) const { if (scanHeight == 0) { @@ -2355,7 +2328,7 @@ namespace cn return timestamp; } - uint64_t WalletGreen::getCurrentTimestampAdjusted() + uint64_t WalletGreen::getCurrentTimestampAdjusted() const { /* Get the current time as a unix timestamp */ std::time_t time = std::time(nullptr); @@ -2658,7 +2631,7 @@ namespace cn bool eraseOutputTransfers) { - return eraseTransfers(transactionId, firstTransferIdx, [this, &knownAddresses, eraseOutputTransfers](bool isOutput, const std::string &transferAddress) { + return eraseTransfers(transactionId, firstTransferIdx, [&knownAddresses, eraseOutputTransfers](bool isOutput, const std::string &transferAddress) { return eraseOutputTransfers == isOutput && knownAddresses.count(transferAddress) == 0; }); } @@ -2732,7 +2705,7 @@ namespace cn throwIfStopped(); auto relayTransactionCompleted = std::promise(); auto relayTransactionWaitFuture = relayTransactionCompleted.get_future(); - m_node.relayTransaction(cryptoNoteTransaction, [&ec, &relayTransactionCompleted, this](std::error_code error) + m_node.relayTransaction(cryptoNoteTransaction, [&ec, &relayTransactionCompleted](std::error_code) { auto detachedPromise = std::move(relayTransactionCompleted); detachedPromise.set_value(ec); @@ -2825,7 +2798,7 @@ namespace cn void WalletGreen::requestMixinOuts( const std::vector &selectedTransfers, uint64_t mixIn, - std::vector &mixinResult) + std::vector &mixinResult) { std::vector amounts; @@ -2841,7 +2814,7 @@ namespace cn auto getRandomOutsByAmountsCompleted = std::promise(); auto getRandomOutsByAmountsWaitFuture = getRandomOutsByAmountsCompleted.get_future(); - m_node.getRandomOutsByAmounts(std::move(amounts), mixIn, mixinResult, [&getRandomOutsByAmountsCompleted, &mixinError, this](std::error_code ec) { + m_node.getRandomOutsByAmounts(std::move(amounts), mixIn, mixinResult, [&getRandomOutsByAmountsCompleted](std::error_code ec) { auto detachedPromise = std::move(getRandomOutsByAmountsCompleted); detachedPromise.set_value(ec); }); @@ -2858,27 +2831,27 @@ namespace cn uint64_t WalletGreen::selectTransfers( uint64_t neededMoney, uint64_t dustThreshold, - std::vector &&wallets, - std::vector &selectedTransfers) + const std::vector &wallets, + std::vector &selectedTransfers) const { uint64_t foundMoney = 0; - typedef std::pair OutputData; + using OutputData = std::pair; std::vector walletOuts; std::unordered_map> buckets; - for (auto walletIt = wallets.begin(); walletIt != wallets.end(); ++walletIt) + for (const auto &wallet : wallets) { - for (auto outIt = walletIt->outs.begin(); outIt != walletIt->outs.end(); ++outIt) + for (const auto &out : wallet.outs) { - int numberOfDigits = floor(log10(outIt->amount)) + 1; + auto numberOfDigits = static_cast(floor(log10(out.amount)) + 1); - if (outIt->amount > dustThreshold) + if (out.amount > dustThreshold) { buckets[numberOfDigits].emplace_back( std::piecewise_construct, - std::forward_as_tuple(walletIt->wallet), - std::forward_as_tuple(*outIt)); + std::forward_as_tuple(wallet.wallet), + std::forward_as_tuple(out)); } } } @@ -2926,14 +2899,14 @@ namespace cn continue; } - ITransfersContainer *container = wallet.container; + const ITransfersContainer *container = wallet.container; WalletOuts outs; container->getOutputs(outs.outs, ITransfersContainer::IncludeKeyUnlocked); outs.wallet = const_cast(&wallet); walletOuts.push_back(std::move(outs)); - }; + } return walletOuts; } @@ -2942,7 +2915,7 @@ namespace cn { const auto &wallet = getWalletRecord(address); - ITransfersContainer *container = wallet.container; + const ITransfersContainer *container = wallet.container; WalletOuts outs; container->getOutputs(outs.outs, ITransfersContainer::IncludeKeyUnlocked); outs.wallet = const_cast(&wallet); @@ -2969,7 +2942,7 @@ namespace cn std::vector WalletGreen::splitDestinations(const std::vector &destinations, uint64_t dustThreshold, - const cn::Currency ¤cy) + const cn::Currency ¤cy) const { std::vector decomposedOutputs; @@ -2986,7 +2959,7 @@ namespace cn cn::WalletGreen::ReceiverAmounts WalletGreen::splitAmount( uint64_t amount, const AccountPublicAddress &destination, - uint64_t dustThreshold) + uint64_t dustThreshold) const { ReceiverAmounts receiverAmounts; @@ -2998,12 +2971,12 @@ namespace cn void WalletGreen::prepareInputs( const std::vector &selectedTransfers, - std::vector &mixinResult, + std::vector &mixinResult, uint64_t mixIn, - std::vector &keysInfo) + std::vector &keysInfo) const { - typedef cn::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry out_entry; + using out_entry = cn::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry; size_t i = 0; for (const auto &input : selectedTransfers) @@ -3015,9 +2988,8 @@ namespace cn { std::sort(mixinResult[i].outs.begin(), mixinResult[i].outs.end(), [](const out_entry &a, const out_entry &b) { return a.global_amount_index < b.global_amount_index; }); - for (auto &fakeOut : mixinResult[i].outs) + for (const auto &fakeOut : mixinResult[i].outs) { - if (input.out.globalOutputIndex == fakeOut.global_amount_index) { continue; @@ -3025,10 +2997,12 @@ namespace cn transaction_types::GlobalOutput globalOutput; globalOutput.outputIndex = static_cast(fakeOut.global_amount_index); - globalOutput.targetKey = reinterpret_cast(fakeOut.out_key); + globalOutput.targetKey = fakeOut.out_key; keyInfo.outputs.push_back(std::move(globalOutput)); if (keyInfo.outputs.size() >= mixIn) + { break; + } } } @@ -3039,7 +3013,7 @@ namespace cn transaction_types::GlobalOutput realOutput; realOutput.outputIndex = input.out.globalOutputIndex; - realOutput.targetKey = reinterpret_cast(input.out.outputKey); + realOutput.targetKey = input.out.outputKey; auto insertedIn = keyInfo.outputs.insert(insertIn, realOutput); @@ -3089,7 +3063,7 @@ namespace cn auto heightIt = m_blockchain.project(it); - uint32_t blockIndex = static_cast(std::distance(m_blockchain.get().begin(), heightIt)); + auto blockIndex = static_cast(std::distance(m_blockchain.get().begin(), heightIt)); return getTransactionsInBlocks(blockIndex, count); } @@ -3107,7 +3081,7 @@ namespace cn auto heightIt = m_blockchain.project(it); - uint32_t blockIndex = static_cast(std::distance(m_blockchain.get().begin(), heightIt)); + auto blockIndex = static_cast(std::distance(m_blockchain.get().begin(), heightIt)); return getDepositsInBlocks(blockIndex, count); } @@ -3149,7 +3123,7 @@ namespace cn throwIfNotInitialized(); throwIfStopped(); - uint32_t blockCount = static_cast(m_blockchain.size()); + auto blockCount = static_cast(m_blockchain.size()); assert(blockCount != 0); return blockCount; @@ -3235,6 +3209,7 @@ namespace cn void WalletGreen::onError(ITransfersSubscription *object, uint32_t height, std::error_code ec) { + // Do nothing } void WalletGreen::synchronizationProgressUpdated(uint32_t processedBlockCount, uint32_t totalBlockCount) @@ -3313,7 +3288,7 @@ namespace cn void WalletGreen::onTransactionDeleteBegin(const crypto::PublicKey &viewPublicKey, const crypto::Hash &transactionHash) { - m_dispatcher.remoteSpawn([=]() { transactionDeleteBegin(transactionHash); }); + m_dispatcher.remoteSpawn([this, &transactionHash]() { transactionDeleteBegin(transactionHash); }); } // TODO remove @@ -3323,7 +3298,7 @@ namespace cn void WalletGreen::onTransactionDeleteEnd(const crypto::PublicKey &viewPublicKey, const crypto::Hash &transactionHash) { - m_dispatcher.remoteSpawn([=]() { transactionDeleteEnd(transactionHash); }); + m_dispatcher.remoteSpawn([this, &transactionHash]() { transactionDeleteEnd(transactionHash); }); } // TODO remove @@ -3370,9 +3345,7 @@ namespace cn // transaction uint64_t outputsAmount; bool found = container->getTransactionInformation(transactionHash, info, &inputsAmount, &outputsAmount); - if (found) - { - } + (void)found; assert(found); ContainerAmounts containerAmounts; @@ -3542,7 +3515,7 @@ namespace cn proof.txid = td.transactionHash; proof.index_in_tx = td.outputInTransaction; - auto txPubKey = td.transactionPublicKey; + const auto& txPubKey = td.transactionPublicKey; for (int i = 0; i < 2; ++i) { @@ -3609,7 +3582,7 @@ namespace cn { crypto::generate_tx_proof(transactionHash, R, address.viewPublicKey, rA, tx_key, sig); } - catch (std::runtime_error) + catch (std::runtime_error&) { return false; } @@ -3657,7 +3630,7 @@ namespace cn m_fusionTxsCache.emplace(transactionId, isFusionTransaction(*it)); } - for (auto containerAmounts : containerAmountsList) + for (const auto& containerAmounts : containerAmountsList) { auto newDepositOuts = containerAmounts.container->getTransactionOutputs(transactionInfo.transactionHash, ITransfersContainer::IncludeTypeDeposit | ITransfersContainer::IncludeStateAll); auto spentDepositOutputs = containerAmounts.container->getTransactionInputs(transactionInfo.transactionHash, ITransfersContainer::IncludeTypeDeposit); @@ -3665,7 +3638,7 @@ namespace cn std::vector updatedDepositIds; /* Check for new deposits in this transaction, and create them */ - for (size_t i = 0; i < newDepositOuts.size(); i++) + for (const auto& depositOutput: newDepositOuts) { /* We only add confirmed deposit entries, so this condition prevents the same deposit in the deposit index during creation and during confirmation */ @@ -3673,14 +3646,14 @@ namespace cn { continue; } - auto id = insertNewDeposit(newDepositOuts[i], transactionId, m_currency, transactionInfo.blockHeight); + auto id = insertNewDeposit(depositOutput, transactionId, m_currency, transactionInfo.blockHeight); updatedDepositIds.push_back(id); } /* Now check for any deposit withdrawals in the transactions */ - for (size_t i = 0; i < spentDepositOutputs.size(); i++) + for (const auto& depositOutput: spentDepositOutputs) { - auto depositId = getDepositId(spentDepositOutputs[i].transactionHash); + auto depositId = getDepositId(depositOutput.transactionHash); assert(depositId != WALLET_INVALID_DEPOSIT_ID); if (depositId == WALLET_INVALID_DEPOSIT_ID) { @@ -4065,13 +4038,8 @@ namespace cn { size_t id = WALLET_INVALID_TRANSACTION_ID; - tools::ScopeExit releaseContext([this, &id] { + tools::ScopeExit releaseContext([this] { m_dispatcher.yield(); - - if (id != WALLET_INVALID_TRANSACTION_ID) - { - auto &tx = m_transactions[id]; - } }); platform_system::EventLock lk(m_readyEvent); @@ -4111,7 +4079,6 @@ namespace cn return WALLET_INVALID_TRANSACTION_ID; } - using outs_for_amount = cn::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount; std::vector mixinResult; if (mixin != 0) { @@ -4161,7 +4128,7 @@ namespace cn return id; } - WalletGreen::ReceiverAmounts WalletGreen::decomposeFusionOutputs(const AccountPublicAddress &address, uint64_t inputsAmount) + WalletGreen::ReceiverAmounts WalletGreen::decomposeFusionOutputs(const AccountPublicAddress &address, uint64_t inputsAmount) const { WalletGreen::ReceiverAmounts outputs; outputs.receiver = address; @@ -4337,9 +4304,9 @@ namespace cn auto walletOuts = sourceAddresses.empty() ? pickWalletsWithMoney() : pickWallets(sourceAddresses); std::array::digits10 + 1> bucketSizes; bucketSizes.fill(0); - for (size_t walletIndex = 0; walletIndex < walletOuts.size(); ++walletIndex) + for (const auto &wallet : walletOuts) { - for (auto &out : walletOuts[walletIndex].outs) + for (const auto &out : wallet.outs) { uint8_t powerOfTen = 0; if (m_currency.isAmountApplicableInFusionTransactionInput(out.amount, threshold, powerOfTen, m_node.getLastKnownBlockHeight())) @@ -4349,7 +4316,7 @@ namespace cn } } - result.totalOutputCount += walletOuts[walletIndex].outs.size(); + result.totalOutputCount += wallet.outs.size(); } for (auto bucketSize : bucketSizes) @@ -4364,21 +4331,21 @@ namespace cn } std::vector WalletGreen::pickRandomFusionInputs(const std::vector &addresses, - uint64_t threshold, size_t minInputCount, size_t maxInputCount) + uint64_t threshold, size_t minInputCount, size_t maxInputCount) const { std::vector allFusionReadyOuts; auto walletOuts = addresses.empty() ? pickWalletsWithMoney() : pickWallets(addresses); std::array::digits10 + 1> bucketSizes; bucketSizes.fill(0); - for (size_t walletIndex = 0; walletIndex < walletOuts.size(); ++walletIndex) + for (auto &walletOut : walletOuts) { - for (auto &out : walletOuts[walletIndex].outs) + for (auto &out : walletOut.outs) { uint8_t powerOfTen = 0; if (m_currency.isAmountApplicableInFusionTransactionInput(out.amount, threshold, powerOfTen, m_node.getLastKnownBlockHeight())) { - allFusionReadyOuts.push_back({std::move(out), walletOuts[walletIndex].wallet}); + allFusionReadyOuts.push_back({std::move(out), walletOut.wallet}); assert(powerOfTen < std::numeric_limits::digits10 + 1); bucketSizes[powerOfTen]++; } @@ -4415,11 +4382,11 @@ namespace cn uint64_t upperBound = selectedBucket == std::numeric_limits::digits10 ? UINT64_MAX : lowerBound * 10; std::vector selectedOuts; selectedOuts.reserve(bucketSizes[selectedBucket]); - for (size_t outIndex = 0; outIndex < allFusionReadyOuts.size(); ++outIndex) + for (auto& output: allFusionReadyOuts) { - if (allFusionReadyOuts[outIndex].out.amount >= lowerBound && allFusionReadyOuts[outIndex].out.amount < upperBound) + if (output.out.amount >= lowerBound && output.out.amount < upperBound) { - selectedOuts.push_back(std::move(allFusionReadyOuts[outIndex])); + selectedOuts.push_back(std::move(output)); } } @@ -4459,7 +4426,7 @@ namespace cn } auto &blockHeightIndex = m_deposits.get(); - uint32_t stopIndex = static_cast(std::min(m_blockchain.size(), blockIndex + count)); + auto stopIndex = static_cast(std::min(m_blockchain.size(), blockIndex + count)); for (uint32_t height = blockIndex; height < stopIndex; ++height) { @@ -4495,7 +4462,7 @@ namespace cn } auto &blockHeightIndex = m_transactions.get(); - uint32_t stopIndex = static_cast(std::min(m_blockchain.size(), blockIndex + count)); + auto stopIndex = static_cast(std::min(m_blockchain.size(), blockIndex + count)); for (uint32_t height = blockIndex; height < stopIndex; ++height) { @@ -4586,12 +4553,6 @@ namespace cn } } - void WalletGreen::getViewKeyKnownBlocks(const crypto::PublicKey &viewPublicKey) - { - std::vector blockchain = m_synchronizer.getViewKeyKnownBlocks(m_viewPublicKey); - m_blockchain.insert(m_blockchain.end(), blockchain.begin(), blockchain.end()); - } - ///pre: changeDestinationAddress belongs to current container ///pre: source address belongs to current container cn::AccountPublicAddress WalletGreen::getChangeDestination(const std::string &changeDestinationAddress, const std::vector &sourceAddresses) const diff --git a/src/Wallet/WalletGreen.h b/src/Wallet/WalletGreen.h index 424766ec3..be031daca 100644 --- a/src/Wallet/WalletGreen.h +++ b/src/Wallet/WalletGreen.h @@ -24,6 +24,7 @@ namespace cn { + using outs_for_amount= cn::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount; class WalletGreen : public IObservableImpl, public ITransfersObserver, @@ -36,9 +37,9 @@ class WalletGreen : public IObservableImpl, ~WalletGreen() override; /* Deposit related functions */ - void createDeposit(uint64_t amount, uint64_t term, std::string sourceAddress, std::string destinationAddress, std::string &transactionHash) override; + void createDeposit(uint64_t amount, uint32_t term, std::string sourceAddress, std::string destinationAddress, std::string &transactionHash) override; void withdrawDeposit(DepositId depositId, std::string &transactionHash) override; - std::vector prepareMultisignatureInputs(const std::vector &selectedTransfers); + std::vector prepareMultisignatureInputs(const std::vector &selectedTransfers) const; void initialize(const std::string& path, const std::string& password) override; @@ -156,8 +157,8 @@ class WalletGreen : public IObservableImpl, std::string doCreateAddress(const crypto::PublicKey &spendPublicKey, const crypto::SecretKey &spendSecretKey, uint64_t creationTimestamp); std::vector doCreateAddressList(const std::vector &addressDataList); - uint64_t scanHeightToTimestamp(const uint32_t scanHeight); - uint64_t getCurrentTimestampAdjusted(); + uint64_t scanHeightToTimestamp(const uint32_t scanHeight) const; + uint64_t getCurrentTimestampAdjusted() const; struct InputInfo { @@ -284,21 +285,21 @@ class WalletGreen : public IObservableImpl, void requestMixinOuts(const std::vector &selectedTransfers, uint64_t mixIn, - std::vector &mixinResult); + std::vector &mixinResult); void prepareInputs(const std::vector &selectedTransfers, - std::vector &mixinResult, + std::vector &mixinResult, uint64_t mixIn, - std::vector &keysInfo); + std::vector &keysInfo) const; uint64_t selectTransfers(uint64_t needeMoney, uint64_t dustThreshold, - std::vector &&wallets, - std::vector &selectedTransfers); + const std::vector &wallets, + std::vector &selectedTransfers) const; std::vector splitDestinations(const std::vector &destinations, - uint64_t dustThreshold, const Currency ¤cy); - ReceiverAmounts splitAmount(uint64_t amount, const AccountPublicAddress &destination, uint64_t dustThreshold); + uint64_t dustThreshold, const Currency ¤cy) const; + ReceiverAmounts splitAmount(uint64_t amount, const AccountPublicAddress &destination, uint64_t dustThreshold) const; std::unique_ptr makeTransaction(const std::vector &decomposedOutputs, std::vector &keysInfo, const std::vector &messages, const std::string &extra, uint64_t unlockTimestamp, crypto::SecretKey &transactionSK); @@ -337,7 +338,7 @@ class WalletGreen : public IObservableImpl, static void encryptAndSaveContainerData(ContainerStorage& storage, const crypto::chacha8_key& key, const void* containerData, size_t containerDataSize); void loadWalletCache(std::unordered_set& addedKeys, std::unordered_set& deletedKeys, std::string& extra); - void copyContainerStorageKeys(ContainerStorage& src, const crypto::chacha8_key& srcKey, ContainerStorage& dst, const crypto::chacha8_key& dstKey); + void copyContainerStorageKeys(const ContainerStorage& src, const crypto::chacha8_key& srcKey, ContainerStorage& dst, const crypto::chacha8_key& dstKey) const; static void copyContainerStoragePrefix(ContainerStorage& src, const crypto::chacha8_key& srcKey, ContainerStorage& dst, const crypto::chacha8_key& dstKey); void deleteOrphanTransactions(const std::unordered_set &deletedKeys); @@ -348,9 +349,9 @@ class WalletGreen : public IObservableImpl, void subscribeWallets(); std::vector pickRandomFusionInputs(const std::vector &addresses, - uint64_t threshold, size_t minInputCount, size_t maxInputCount); + uint64_t threshold, size_t minInputCount, size_t maxInputCount) const; - ReceiverAmounts decomposeFusionOutputs(const AccountPublicAddress &address, uint64_t inputsAmount); + ReceiverAmounts decomposeFusionOutputs(const AccountPublicAddress &address, uint64_t inputsAmount) const; enum class WalletState { @@ -375,7 +376,6 @@ class WalletGreen : public IObservableImpl, std::vector getTransactionTransfers(const WalletTransaction &transaction) const; void filterOutTransactions(WalletTransactions &transactions, WalletTransfers &transfers, std::function &&pred) const; void initBlockchain(const crypto::PublicKey& viewPublicKey); - void getViewKeyKnownBlocks(const crypto::PublicKey &viewPublicKey); cn::AccountPublicAddress getChangeDestination(const std::string &changeDestinationAddress, const std::vector &sourceAddresses) const; bool isMyAddress(const std::string &address) const; @@ -396,7 +396,7 @@ class WalletGreen : public IObservableImpl, const Currency &m_currency; INode &m_node; mutable logging::LoggerRef m_logger; - bool m_stopped; + bool m_stopped = false; WalletDeposits m_deposits; WalletsContainer m_walletsContainer; ContainerStorage m_containerStorage; @@ -406,7 +406,7 @@ class WalletGreen : public IObservableImpl, mutable std::unordered_map m_fusionTxsCache; // txIndex -> isFusion UncommitedTransactions m_uncommitedTransactions; - bool m_blockchainSynchronizerStarted; + bool m_blockchainSynchronizerStarted = false; BlockchainSynchronizer m_blockchainSynchronizer; TransfersSyncronizer m_synchronizer; @@ -414,7 +414,7 @@ class WalletGreen : public IObservableImpl, std::queue m_events; mutable platform_system::Event m_readyEvent; - WalletState m_state; + WalletState m_state = WalletState::NOT_INITIALIZED; std::string m_password; crypto::chacha8_key m_key; @@ -424,10 +424,10 @@ class WalletGreen : public IObservableImpl, crypto::PublicKey m_viewPublicKey; crypto::SecretKey m_viewSecretKey; - uint64_t m_actualBalance; - uint64_t m_pendingBalance; - uint64_t m_lockedDepositBalance; - uint64_t m_unlockedDepositBalance; + uint64_t m_actualBalance = 0; + uint64_t m_pendingBalance = 0; + uint64_t m_lockedDepositBalance = 0; + uint64_t m_unlockedDepositBalance = 0; uint64_t m_upperTransactionSizeLimit; uint32_t m_transactionSoftLockTime; diff --git a/src/Wallet/WalletSerializationV1.cpp b/src/Wallet/WalletSerializationV1.cpp index 07496ea78..333014797 100644 --- a/src/Wallet/WalletSerializationV1.cpp +++ b/src/Wallet/WalletSerializationV1.cpp @@ -264,7 +264,7 @@ cn::WalletTransfer convert(const cn::WalletLegacyTransfer& tr) { namespace cn { -const uint32_t WalletSerializer::SERIALIZATION_VERSION = 5; +const uint8_t WalletSerializer::SERIALIZATION_VERSION = 5; void CryptoContext::incIv() { uint64_t * i = reinterpret_cast(&iv.data[0]); diff --git a/src/Wallet/WalletSerializationV1.h b/src/Wallet/WalletSerializationV1.h index 9513f9391..b35806d52 100644 --- a/src/Wallet/WalletSerializationV1.h +++ b/src/Wallet/WalletSerializationV1.h @@ -48,7 +48,7 @@ class WalletSerializer void load(const crypto::chacha8_key &key, common::IInputStream &source); private: - static const uint32_t SERIALIZATION_VERSION; + static const uint8_t SERIALIZATION_VERSION; void loadWallet(common::IInputStream &source, const crypto::chacha8_key &key, uint32_t version); void loadWalletV1(common::IInputStream &source, const crypto::chacha8_key &key); diff --git a/tests/UnitTests/TestWalletService.cpp b/tests/UnitTests/TestWalletService.cpp index 277837ce3..392bcc31e 100644 --- a/tests/UnitTests/TestWalletService.cpp +++ b/tests/UnitTests/TestWalletService.cpp @@ -101,7 +101,7 @@ struct IWalletBaseStub : public cn::IWallet, public cn::IFusionManager { virtual void start() override { m_stopped = false; } virtual void stop() override { m_stopped = true; m_eventOccurred.set(); } - void createDeposit(uint64_t amount, uint64_t term, std::string sourceAddress, std::string destinationAddress, std::string &transactionHash) override {} + void createDeposit(uint64_t amount, uint32_t term, std::string sourceAddress, std::string destinationAddress, std::string &transactionHash) override {} void withdrawDeposit(DepositId depositId, std::string &transactionHash) override{}; Deposit getDeposit(size_t depositIndex) const override { From 080f889cea03aa0a1925d45b047114eb744d2712 Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sun, 9 Apr 2023 16:41:09 +0200 Subject: [PATCH 09/17] Remove WalletGreen message duplication --- src/Wallet/WalletGreen.cpp | 43 ++++---------------------------------- 1 file changed, 4 insertions(+), 39 deletions(-) diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index 97cf7bf97..e7b6ca07f 100644 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -335,24 +335,6 @@ namespace cn crypto::SecretKey transactionSK; transaction->getTransactionSecretKey(transactionSK); - /* Add the transaction extra */ - std::vector messages; - crypto::PublicKey publicKey = transaction->getTransactionPublicKey(); - cn::KeyPair kp = {publicKey, transactionSK}; - for (size_t i = 0; i < messages.size(); ++i) - { - cn::AccountPublicAddress addressBin; - if (!m_currency.parseAccountAddressString(messages[i].address, addressBin)) - continue; - cn::tx_extra_message tag; - if (!tag.encrypt(i, messages[i].message, &addressBin, kp)) - continue; - BinaryArray ba; - toBinaryArray(tag, ba); - ba.insert(ba.begin(), TX_EXTRA_MESSAGE_TAG); - transaction->appendExtra(ba); - } - assert(inputs.size() == selectedTransfers.size()); for (size_t i = 0; i < inputs.size(); ++i) { @@ -518,24 +500,6 @@ namespace cn transaction->getTransactionSecretKey(transactionSK); transaction->setUnlockTime(0); - /* Add the transaction extra */ - std::vector messages; - crypto::PublicKey publicKey = transaction->getTransactionPublicKey(); - cn::KeyPair kp = {publicKey, transactionSK}; - for (size_t i = 0; i < messages.size(); ++i) - { - cn::AccountPublicAddress addressBin; - if (!m_currency.parseAccountAddressString(messages[i].address, addressBin)) - continue; - cn::tx_extra_message tag; - if (!tag.encrypt(i, messages[i].message, &addressBin, kp)) - continue; - BinaryArray ba; - toBinaryArray(tag, ba); - ba.insert(ba.begin(), TX_EXTRA_MESSAGE_TAG); - transaction->appendExtra(ba); - } - /* Prepare the inputs */ /* Get additional inputs for the mixin */ @@ -2677,9 +2641,10 @@ namespace cn if (!tag.encrypt(i, messages[i].message, &addressBin, kp)) continue; BinaryArray ba; - toBinaryArray(tag, ba); - ba.insert(ba.begin(), TX_EXTRA_MESSAGE_TAG); - tx->appendExtra(ba); + if (cn::append_message_to_extra(ba, tag)) + { + tx->appendExtra(ba); + } } for (const auto &amountToAddress : amountsToAddresses) From 17ca1389f83146a5457740d17a1fb2cd0bbbf031 Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sun, 9 Apr 2023 18:45:20 +0200 Subject: [PATCH 10/17] Remove WalletGreen transaction duplication --- src/Wallet/WalletGreen.cpp | 55 ++++++++------------------------------ src/Wallet/WalletGreen.h | 4 +-- 2 files changed, 13 insertions(+), 46 deletions(-) diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index e7b6ca07f..fa5fbdfda 100644 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -1871,9 +1871,8 @@ namespace cn size_t WalletGreen::transfer(const TransactionParameters &transactionParameters, crypto::SecretKey &transactionSK) { - tools::ScopeExit releaseContext([this] { - m_dispatcher.yield(); - }); + tools::ScopeExit releaseContext([this] + { m_dispatcher.yield(); }); platform_system::EventLock lk(m_readyEvent); @@ -1881,11 +1880,11 @@ namespace cn throwIfTrackingMode(); throwIfStopped(); - return doTransfer(transactionParameters, transactionSK); + return doTransfer(transactionParameters, transactionSK, true); } void WalletGreen::prepareTransaction( - std::vector &&wallets, + const std::vector &wallets, const std::vector &orders, const std::vector &messages, uint64_t fee, @@ -1955,7 +1954,7 @@ namespace cn validateOrders(transactionParameters.destinations); } - size_t WalletGreen::doTransfer(const TransactionParameters &transactionParameters, crypto::SecretKey &transactionSK) + size_t WalletGreen::doTransfer(const TransactionParameters &transactionParameters, crypto::SecretKey &transactionSK, bool send) { validateTransactionParameters(transactionParameters); cn::AccountPublicAddress changeDestination = getChangeDestination(transactionParameters.changeDestination, transactionParameters.sourceAddresses); @@ -1972,7 +1971,7 @@ namespace cn PreparedTransaction preparedTransaction; prepareTransaction( - std::move(wallets), + wallets, transactionParameters.destinations, transactionParameters.messages, transactionParameters.fee, @@ -1984,53 +1983,21 @@ namespace cn preparedTransaction, transactionSK); - return validateSaveAndSendTransaction(*preparedTransaction.transaction, preparedTransaction.destinations, false, true); + return validateSaveAndSendTransaction(*preparedTransaction.transaction, preparedTransaction.destinations, false, send); } size_t WalletGreen::makeTransaction(const TransactionParameters &sendingTransaction) { - size_t id = WALLET_INVALID_TRANSACTION_ID; - tools::ScopeExit releaseContext([this] { - m_dispatcher.yield(); - }); + tools::ScopeExit releaseContext([this] + { m_dispatcher.yield(); }); platform_system::EventLock lk(m_readyEvent); throwIfNotInitialized(); throwIfTrackingMode(); throwIfStopped(); - - validateTransactionParameters(sendingTransaction); - cn::AccountPublicAddress changeDestination = getChangeDestination(sendingTransaction.changeDestination, sendingTransaction.sourceAddresses); - m_logger(DEBUGGING) << "Change address " << m_currency.accountAddressAsString(changeDestination); - - std::vector wallets; - if (!sendingTransaction.sourceAddresses.empty()) - { - wallets = pickWallets(sendingTransaction.sourceAddresses); - } - else - { - wallets = pickWalletsWithMoney(); - } - - PreparedTransaction preparedTransaction; crypto::SecretKey txSecretKey; - prepareTransaction( - std::move(wallets), - sendingTransaction.destinations, - sendingTransaction.messages, - sendingTransaction.fee, - sendingTransaction.mixIn, - sendingTransaction.extra, - sendingTransaction.unlockTimestamp, - sendingTransaction.donation, - changeDestination, - preparedTransaction, - txSecretKey); - - id = validateSaveAndSendTransaction(*preparedTransaction.transaction, preparedTransaction.destinations, false, false); - return id; + return doTransfer(sendingTransaction, txSecretKey, false); } void WalletGreen::commitTransaction(size_t transactionId) @@ -4669,7 +4636,7 @@ namespace cn PreparedTransaction preparedTransaction; crypto::SecretKey txSecretKey; prepareTransaction( - std::move(wallets), + wallets, sendingTransaction.destinations, sendingTransaction.messages, sendingTransaction.fee, diff --git a/src/Wallet/WalletGreen.h b/src/Wallet/WalletGreen.h index be031daca..1ddf36d5f 100644 --- a/src/Wallet/WalletGreen.h +++ b/src/Wallet/WalletGreen.h @@ -264,7 +264,7 @@ class WalletGreen : public IObservableImpl, uint64_t changeAmount; }; - void prepareTransaction(std::vector &&wallets, + void prepareTransaction(const std::vector &wallets, const std::vector &orders, const std::vector &messages, uint64_t fee, @@ -281,7 +281,7 @@ class WalletGreen : public IObservableImpl, void validateOrders(const std::vector &orders) const; void validateTransactionParameters(const TransactionParameters &transactionParameters) const; - size_t doTransfer(const TransactionParameters &transactionParameters, crypto::SecretKey &transactionSK); + size_t doTransfer(const TransactionParameters &transactionParameters, crypto::SecretKey &transactionSK, bool send); void requestMixinOuts(const std::vector &selectedTransfers, uint64_t mixIn, From 2691680d0409b79812fbca15d077ed64df3fc571 Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sat, 15 Apr 2023 14:28:04 +0200 Subject: [PATCH 11/17] Fix promise --- src/Wallet/WalletGreen.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index fa5fbdfda..44f503625 100644 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -2633,16 +2633,15 @@ namespace cn void WalletGreen::sendTransaction(const cn::Transaction &cryptoNoteTransaction) { - std::error_code ec; throwIfStopped(); auto relayTransactionCompleted = std::promise(); auto relayTransactionWaitFuture = relayTransactionCompleted.get_future(); - m_node.relayTransaction(cryptoNoteTransaction, [&ec, &relayTransactionCompleted](std::error_code) + m_node.relayTransaction(cryptoNoteTransaction, [&relayTransactionCompleted](std::error_code ec) { auto detachedPromise = std::move(relayTransactionCompleted); detachedPromise.set_value(ec); }); - ec = relayTransactionWaitFuture.get(); + std::error_code ec = relayTransactionWaitFuture.get(); if (ec) { @@ -2739,24 +2738,22 @@ namespace cn amounts.push_back(out.out.amount); } - std::error_code mixinError; - throwIfStopped(); auto getRandomOutsByAmountsCompleted = std::promise(); auto getRandomOutsByAmountsWaitFuture = getRandomOutsByAmountsCompleted.get_future(); m_node.getRandomOutsByAmounts(std::move(amounts), mixIn, mixinResult, [&getRandomOutsByAmountsCompleted](std::error_code ec) { - auto detachedPromise = std::move(getRandomOutsByAmountsCompleted); + auto detachedPromise = std::move(getRandomOutsByAmountsCompleted); detachedPromise.set_value(ec); }); - mixinError = getRandomOutsByAmountsWaitFuture.get(); + std::error_code ec = getRandomOutsByAmountsWaitFuture.get(); checkIfEnoughMixins(mixinResult, mixIn); - if (mixinError) + if (ec) { - throw std::system_error(mixinError); + throw std::system_error(ec); } } From 8edffedb9b594a70b00206b1ff6ad7be5458ba33 Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sat, 15 Apr 2023 15:22:17 +0200 Subject: [PATCH 12/17] Add messages to WalletTransaction --- include/IWallet.h | 1 + src/Wallet/WalletGreen.cpp | 26 +++++++++++++++++++++++++- src/Wallet/WalletGreen.h | 1 + 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/include/IWallet.h b/include/IWallet.h index 867e60838..7a3c488ca 100644 --- a/include/IWallet.h +++ b/include/IWallet.h @@ -107,6 +107,7 @@ struct WalletTransaction size_t firstDepositId = WALLET_INVALID_DEPOSIT_ID; size_t depositCount = 0; bool isBase; + std::vector messages; }; enum class WalletTransferType : uint8_t diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index 44f503625..c8d7e3dfc 100644 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -1810,7 +1810,23 @@ namespace cn throw std::system_error(make_error_code(cn::error::INDEX_OUT_OF_RANGE)); } - return m_transactions.get()[transactionIndex]; + WalletTransaction transaction = m_transactions.get()[transactionIndex]; + transaction.messages = getMessagesFromExtra(transaction.extra); + return transaction; + } + + std::vector WalletGreen::getMessagesFromExtra(const std::string &extra) const + { + std::vector messages; + std::vector extraBin = common::asBinaryArray(extra); + crypto::PublicKey publicKey = cn::getTransactionPublicKeyFromExtra(extraBin); + for (size_t i = 0; i < getAddressCount(); ++i) + { + crypto::SecretKey secretKey = getAddressSpendKey(getAddress(i)).secretKey; + std::vector m = cn::get_messages_from_extra(extraBin, publicKey, &secretKey); + messages.insert(std::end(messages), std::begin(m), std::end(m)); + } + return messages; } Deposit WalletGreen::getDeposit(size_t depositIndex) const @@ -2195,6 +2211,12 @@ namespace cn transaction.isBase = isBase; updated = true; } + + if (transaction.messages != info.messages) + { + transaction.messages = info.messages; + updated = true; + } }); (void)r; assert(r); @@ -2227,6 +2249,7 @@ namespace cn tx.extra.assign(reinterpret_cast(info.extra.data()), info.extra.size()); tx.totalAmount = txBalance; tx.creationTime = info.timestamp; + tx.messages = info.messages; size_t txId = index.size(); index.push_back(std::move(tx)); @@ -2973,6 +2996,7 @@ namespace cn WalletTransactionWithTransfers walletTransaction; walletTransaction.transaction = *it; + walletTransaction.transaction.messages = getMessagesFromExtra(it->extra); walletTransaction.transfers = getTransactionTransfers(*it); return walletTransaction; diff --git a/src/Wallet/WalletGreen.h b/src/Wallet/WalletGreen.h index 1ddf36d5f..313dee48c 100644 --- a/src/Wallet/WalletGreen.h +++ b/src/Wallet/WalletGreen.h @@ -384,6 +384,7 @@ class WalletGreen : public IObservableImpl, void deleteFromUncommitedTransactions(const std::vector &deletedTransactions); void pushToPaymentsIndex(const crypto::Hash &paymentId, size_t txId); void buildPaymentIds(); + std::vector getMessagesFromExtra(const std::string &extra) const; cn::WalletEvent makeTransactionUpdatedEvent(size_t id); cn::WalletEvent makeTransactionCreatedEvent(size_t id); From a2f8ed393fbfa8dc80b1f7121df4a353b5788b77 Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sat, 22 Apr 2023 16:07:55 +0200 Subject: [PATCH 13/17] Add ttl to WalletGreen --- include/IWallet.h | 1 + src/ConcealWallet/ConcealWallet.cpp | 2 +- src/Wallet/WalletGreen.cpp | 21 +++++++++++++++++---- src/Wallet/WalletGreen.h | 3 ++- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/include/IWallet.h b/include/IWallet.h index 7a3c488ca..c44727fab 100644 --- a/include/IWallet.h +++ b/include/IWallet.h @@ -155,6 +155,7 @@ struct TransactionParameters uint64_t unlockTimestamp = 0; DonationSettings donation; std::string changeDestination; + uint64_t ttl = 0; }; struct WalletTransactionWithTransfers diff --git a/src/ConcealWallet/ConcealWallet.cpp b/src/ConcealWallet/ConcealWallet.cpp index 3a4d7c58f..7e0fec321 100644 --- a/src/ConcealWallet/ConcealWallet.cpp +++ b/src/ConcealWallet/ConcealWallet.cpp @@ -1353,7 +1353,7 @@ bool conceal_wallet::transfer(const std::vector &args) { sendParams.destinations = cmd.dsts; sendParams.messages = messages; sendParams.extra = extraString; - sendParams.unlockTimestamp = ttl; + sendParams.ttl = ttl; sendParams.changeDestination = m_wallet->getAddress(0); crypto::SecretKey transactionSK; diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index c8d7e3dfc..854841f02 100644 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -1909,10 +1909,14 @@ namespace cn uint64_t unlockTimestamp, const DonationSettings &donation, const cn::AccountPublicAddress &changeDestination, + uint64_t ttl, PreparedTransaction &preparedTransaction, crypto::SecretKey &transactionSK) { - + if (ttl != 0) + { + fee = 0; + } preparedTransaction.destinations = convertOrdersToTransfers(orders); preparedTransaction.neededMoney = countNeededMoney(preparedTransaction.destinations, fee); @@ -1950,7 +1954,7 @@ namespace cn decomposedOutputs.emplace_back(std::move(splittedChange)); } - preparedTransaction.transaction = makeTransaction(decomposedOutputs, keysInfo, messages, extra, unlockTimestamp, transactionSK); + preparedTransaction.transaction = makeTransaction(decomposedOutputs, keysInfo, messages, extra, unlockTimestamp, ttl, transactionSK); } void WalletGreen::validateTransactionParameters(const TransactionParameters &transactionParameters) const @@ -1996,6 +2000,7 @@ namespace cn transactionParameters.unlockTimestamp, transactionParameters.donation, changeDestination, + transactionParameters.ttl, preparedTransaction, transactionSK); @@ -2591,7 +2596,7 @@ namespace cn } std::unique_ptr WalletGreen::makeTransaction(const std::vector &decomposedOutputs, - std::vector &keysInfo, const std::vector &messages, const std::string &extra, uint64_t unlockTimestamp, crypto::SecretKey &transactionSK) + std::vector &keysInfo, const std::vector &messages, const std::string &extra, uint64_t unlockTimestamp, uint64_t ttl, crypto::SecretKey &transactionSK) { std::unique_ptr tx = createTransaction(); @@ -2637,6 +2642,13 @@ namespace cn } } + if (ttl != 0) + { + BinaryArray ba; + cn::appendTTLToExtra(ba, ttl); + tx->appendExtra(ba); + } + for (const auto &amountToAddress : amountsToAddresses) { tx->addOutput(amountToAddress.second, *amountToAddress.first); @@ -4063,7 +4075,7 @@ namespace cn crypto::SecretKey txkey; std::vector messages; - fusionTransaction = makeTransaction(std::vector{decomposedOutputs}, keysInfo, messages, "", 0, txkey); + fusionTransaction = makeTransaction(std::vector{decomposedOutputs}, keysInfo, messages, "", 0, 0, txkey); transactionSize = getTransactionSize(*fusionTransaction); ++round; @@ -4666,6 +4678,7 @@ namespace cn sendingTransaction.unlockTimestamp, sendingTransaction.donation, changeDestination, + sendingTransaction.ttl, preparedTransaction, txSecretKey); diff --git a/src/Wallet/WalletGreen.h b/src/Wallet/WalletGreen.h index 313dee48c..66d3aaa84 100644 --- a/src/Wallet/WalletGreen.h +++ b/src/Wallet/WalletGreen.h @@ -273,6 +273,7 @@ class WalletGreen : public IObservableImpl, uint64_t unlockTimestamp, const DonationSettings &donation, const cn::AccountPublicAddress &changeDestinationAddress, + uint64_t ttl, PreparedTransaction &preparedTransaction, crypto::SecretKey &transactionSK); void validateAddresses(const std::vector &addresses) const; @@ -302,7 +303,7 @@ class WalletGreen : public IObservableImpl, ReceiverAmounts splitAmount(uint64_t amount, const AccountPublicAddress &destination, uint64_t dustThreshold) const; std::unique_ptr makeTransaction(const std::vector &decomposedOutputs, - std::vector &keysInfo, const std::vector &messages, const std::string &extra, uint64_t unlockTimestamp, crypto::SecretKey &transactionSK); + std::vector &keysInfo, const std::vector &messages, const std::string &extra, uint64_t unlockTimestamp, uint64_t ttl, crypto::SecretKey &transactionSK); void sendTransaction(const cn::Transaction &cryptoNoteTransaction); size_t validateSaveAndSendTransaction(const ITransactionReader &transaction, const std::vector &destinations, bool isFusion, bool send); From dd6854e04b8e580639e3a41e34d8445d5dc9b769 Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sun, 22 Oct 2023 15:31:09 +0200 Subject: [PATCH 14/17] Add paymentId to extra --- src/CryptoNoteCore/TransactionExtra.cpp | 9 +++++++++ src/CryptoNoteCore/TransactionExtra.h | 1 + src/PaymentGate/WalletService.cpp | 5 +---- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/CryptoNoteCore/TransactionExtra.cpp b/src/CryptoNoteCore/TransactionExtra.cpp index 43f092d62..9f8118139 100644 --- a/src/CryptoNoteCore/TransactionExtra.cpp +++ b/src/CryptoNoteCore/TransactionExtra.cpp @@ -357,6 +357,15 @@ namespace cn return true; } + bool addPaymentIdToExtra(const std::string &paymentId, std::string &extra) { + std::vector extraVector; + if (!createTxExtraWithPaymentId(paymentId, extraVector)) { + return false; + } + std::copy(extraVector.begin(), extraVector.end(), std::back_inserter(extra)); + return true; + } + #define TX_EXTRA_MESSAGE_CHECKSUM_SIZE 4 #pragma pack(push, 1) diff --git a/src/CryptoNoteCore/TransactionExtra.h b/src/CryptoNoteCore/TransactionExtra.h index 064bf7fd8..f9a950b5e 100644 --- a/src/CryptoNoteCore/TransactionExtra.h +++ b/src/CryptoNoteCore/TransactionExtra.h @@ -99,5 +99,6 @@ bool createTxExtraWithPaymentId(const std::string& paymentIdString, std::vector< //returns false if payment id is not found or parse error bool getPaymentIdFromTxExtra(const std::vector& extra, crypto::Hash& paymentId); bool parsePaymentId(const std::string& paymentIdString, crypto::Hash& paymentId); +bool addPaymentIdToExtra(const std::string &paymentId, std::string &extra); } diff --git a/src/PaymentGate/WalletService.cpp b/src/PaymentGate/WalletService.cpp index b9c61c06b..0b75f588a 100644 --- a/src/PaymentGate/WalletService.cpp +++ b/src/PaymentGate/WalletService.cpp @@ -183,13 +183,10 @@ namespace payment_service void addPaymentIdToExtra(const std::string &paymentId, std::string &extra) { - std::vector extraVector; - if (!cn::createTxExtraWithPaymentId(paymentId, extraVector)) + if (!cn::addPaymentIdToExtra(paymentId, extra)) { throw std::runtime_error("Couldn't add payment id to extra"); } - - std::copy(extraVector.begin(), extraVector.end(), std::back_inserter(extra)); } void validatePaymentId(const std::string &paymentId, const logging::LoggerRef& logger) From 195c5cbe69660a91bfa448ebb8c67d60db5ca5b9 Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sun, 19 Nov 2023 16:11:52 +0100 Subject: [PATCH 15/17] Update WalletGreen --- src/Wallet/WalletGreen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index 854841f02..de7a4808a 100644 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -1259,6 +1259,7 @@ namespace cn m_state = WalletState::INITIALIZED; m_logger(INFO, BRIGHT_WHITE) << "Container loaded, view public key " << common::podToHex(m_viewPublicKey) << ", wallet count " << m_walletsContainer.size() << ", actual balance " << m_currency.formatAmount(m_actualBalance) << ", pending balance " << m_currency.formatAmount(m_pendingBalance); + m_observerManager.notify(&IWalletObserver::initCompleted, std::error_code()); } void WalletGreen::clearCaches(bool clearTransactions, bool clearCachedData) From 628a30521d7725d618396e639b527bf9d254526c Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sun, 26 Nov 2023 16:38:45 +0100 Subject: [PATCH 16/17] Fix WalletGreen password change --- src/Common/FileMappedVector.h | 2 +- src/Wallet/WalletGreen.cpp | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Common/FileMappedVector.h b/src/Common/FileMappedVector.h index 0ae892f46..705dfc87a 100644 --- a/src/Common/FileMappedVector.h +++ b/src/Common/FileMappedVector.h @@ -759,7 +759,7 @@ void FileMappedVector::rename(const std::string& newPath) { template template void FileMappedVector::atomicUpdate(F&& func) { - atomicUpdate0(capacity(), prefixSize(), suffixSize(), std::forward(func)); + atomicUpdate0(capacity(), prefixSize(), suffixSize(), std::move(func)); } template diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index de7a4808a..c53070b82 100644 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -1368,7 +1368,30 @@ namespace cn throw std::system_error(make_error_code(error::WRONG_PASSWORD)); } + if (oldPassword == newPassword) + { + return; + } + + crypto::cn_context cnContext; + crypto::chacha8_key newKey; + crypto::generate_chacha8_key(cnContext, newPassword, newKey); + + m_containerStorage.atomicUpdate([this, newKey](ContainerStorage &newStorage) + { + copyContainerStoragePrefix(m_containerStorage, m_key, newStorage, newKey); + copyContainerStorageKeys(m_containerStorage, m_key, newStorage, newKey); + + if (m_containerStorage.suffixSize() > 0) { + BinaryArray containerData; + loadAndDecryptContainerData(m_containerStorage, m_key, containerData); + encryptAndSaveContainerData(newStorage, newKey, containerData.data(), containerData.size()); + } }); + + m_key = newKey; m_password = newPassword; + + m_logger(INFO, BRIGHT_WHITE) << "Container password changed"; } size_t WalletGreen::getAddressCount() const From 63ca10a9e5b5aac674cad3867d8c863b8a830669 Mon Sep 17 00:00:00 2001 From: AxVultis Date: Sun, 26 Nov 2023 16:51:32 +0100 Subject: [PATCH 17/17] Update #include --- src/Mnemonics/CRC32.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mnemonics/CRC32.h b/src/Mnemonics/CRC32.h index 07b5404ec..a72550f77 100644 --- a/src/Mnemonics/CRC32.h +++ b/src/Mnemonics/CRC32.h @@ -26,7 +26,7 @@ SOFTWARE. #pragma once #include - +#include #include namespace crc32