mirror of
				https://git.wownero.com/wownero/wownero.git
				synced 2024-08-15 01:03:23 +00:00 
			
		
		
		
	Misc. wallet API and wallet2 changes
This commit is contained in:
		
							parent
							
								
									e6cc37e9b0
								
							
						
					
					
						commit
						3234b5fe62
					
				
					 12 changed files with 336 additions and 34 deletions
				
			
		| 
						 | 
				
			
			@ -67,7 +67,10 @@ void SubaddressImpl::refresh(uint32_t accountIndex)
 | 
			
		|||
  clearRows();
 | 
			
		||||
  for (size_t i = 0; i < m_wallet->m_wallet->get_num_subaddresses(accountIndex); ++i)
 | 
			
		||||
  {
 | 
			
		||||
    m_rows.push_back(new SubaddressRow(i, m_wallet->m_wallet->get_subaddress_as_str({accountIndex, (uint32_t)i}), m_wallet->m_wallet->get_subaddress_label({accountIndex, (uint32_t)i})));
 | 
			
		||||
      m_rows.push_back(new SubaddressRow(i,
 | 
			
		||||
                                         m_wallet->m_wallet->get_subaddress_as_str({accountIndex, (uint32_t)i}),
 | 
			
		||||
                                         m_wallet->m_wallet->get_subaddress_label({accountIndex, (uint32_t)i}),
 | 
			
		||||
                                         m_wallet->m_wallet->get_subaddress_used({accountIndex, (uint32_t)i})));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -199,6 +199,9 @@ void TransactionHistoryImpl::refresh()
 | 
			
		|||
            ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id)});
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (const auto &r: pd.m_rings) {
 | 
			
		||||
            ti->m_rings.push_back({string_tools::pod_to_hex(r.first), cryptonote::relative_output_offsets_to_absolute(r.second)});
 | 
			
		||||
        }
 | 
			
		||||
        m_history.push_back(ti);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -229,10 +232,15 @@ void TransactionHistoryImpl::refresh()
 | 
			
		|||
        ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
 | 
			
		||||
        ti->m_timestamp = pd.m_timestamp;
 | 
			
		||||
        ti->m_confirmations = 0;
 | 
			
		||||
        for (const auto &d : pd.m_dests)
 | 
			
		||||
 | 
			
		||||
        for (const auto &d : pd.m_dests) {
 | 
			
		||||
        {
 | 
			
		||||
            ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id)});
 | 
			
		||||
        }        
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (const auto &r: pd.m_rings) {
 | 
			
		||||
            ti->m_rings.push_back({string_tools::pod_to_hex(r.first), cryptonote::relative_output_offsets_to_absolute(r.second)});
 | 
			
		||||
        }
 | 
			
		||||
        m_history.push_back(ti);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -139,6 +139,11 @@ const std::vector<TransactionInfo::Transfer> &TransactionInfoImpl::transfers() c
 | 
			
		|||
    return m_transfers;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const std::vector<std::pair<std::string, std::vector<uint64_t>>> &TransactionInfoImpl::rings() const
 | 
			
		||||
{
 | 
			
		||||
    return m_rings;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint64_t TransactionInfoImpl::confirmations() const
 | 
			
		||||
{
 | 
			
		||||
    return m_confirmations;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,6 +63,8 @@ public:
 | 
			
		|||
    virtual uint64_t confirmations() const override;
 | 
			
		||||
    virtual uint64_t unlockTime() const override;
 | 
			
		||||
 | 
			
		||||
    virtual const std::vector<std::pair<std::string, std::vector<uint64_t>>> &rings() const override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    int         m_direction;
 | 
			
		||||
    bool        m_pending;
 | 
			
		||||
| 
						 | 
				
			
			@ -81,6 +83,7 @@ private:
 | 
			
		|||
    std::vector<Transfer> m_transfers;
 | 
			
		||||
    uint64_t    m_confirmations;
 | 
			
		||||
    uint64_t    m_unlock_time;
 | 
			
		||||
    std::vector<std::pair<std::string, std::vector<uint64_t>>> m_rings;
 | 
			
		||||
 | 
			
		||||
    friend class TransactionHistoryImpl;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,7 @@
 | 
			
		|||
#include "transaction_history.h"
 | 
			
		||||
#include "address_book.h"
 | 
			
		||||
#include "subaddress.h"
 | 
			
		||||
#include "coins.h"
 | 
			
		||||
#include "subaddress_account.h"
 | 
			
		||||
#include "common_defines.h"
 | 
			
		||||
#include "common/util.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -166,11 +167,8 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
 | 
			
		|||
                     << ", burnt: " << print_money(burnt)
 | 
			
		||||
                     << ", raw_output_value: " << print_money(amount)
 | 
			
		||||
                     << ", idx: " << subaddr_index);
 | 
			
		||||
        // do not signal on received tx if wallet is not syncronized completely
 | 
			
		||||
        if (m_listener && m_wallet->synchronized()) {
 | 
			
		||||
            m_listener->moneyReceived(tx_hash, amount - burnt);
 | 
			
		||||
            m_listener->updated();
 | 
			
		||||
        }
 | 
			
		||||
        m_listener->moneyReceived(tx_hash, amount);
 | 
			
		||||
        m_listener->updated();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index)
 | 
			
		||||
| 
						 | 
				
			
			@ -182,11 +180,8 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
 | 
			
		|||
                     << ", tx: " << tx_hash
 | 
			
		||||
                     << ", amount: " << print_money(amount)
 | 
			
		||||
                     << ", idx: " << subaddr_index);
 | 
			
		||||
        // do not signal on received tx if wallet is not syncronized completely
 | 
			
		||||
        if (m_listener && m_wallet->synchronized()) {
 | 
			
		||||
            m_listener->unconfirmedMoneyReceived(tx_hash, amount);
 | 
			
		||||
            m_listener->updated();
 | 
			
		||||
        }
 | 
			
		||||
        m_listener->unconfirmedMoneyReceived(tx_hash, amount);
 | 
			
		||||
        m_listener->updated();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx,
 | 
			
		||||
| 
						 | 
				
			
			@ -198,11 +193,8 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
 | 
			
		|||
                     << ", tx: " << tx_hash
 | 
			
		||||
                     << ", amount: " << print_money(amount)
 | 
			
		||||
                     << ", idx: " << subaddr_index);
 | 
			
		||||
        // do not signal on sent tx if wallet is not syncronized completely
 | 
			
		||||
        if (m_listener && m_wallet->synchronized()) {
 | 
			
		||||
            m_listener->moneySpent(tx_hash, amount);
 | 
			
		||||
            m_listener->updated();
 | 
			
		||||
        }
 | 
			
		||||
        m_listener->moneySpent(tx_hash, amount);
 | 
			
		||||
        m_listener->updated();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx)
 | 
			
		||||
| 
						 | 
				
			
			@ -436,6 +428,7 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds)
 | 
			
		|||
    m_refreshEnabled = false;
 | 
			
		||||
    m_addressBook.reset(new AddressBookImpl(this));
 | 
			
		||||
    m_subaddress.reset(new SubaddressImpl(this));
 | 
			
		||||
    m_coins.reset(new CoinsImpl(this));
 | 
			
		||||
    m_subaddressAccount.reset(new SubaddressAccountImpl(this));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -763,6 +756,35 @@ bool WalletImpl::recover(const std::string &path, const std::string &password, c
 | 
			
		|||
    return status() == Status_Ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool WalletImpl::recoverDeterministicWalletFromSpendKey(const std::string &path, const std::string &password, const std::string &language, const std::string &spendkey_string)
 | 
			
		||||
{
 | 
			
		||||
    clearStatus();
 | 
			
		||||
    m_errorString.clear();
 | 
			
		||||
 | 
			
		||||
    m_recoveringFromSeed = true;
 | 
			
		||||
    m_recoveringFromDevice = false;
 | 
			
		||||
 | 
			
		||||
    // parse spend key
 | 
			
		||||
    crypto::secret_key spendkey;
 | 
			
		||||
    if (!spendkey_string.empty()) {
 | 
			
		||||
        cryptonote::blobdata spendkey_data;
 | 
			
		||||
        if(!epee::string_tools::parse_hexstr_to_binbuff(spendkey_string, spendkey_data) || spendkey_data.size() != sizeof(crypto::secret_key))
 | 
			
		||||
        {
 | 
			
		||||
            setStatusError(tr("failed to parse secret spend key"));
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        m_wallet->generate(path, password, spendkey, true, false);
 | 
			
		||||
        setSeedLanguage(language);
 | 
			
		||||
    } catch (const std::exception &e) {
 | 
			
		||||
        setStatusCritical(e.what());
 | 
			
		||||
    }
 | 
			
		||||
    return status() == Status_Ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool WalletImpl::close(bool store)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1724,6 +1746,137 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const
 | 
			
		|||
    return createTransactionMultDest(std::vector<string> {dst_addr}, payment_id, amount ? (std::vector<uint64_t> {*amount}) : (optional<std::vector<uint64_t>>()), mixin_count, priority, subaddr_account, subaddr_indices);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PendingTransaction *WalletImpl::createTransactionSingle(const string &key_image, const string &dst_addr,
 | 
			
		||||
                                                        const size_t outputs, PendingTransaction::Priority priority)
 | 
			
		||||
{
 | 
			
		||||
    clearStatus();
 | 
			
		||||
    // Pause refresh thread while creating transaction
 | 
			
		||||
    pauseRefresh();
 | 
			
		||||
 | 
			
		||||
    cryptonote::address_parse_info info;
 | 
			
		||||
 | 
			
		||||
    size_t fake_outs_count = m_wallet->adjust_mixin(m_wallet->default_mixin());
 | 
			
		||||
 | 
			
		||||
    uint32_t adjusted_priority = m_wallet->adjust_priority(static_cast<uint32_t>(priority));
 | 
			
		||||
 | 
			
		||||
    PendingTransactionImpl * transaction = new PendingTransactionImpl(*this);
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        std::vector<uint8_t> extra;
 | 
			
		||||
        std::string extra_nonce;
 | 
			
		||||
        vector<cryptonote::tx_destination_entry> dsts;
 | 
			
		||||
 | 
			
		||||
        bool error = false;
 | 
			
		||||
 | 
			
		||||
        crypto::key_image ki;
 | 
			
		||||
        if (!epee::string_tools::hex_to_pod(key_image, ki))
 | 
			
		||||
        {
 | 
			
		||||
            setStatusError(tr("failed to parse key image"));
 | 
			
		||||
            error = true;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), dst_addr))
 | 
			
		||||
        {
 | 
			
		||||
            setStatusError(tr("Invalid destination address"));
 | 
			
		||||
            error = true;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        if (info.has_payment_id) {
 | 
			
		||||
            if (!extra_nonce.empty()) {
 | 
			
		||||
                setStatusError(tr("a single transaction cannot use more than one payment id"));
 | 
			
		||||
                error = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, info.payment_id);
 | 
			
		||||
        }
 | 
			
		||||
        if (error) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        if (!extra_nonce.empty() && !add_extra_nonce_to_tx_extra(extra, extra_nonce)) {
 | 
			
		||||
            setStatusError(tr("failed to set up payment id, though it was decoded correctly"));
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        try {
 | 
			
		||||
            transaction->m_pending_tx = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress,
 | 
			
		||||
                                                                             outputs, fake_outs_count, 0 /* unlock time */, priority, extra);
 | 
			
		||||
 | 
			
		||||
            pendingTxPostProcess(transaction);
 | 
			
		||||
 | 
			
		||||
            if (multisig().isMultisig) {
 | 
			
		||||
                auto tx_set = m_wallet->make_multisig_tx_set(transaction->m_pending_tx);
 | 
			
		||||
                transaction->m_pending_tx = tx_set.m_ptx;
 | 
			
		||||
                transaction->m_signers = tx_set.m_signers;
 | 
			
		||||
            }
 | 
			
		||||
        } catch (const tools::error::daemon_busy&) {
 | 
			
		||||
            // TODO: make it translatable with "tr"?
 | 
			
		||||
            setStatusError(tr("daemon is busy. Please try again later."));
 | 
			
		||||
        } catch (const tools::error::no_connection_to_daemon&) {
 | 
			
		||||
            setStatusError(tr("no connection to daemon. Please make sure daemon is running."));
 | 
			
		||||
        } catch (const tools::error::wallet_rpc_error& e) {
 | 
			
		||||
            setStatusError(tr("RPC error: ") +  e.to_string());
 | 
			
		||||
        } catch (const tools::error::get_outs_error &e) {
 | 
			
		||||
            setStatusError((boost::format(tr("failed to get outputs to mix: %s")) % e.what()).str());
 | 
			
		||||
        } catch (const tools::error::not_enough_unlocked_money& e) {
 | 
			
		||||
            std::ostringstream writer;
 | 
			
		||||
 | 
			
		||||
            writer << boost::format(tr("not enough money to transfer, available only %s, sent amount %s")) %
 | 
			
		||||
                      print_money(e.available()) %
 | 
			
		||||
                      print_money(e.tx_amount());
 | 
			
		||||
            setStatusError(writer.str());
 | 
			
		||||
        } catch (const tools::error::not_enough_money& e) {
 | 
			
		||||
            std::ostringstream writer;
 | 
			
		||||
 | 
			
		||||
            writer << boost::format(tr("not enough money to transfer, overall balance only %s, sent amount %s")) %
 | 
			
		||||
                      print_money(e.available()) %
 | 
			
		||||
                      print_money(e.tx_amount());
 | 
			
		||||
            setStatusError(writer.str());
 | 
			
		||||
        } catch (const tools::error::tx_not_possible& e) {
 | 
			
		||||
            std::ostringstream writer;
 | 
			
		||||
 | 
			
		||||
            writer << boost::format(tr("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)")) %
 | 
			
		||||
                      print_money(e.available()) %
 | 
			
		||||
                      print_money(e.tx_amount() + e.fee())  %
 | 
			
		||||
                      print_money(e.tx_amount()) %
 | 
			
		||||
                      print_money(e.fee());
 | 
			
		||||
            setStatusError(writer.str());
 | 
			
		||||
        } catch (const tools::error::not_enough_outs_to_mix& e) {
 | 
			
		||||
            std::ostringstream writer;
 | 
			
		||||
            writer << tr("not enough outputs for specified ring size") << " = " << (e.mixin_count() + 1) << ":";
 | 
			
		||||
            for (const std::pair<uint64_t, uint64_t> outs_for_amount : e.scanty_outs()) {
 | 
			
		||||
                writer << "\n" << tr("output amount") << " = " << print_money(outs_for_amount.first) << ", " << tr("found outputs to use") << " = " << outs_for_amount.second;
 | 
			
		||||
            }
 | 
			
		||||
            writer << "\n" << tr("Please sweep unmixable outputs.");
 | 
			
		||||
            setStatusError(writer.str());
 | 
			
		||||
        } catch (const tools::error::tx_not_constructed&) {
 | 
			
		||||
            setStatusError(tr("transaction was not constructed"));
 | 
			
		||||
        } catch (const tools::error::tx_rejected& e) {
 | 
			
		||||
            std::ostringstream writer;
 | 
			
		||||
            writer << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) <<  e.status();
 | 
			
		||||
            setStatusError(writer.str());
 | 
			
		||||
        } catch (const tools::error::tx_sum_overflow& e) {
 | 
			
		||||
            setStatusError(e.what());
 | 
			
		||||
        } catch (const tools::error::zero_destination&) {
 | 
			
		||||
            setStatusError(tr("one of destinations is zero"));
 | 
			
		||||
        } catch (const tools::error::tx_too_big& e) {
 | 
			
		||||
            setStatusError(tr("failed to find a suitable way to split transactions"));
 | 
			
		||||
        } catch (const tools::error::transfer_error& e) {
 | 
			
		||||
            setStatusError(string(tr("unknown transfer error: ")) + e.what());
 | 
			
		||||
        } catch (const tools::error::wallet_internal_error& e) {
 | 
			
		||||
            setStatusError(string(tr("internal error: ")) + e.what());
 | 
			
		||||
        } catch (const std::exception& e) {
 | 
			
		||||
            setStatusError(string(tr("unexpected error: ")) + e.what());
 | 
			
		||||
        } catch (...) {
 | 
			
		||||
            setStatusError(tr("unknown error"));
 | 
			
		||||
        }
 | 
			
		||||
    } while (false);
 | 
			
		||||
 | 
			
		||||
    statusWithErrorString(transaction->m_status, transaction->m_errorString);
 | 
			
		||||
    // Resume refresh thread
 | 
			
		||||
    startRefresh();
 | 
			
		||||
    return transaction;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1843,6 +1996,11 @@ AddressBook *WalletImpl::addressBook()
 | 
			
		|||
    return m_addressBook.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Coins *WalletImpl::coins()
 | 
			
		||||
{
 | 
			
		||||
    return m_coins.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Subaddress *WalletImpl::subaddress()
 | 
			
		||||
{
 | 
			
		||||
    return m_subaddress.get();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,6 +46,7 @@ class PendingTransactionImpl;
 | 
			
		|||
class UnsignedTransactionImpl;
 | 
			
		||||
class AddressBookImpl;
 | 
			
		||||
class SubaddressImpl;
 | 
			
		||||
class CoinsImpl;
 | 
			
		||||
class SubaddressAccountImpl;
 | 
			
		||||
struct Wallet2CallbackImpl;
 | 
			
		||||
class PendingTransactionInfoImpl;
 | 
			
		||||
| 
						 | 
				
			
			@ -78,6 +79,10 @@ public:
 | 
			
		|||
                            const std::string &address_string, 
 | 
			
		||||
                            const std::string &viewkey_string,
 | 
			
		||||
                            const std::string &spendkey_string = "");
 | 
			
		||||
    bool recoverDeterministicWalletFromSpendKey(const std::string &path,
 | 
			
		||||
                                                const std::string &password,
 | 
			
		||||
                                                const std::string &language,
 | 
			
		||||
                                                const std::string &spendkey_string);
 | 
			
		||||
    bool recoverFromDevice(const std::string &path,
 | 
			
		||||
                           const std::string &password,
 | 
			
		||||
                           const std::string &device_name);
 | 
			
		||||
| 
						 | 
				
			
			@ -164,6 +169,10 @@ public:
 | 
			
		|||
                                        PendingTransaction::Priority priority = PendingTransaction::Priority_Low,
 | 
			
		||||
                                        uint32_t subaddr_account = 0,
 | 
			
		||||
                                        std::set<uint32_t> subaddr_indices = {}) override;
 | 
			
		||||
 | 
			
		||||
    PendingTransaction * createTransactionSingle(const std::string &key_image, const std::string &dst_addr,
 | 
			
		||||
                                                 size_t outputs = 1, PendingTransaction::Priority priority = PendingTransaction::Priority_Low) override;
 | 
			
		||||
 | 
			
		||||
    virtual PendingTransaction * createSweepUnmixableTransaction() override;
 | 
			
		||||
    bool submitTransaction(const std::string &fileName) override;
 | 
			
		||||
    virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override;
 | 
			
		||||
| 
						 | 
				
			
			@ -181,6 +190,7 @@ public:
 | 
			
		|||
                                            PendingTransaction::Priority priority) const override;
 | 
			
		||||
    virtual TransactionHistory * history() override;
 | 
			
		||||
    virtual AddressBook * addressBook() override;
 | 
			
		||||
    virtual Coins * coins() override;
 | 
			
		||||
    virtual Subaddress * subaddress() override;
 | 
			
		||||
    virtual SubaddressAccount * subaddressAccount() override;
 | 
			
		||||
    virtual void setListener(WalletListener * l) override;
 | 
			
		||||
| 
						 | 
				
			
			@ -252,6 +262,7 @@ private:
 | 
			
		|||
    friend struct Wallet2CallbackImpl;
 | 
			
		||||
    friend class AddressBookImpl;
 | 
			
		||||
    friend class SubaddressImpl;
 | 
			
		||||
    friend class CoinsImpl;
 | 
			
		||||
    friend class SubaddressAccountImpl;
 | 
			
		||||
    friend class PendingTransactionInfoImpl;
 | 
			
		||||
    friend class TransactionConstructionInfoImpl;
 | 
			
		||||
| 
						 | 
				
			
			@ -265,6 +276,7 @@ private:
 | 
			
		|||
    std::unique_ptr<Wallet2CallbackImpl> m_wallet2Callback;
 | 
			
		||||
    std::unique_ptr<AddressBookImpl>  m_addressBook;
 | 
			
		||||
    std::unique_ptr<SubaddressImpl>  m_subaddress;
 | 
			
		||||
    std::unique_ptr<CoinsImpl> m_coins;
 | 
			
		||||
    std::unique_ptr<SubaddressAccountImpl>  m_subaddressAccount;
 | 
			
		||||
 | 
			
		||||
    // multi-threaded refresh stuff
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -250,6 +250,7 @@ struct TransactionInfo
 | 
			
		|||
    virtual std::string paymentId() const = 0;
 | 
			
		||||
    //! only applicable for output transactions
 | 
			
		||||
    virtual const std::vector<Transfer> & transfers() const = 0;
 | 
			
		||||
    virtual const std::vector<std::pair<std::string, std::vector<uint64_t>>> & rings() const = 0;
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * @brief The TransactionHistory - interface for displaying transaction history
 | 
			
		||||
| 
						 | 
				
			
			@ -312,22 +313,66 @@ struct AddressBook
 | 
			
		|||
    virtual int lookupPaymentID(const std::string &payment_id) const = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief The CoinsInfo - interface for displaying coins information
 | 
			
		||||
 */
 | 
			
		||||
struct CoinsInfo
 | 
			
		||||
{
 | 
			
		||||
    virtual ~CoinsInfo() = 0;
 | 
			
		||||
 | 
			
		||||
    virtual uint64_t blockHeight() const = 0;
 | 
			
		||||
    virtual std::string hash() const = 0;
 | 
			
		||||
    virtual size_t internalOutputIndex() const = 0;
 | 
			
		||||
    virtual uint64_t globalOutputIndex() const = 0;
 | 
			
		||||
    virtual bool spent() const = 0;
 | 
			
		||||
    virtual bool frozen() const = 0;
 | 
			
		||||
    virtual uint64_t spentHeight() const = 0;
 | 
			
		||||
    virtual uint64_t amount() const = 0;
 | 
			
		||||
    virtual bool rct() const = 0;
 | 
			
		||||
    virtual bool keyImageKnown() const = 0;
 | 
			
		||||
    virtual size_t pkIndex() const = 0;
 | 
			
		||||
    virtual uint32_t subaddrIndex() const = 0;
 | 
			
		||||
    virtual uint32_t subaddrAccount() const = 0;
 | 
			
		||||
    virtual std::string address() const = 0;
 | 
			
		||||
    virtual std::string addressLabel() const = 0;
 | 
			
		||||
    virtual std::string keyImage() const = 0;
 | 
			
		||||
    virtual uint64_t unlockTime() const = 0;
 | 
			
		||||
    virtual bool unlocked() const = 0;
 | 
			
		||||
    virtual std::string pubKey() const = 0;
 | 
			
		||||
    virtual bool coinbase() const = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Coins
 | 
			
		||||
{
 | 
			
		||||
    virtual ~Coins() = 0;
 | 
			
		||||
    virtual int count() const = 0;
 | 
			
		||||
    virtual CoinsInfo * coin(int index)  const = 0;
 | 
			
		||||
    virtual std::vector<CoinsInfo*> getAll() const = 0;
 | 
			
		||||
    virtual void refresh() = 0;
 | 
			
		||||
    virtual void setFrozen(int index) = 0;
 | 
			
		||||
    virtual void thaw(int index) = 0;
 | 
			
		||||
    virtual bool isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct SubaddressRow {
 | 
			
		||||
public:
 | 
			
		||||
    SubaddressRow(std::size_t _rowId, const std::string &_address, const std::string &_label):
 | 
			
		||||
    SubaddressRow(std::size_t _rowId, const std::string &_address, const std::string &_label, bool _used):
 | 
			
		||||
        m_rowId(_rowId),
 | 
			
		||||
        m_address(_address),
 | 
			
		||||
        m_label(_label) {}
 | 
			
		||||
        m_label(_label),
 | 
			
		||||
        m_used(_used) {}
 | 
			
		||||
 
 | 
			
		||||
private:
 | 
			
		||||
    std::size_t m_rowId;
 | 
			
		||||
    std::string m_address;
 | 
			
		||||
    std::string m_label;
 | 
			
		||||
    bool m_used;
 | 
			
		||||
public:
 | 
			
		||||
    std::string extra;
 | 
			
		||||
    std::string getAddress() const {return m_address;}
 | 
			
		||||
    std::string getLabel() const {return m_label;}
 | 
			
		||||
    std::size_t getRowId() const {return m_rowId;}
 | 
			
		||||
    bool isUsed() const {return m_used;}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Subaddress
 | 
			
		||||
| 
						 | 
				
			
			@ -915,6 +960,18 @@ struct Wallet
 | 
			
		|||
                                                   uint32_t subaddr_account = 0,
 | 
			
		||||
                                                   std::set<uint32_t> subaddr_indices = {}) = 0;
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
     * \brief createTransactionSingle creates transaction with single input
 | 
			
		||||
     * \param key_image               key image as string
 | 
			
		||||
     * \param dst_addr                destination address as string
 | 
			
		||||
     * \param priority
 | 
			
		||||
     * \return                        PendingTransaction object. caller is responsible to check PendingTransaction::status()
 | 
			
		||||
     *                                after object returned
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    virtual PendingTransaction * createTransactionSingle(const std::string &key_image, const std::string &dst_addr,
 | 
			
		||||
                                                         size_t outputs = 1, PendingTransaction::Priority = PendingTransaction::Priority_Low) = 0;
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
     * \brief createSweepUnmixableTransaction creates transaction with unmixable outputs.
 | 
			
		||||
     * \return                  PendingTransaction object. caller is responsible to check PendingTransaction::status()
 | 
			
		||||
| 
						 | 
				
			
			@ -1009,6 +1066,7 @@ struct Wallet
 | 
			
		|||
 | 
			
		||||
    virtual TransactionHistory * history() = 0;
 | 
			
		||||
    virtual AddressBook * addressBook() = 0;
 | 
			
		||||
    virtual Coins * coins() = 0;
 | 
			
		||||
    virtual Subaddress * subaddress() = 0;
 | 
			
		||||
    virtual SubaddressAccount * subaddressAccount() = 0;
 | 
			
		||||
    virtual void setListener(WalletListener *) = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1065,7 +1123,8 @@ struct Wallet
 | 
			
		|||
    /*
 | 
			
		||||
     * \brief signMessage - sign a message with the spend private key
 | 
			
		||||
     * \param message - the message to sign (arbitrary byte data)
 | 
			
		||||
     * \return the signature
 | 
			
		||||
     * \param address - the address to make the signature with, defaults to primary address (optional)
 | 
			
		||||
     * \return the signature, empty string if the address is invalid or does not belong to the wallet
 | 
			
		||||
     */
 | 
			
		||||
    virtual std::string signMessage(const std::string &message, const std::string &address = "") = 0;
 | 
			
		||||
    /*!
 | 
			
		||||
| 
						 | 
				
			
			@ -1276,6 +1335,25 @@ struct WalletManager
 | 
			
		|||
        return createWalletFromKeys(path, password, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
     * \brief  recover deterministic wallet from spend key.
 | 
			
		||||
     * \param  path           Name of wallet file to be created
 | 
			
		||||
     * \param  password       Password of wallet file
 | 
			
		||||
     * \param  language       language
 | 
			
		||||
     * \param  nettype        Network type
 | 
			
		||||
     * \param  restoreHeight  restore from start height
 | 
			
		||||
     * \param  spendKeyString spend key
 | 
			
		||||
     * \param  kdf_rounds     Number of rounds for key derivation function
 | 
			
		||||
     * \return                Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
 | 
			
		||||
     */
 | 
			
		||||
    virtual Wallet * createDeterministicWalletFromSpendKey(const std::string &path,
 | 
			
		||||
                                                           const std::string &password,
 | 
			
		||||
                                                           const std::string &language,
 | 
			
		||||
                                                           NetworkType nettype,
 | 
			
		||||
                                                           uint64_t restoreHeight,
 | 
			
		||||
                                                           const std::string &spendKeyString,
 | 
			
		||||
                                                           uint64_t kdf_rounds = 1) = 0;
 | 
			
		||||
 | 
			
		||||
   /*!
 | 
			
		||||
    * \deprecated this method creates a wallet WITHOUT a passphrase, use createWalletFromKeys(..., password, ...) instead
 | 
			
		||||
    * \brief  recovers existing wallet using keys. Creates a view only wallet if spend key is omitted
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -127,6 +127,22 @@ Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
 | 
			
		|||
    return wallet;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Wallet *WalletManagerImpl::createDeterministicWalletFromSpendKey(const std::string &path,
 | 
			
		||||
                                                                 const std::string &password,
 | 
			
		||||
                                                                 const std::string &language,
 | 
			
		||||
                                                                 NetworkType nettype,
 | 
			
		||||
                                                                 uint64_t restoreHeight,
 | 
			
		||||
                                                                 const std::string &spendkey_string,
 | 
			
		||||
                                                                 uint64_t kdf_rounds)
 | 
			
		||||
{
 | 
			
		||||
    WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds);
 | 
			
		||||
    if(restoreHeight > 0){
 | 
			
		||||
        wallet->setRefreshFromBlockHeight(restoreHeight);
 | 
			
		||||
    }
 | 
			
		||||
    wallet->recoverDeterministicWalletFromSpendKey(path, password, language, spendkey_string);
 | 
			
		||||
    return wallet;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path,
 | 
			
		||||
                                                  const std::string &password,
 | 
			
		||||
                                                  NetworkType nettype,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,6 +67,13 @@ public:
 | 
			
		|||
                                                    const std::string &addressString,
 | 
			
		||||
                                                    const std::string &viewKeyString,
 | 
			
		||||
                                                    const std::string &spendKeyString = "") override;
 | 
			
		||||
    virtual Wallet * createDeterministicWalletFromSpendKey(const std::string &path,
 | 
			
		||||
                                                           const std::string &password,
 | 
			
		||||
                                                           const std::string &language,
 | 
			
		||||
                                                           NetworkType nettype,
 | 
			
		||||
                                                           uint64_t restoreHeight,
 | 
			
		||||
                                                           const std::string &spendkey_string,
 | 
			
		||||
                                                           uint64_t kdf_rounds) override;
 | 
			
		||||
    virtual Wallet * createWalletFromDevice(const std::string &path,
 | 
			
		||||
                                            const std::string &password,
 | 
			
		||||
                                            NetworkType nettype,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -193,7 +193,7 @@ boost::optional<std::string> NodeRPCProxy::get_target_height(uint64_t &height)
 | 
			
		|||
  auto res = get_info();
 | 
			
		||||
  if (res)
 | 
			
		||||
    return res;
 | 
			
		||||
  height = m_target_height;
 | 
			
		||||
  height = m_target_height > m_height ? m_target_height : m_height;
 | 
			
		||||
  return boost::optional<std::string>();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1574,6 +1574,14 @@ void wallet2::add_subaddress_account(const std::string& label)
 | 
			
		|||
  m_subaddress_labels[index_major][0] = label;
 | 
			
		||||
}
 | 
			
		||||
//----------------------------------------------------------------------------------------------------
 | 
			
		||||
bool wallet2::get_subaddress_used(const cryptonote::subaddress_index& index)
 | 
			
		||||
{
 | 
			
		||||
  return std::find_if(m_transfers.begin(), m_transfers.end(),
 | 
			
		||||
  [this, index](const transfer_details &td) {
 | 
			
		||||
  return td.m_subaddr_index == index;
 | 
			
		||||
  }) != m_transfers.end();
 | 
			
		||||
}
 | 
			
		||||
//----------------------------------------------------------------------------------------------------
 | 
			
		||||
void wallet2::add_subaddress(uint32_t index_major, const std::string& label)
 | 
			
		||||
{
 | 
			
		||||
  THROW_WALLET_EXCEPTION_IF(index_major >= m_subaddress_labels.size(), error::account_index_outofbound);
 | 
			
		||||
| 
						 | 
				
			
			@ -2459,13 +2467,14 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
 | 
			
		|||
          uint64_t amount = tx.vout[o].amount ? tx.vout[o].amount : tx_scan_info[o].amount;
 | 
			
		||||
          if (!pool)
 | 
			
		||||
          {
 | 
			
		||||
	    m_transfers.push_back(transfer_details{});
 | 
			
		||||
	    transfer_details& td = m_transfers.back();
 | 
			
		||||
	    td.m_block_height = height;
 | 
			
		||||
	    td.m_internal_output_index = o;
 | 
			
		||||
	    td.m_global_output_index = o_indices[o];
 | 
			
		||||
	    td.m_tx = (const cryptonote::transaction_prefix&)tx;
 | 
			
		||||
	    td.m_txid = txid;
 | 
			
		||||
            boost::unique_lock<boost::shared_mutex> lock(m_transfers_mutex);
 | 
			
		||||
            m_transfers.push_back(transfer_details{});
 | 
			
		||||
            transfer_details& td = m_transfers.back();
 | 
			
		||||
            td.m_block_height = height;
 | 
			
		||||
            td.m_internal_output_index = o;
 | 
			
		||||
            td.m_global_output_index = o_indices[o];
 | 
			
		||||
            td.m_tx = (const cryptonote::transaction_prefix&)tx;
 | 
			
		||||
            td.m_txid = txid;
 | 
			
		||||
            td.m_key_image = tx_scan_info[o].ki;
 | 
			
		||||
            td.m_key_image_known = !m_watch_only && !m_multisig;
 | 
			
		||||
            if (!td.m_key_image_known)
 | 
			
		||||
| 
						 | 
				
			
			@ -2562,12 +2571,13 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
 | 
			
		|||
          uint64_t extra_amount = amount - burnt;
 | 
			
		||||
          if (!pool)
 | 
			
		||||
          {
 | 
			
		||||
            boost::unique_lock<boost::shared_mutex> lock(m_transfers_mutex);
 | 
			
		||||
            transfer_details &td = m_transfers[kit->second];
 | 
			
		||||
	    td.m_block_height = height;
 | 
			
		||||
	    td.m_internal_output_index = o;
 | 
			
		||||
	    td.m_global_output_index = o_indices[o];
 | 
			
		||||
	    td.m_tx = (const cryptonote::transaction_prefix&)tx;
 | 
			
		||||
	    td.m_txid = txid;
 | 
			
		||||
            td.m_block_height = height;
 | 
			
		||||
            td.m_internal_output_index = o;
 | 
			
		||||
            td.m_global_output_index = o_indices[o];
 | 
			
		||||
            td.m_tx = (const cryptonote::transaction_prefix&)tx;
 | 
			
		||||
            td.m_txid = txid;
 | 
			
		||||
            td.m_amount = amount;
 | 
			
		||||
            td.m_pk_index = pk_index - 1;
 | 
			
		||||
            td.m_subaddr_index = tx_scan_info[o].received->index;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1044,6 +1044,7 @@ private:
 | 
			
		|||
    std::string get_subaddress_as_str(const cryptonote::subaddress_index& index) const;
 | 
			
		||||
    std::string get_address_as_str() const { return get_subaddress_as_str({0, 0}); }
 | 
			
		||||
    std::string get_integrated_address_as_str(const crypto::hash8& payment_id) const;
 | 
			
		||||
    bool get_subaddress_used(const cryptonote::subaddress_index& index);
 | 
			
		||||
    void add_subaddress_account(const std::string& label);
 | 
			
		||||
    size_t get_num_subaddress_accounts() const { return m_subaddress_labels.size(); }
 | 
			
		||||
    size_t get_num_subaddresses(uint32_t index_major) const { return index_major < m_subaddress_labels.size() ? m_subaddress_labels[index_major].size() : 0; }
 | 
			
		||||
| 
						 | 
				
			
			@ -1715,6 +1716,7 @@ private:
 | 
			
		|||
 | 
			
		||||
    static std::string get_default_daemon_address() { CRITICAL_REGION_LOCAL(default_daemon_address_lock); return default_daemon_address; }
 | 
			
		||||
 | 
			
		||||
    boost::shared_mutex m_transfers_mutex;
 | 
			
		||||
  private:
 | 
			
		||||
    /*!
 | 
			
		||||
     * \brief  Stores wallet information to wallet file.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue