This commit is contained in:
SNeedlewoods 2024-12-02 15:24:49 +00:00 committed by GitHub
commit 26c2ded3e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 1709 additions and 62 deletions

View File

@ -33,6 +33,7 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(wallet_api_sources
wallet.cpp
wallet_manager.cpp
enote_details.cpp
transaction_info.cpp
transaction_history.cpp
pending_transaction.cpp
@ -48,6 +49,7 @@ set(wallet_api_headers
set(wallet_api_private_headers
wallet.h
wallet_manager.h
enote_details.h
transaction_info.h
transaction_history.h
pending_transaction.h

View File

@ -0,0 +1,96 @@
// Copyright (c) 2014-2024, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "enote_details.h"
namespace Monero {
EnoteDetails::~EnoteDetails() {}
EnoteDetailsImpl::EnoteDetailsImpl():
m_block_height(0),
m_internal_enote_index(0),
m_global_enote_index(0),
m_spent(false),
m_frozen(false),
m_spent_height(0),
m_amount(0),
m_protocol_version(Tx_Protocol_CryptoNote),
m_key_image_known(false),
m_key_image_request(false),
m_pk_index(0),
m_key_image_partial(false)
{
}
EnoteDetailsImpl::~EnoteDetailsImpl() {}
std::string EnoteDetailsImpl::onetimeAddress() const
{ return m_onetime_address; }
std::string EnoteDetailsImpl::viewTag() const
{ return m_view_tag; }
std::uint64_t EnoteDetailsImpl::blockHeight() const
{ return m_block_height; }
std::string EnoteDetailsImpl::txId() const
{ return m_tx_id; }
std::uint64_t EnoteDetailsImpl::internalEnoteIndex() const
{ return m_internal_enote_index; }
std::uint64_t EnoteDetailsImpl::globalEnoteIndex() const
{ return m_global_enote_index; }
bool EnoteDetailsImpl::isSpent() const
{ return m_spent; }
bool EnoteDetailsImpl::isFrozen() const
{ return m_frozen; }
std::uint64_t EnoteDetailsImpl::spentHeight() const
{ return m_spent_height; }
std::string EnoteDetailsImpl::keyImage() const
{ return m_key_image; }
std::string EnoteDetailsImpl::mask() const
{ return m_mask; }
std::uint64_t EnoteDetailsImpl::amount() const
{ return m_amount; }
EnoteDetails::TxProtocol EnoteDetailsImpl::protocolVersion() const
{ return m_protocol_version; }
bool EnoteDetailsImpl::isKeyImageKnown() const
{ return m_key_image_known; }
bool EnoteDetailsImpl::isKeyImageRequest() const
{ return m_key_image_request; }
std::uint64_t EnoteDetailsImpl::pkIndex() const
{ return m_pk_index; }
std::vector<std::pair<std::uint64_t, std::string>> EnoteDetailsImpl::uses() const
{ return m_uses; }
// Multisig
bool EnoteDetailsImpl::isKeyImagePartial() const
{ return m_key_image_partial; }
} // namespace

View File

@ -0,0 +1,109 @@
// Copyright (c) 2014-2024, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "wallet/api/wallet2_api.h"
namespace Monero {
class EnoteDetailsImpl : public EnoteDetails
{
public:
EnoteDetailsImpl();
~EnoteDetailsImpl() override;
std::string onetimeAddress() const override;
std::string viewTag() const override;
std::uint64_t blockHeight() const override;
std::string txId() const override;
std::uint64_t internalEnoteIndex() const override;
std::uint64_t globalEnoteIndex() const override;
bool isSpent() const override;
bool isFrozen() const override;
std::uint64_t spentHeight() const override;
std::string keyImage() const override;
std::string mask() const override;
std::uint64_t amount() const override;
TxProtocol protocolVersion() const override;
bool isKeyImageKnown() const override;
bool isKeyImageRequest() const override;
std::uint64_t pkIndex() const override;
std::vector<std::pair<std::uint64_t, std::string>> uses() const override;
// Multisig
bool isKeyImagePartial() const override;
private:
friend class WalletImpl;
// Ko
std::string m_onetime_address;
// view_tag
std::string m_view_tag;
// this enote was received at block height
std::uint64_t m_block_height;
// tx id in which tx enote was received
std::string m_tx_id;
// relative index in tx
std::uint64_t m_internal_enote_index;
// absolute index from `cryptonote::COMMAND_RPC_GET_TRANSACTIONS::entry.output_indices`
std::uint64_t m_global_enote_index;
// is spent
bool m_spent;
// is frozen
bool m_frozen;
// blockchain height, set if spent
std::uint64_t m_spent_height;
// key image
std::string m_key_image;
// x, blinding factor in amount commitment C = x G + a H
std::string m_mask;
// a
std::uint64_t m_amount;
// protocol version : Tx_Protocol_CryptoNote / Tx_Protocol_RingCT
TxProtocol m_protocol_version;
// is key image known
bool m_key_image_known;
// view wallets: we want to request it; cold wallets: it was requested
bool m_key_image_request;
// public key index in tx_extra
std::uint64_t m_pk_index;
// track uses of this enote in the blockchain in the format [ [block_height, tx_id], ... ] if `wallet2::m_track_uses` is true (default is false)
std::vector<std::pair<std::uint64_t, std::string>> m_uses;
// Multisig
bool m_key_image_partial;
// NOTE : These multisig members are part of wallet2 transfer_details and may need to get added here.
/*
std::vector<rct::key> m_multisig_k;
std::vector<multisig_info> m_multisig_info; // one per other participant
*/
};
} // namespace

View File

@ -69,6 +69,8 @@ private:
std::unordered_set<crypto::public_key> m_signers;
std::vector<std::string> m_tx_device_aux;
std::vector<crypto::key_image> m_key_images;
// wallet2 m_cold_key_images
std::unordered_map<crypto::public_key, crypto::key_image> m_tx_key_images;
};

View File

@ -150,6 +150,11 @@ void TransactionHistoryImpl::refresh()
ti->m_timestamp = pd.m_timestamp;
ti->m_confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
ti->m_unlock_time = pd.m_unlock_time;
// not used for payment_details
ti->m_change = 0;
ti->m_tx_state = TransactionInfo::confirmed;
// not used for payment_details
ti->m_double_spend_seen = false;
m_history.push_back(ti);
}
@ -193,6 +198,11 @@ 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 = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
ti->m_unlock_time = pd.m_unlock_time;
ti->m_change = pd.m_change;
ti->m_tx_state = TransactionInfo::confirmed;
// not used for confirmed_transfer_details
ti->m_double_spend_seen = false;
// single output transaction might contain multiple transfers
for (const auto &d: pd.m_dests) {
@ -229,6 +239,11 @@ 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;
ti->m_unlock_time = pd.m_tx.unlock_time;
ti->m_change = pd.m_change;
ti->m_tx_state = (TransactionInfo::TxState) pd.m_state;
// not used for unconfirmed_transfer_details
ti->m_double_spend_seen = false;
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)});
@ -258,6 +273,11 @@ void TransactionHistoryImpl::refresh()
ti->m_label = m_wallet->m_wallet->get_subaddress_label(pd.m_subaddr_index);
ti->m_timestamp = pd.m_timestamp;
ti->m_confirmations = 0;
ti->m_unlock_time = pd.m_unlock_time;
// not used for pool_payment_details
ti->m_change = 0;
ti->m_tx_state = TransactionInfo::pending_in_pool;
ti->m_double_spend_seen = i->second.m_double_spend_seen;
m_history.push_back(ti);
LOG_PRINT_L1(__FUNCTION__ << ": Unconfirmed payment found " << pd.m_amount);

View File

@ -149,4 +149,19 @@ uint64_t TransactionInfoImpl::unlockTime() const
return m_unlock_time;
}
std::uint64_t TransactionInfoImpl::receivedChangeAmount() const
{
return m_change;
}
TransactionInfo::TxState TransactionInfoImpl::txState() const
{
return m_tx_state;
}
bool TransactionInfoImpl::isDoubleSpendSeen() const
{
return m_double_spend_seen;
}
} // namespace

View File

@ -63,6 +63,10 @@ public:
virtual uint64_t confirmations() const override;
virtual uint64_t unlockTime() const override;
std::uint64_t receivedChangeAmount() const override;
TxState txState() const override;
bool isDoubleSpendSeen() const override;
private:
int m_direction;
bool m_pending;
@ -81,6 +85,12 @@ private:
std::vector<Transfer> m_transfers;
uint64_t m_confirmations;
uint64_t m_unlock_time;
// received change amount from outgoing transaction
std::uint64_t m_change;
// tx state : pending / pending_in_pool / failed / confirmed
TxState m_tx_state;
// is double spend seen
bool m_double_spend_seen;
friend class TransactionHistoryImpl;

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,7 @@
class WalletApiAccessorTest;
namespace Monero {
class EnoteDetailsImpl;
class TransactionHistoryImpl;
class PendingTransactionImpl;
class UnsignedTransactionImpl;
@ -207,7 +208,7 @@ public:
virtual bool checkSpendProof(const std::string &txid, const std::string &message, const std::string &signature, bool &good) const override;
virtual std::string getReserveProof(bool all, uint32_t account_index, uint64_t amount, const std::string &message) const override;
virtual bool checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const override;
virtual std::string signMessage(const std::string &message, const std::string &address) override;
virtual std::string signMessage(const std::string &message, const std::string &address, bool sign_with_view_key = false) override;
virtual bool verifySignedMessage(const std::string &message, const std::string &address, const std::string &signature) const override;
virtual std::string signMultisigParticipant(const std::string &message) const override;
virtual bool verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const override;
@ -234,6 +235,53 @@ public:
virtual uint64_t getBytesReceived() override;
virtual uint64_t getBytesSent() override;
std::string getMultisigSeed(const std::string &seed_offset) const override;
std::pair<std::uint32_t, std::uint32_t> getSubaddressIndex(const std::string &address) const override;
void freeze(std::size_t idx) override;
void freeze(const std::string &key_image) override;
void thaw(std::size_t idx) override;
void thaw(const std::string &key_image) override;
bool isFrozen(std::size_t idx) const override;
bool isFrozen(const std::string &key_image) const override;
void createOneOffSubaddress(std::uint32_t account_index, std::uint32_t address_index) override;
WalletState getWalletState() const override;
void rewriteWalletFile(const std::string &wallet_name, const std::string &password) override;
void writeWatchOnlyWallet(const std::string &password, std::string &new_keys_file_name) override;
void refreshPoolOnly(bool refreshed = false, bool try_incremental = false) override;
void getEnoteDetails(std::vector<std::unique_ptr<EnoteDetails>> &enote_details) const override;
std::string convertMultisigTxToStr(const PendingTransaction &multisig_ptx) const override;
bool saveMultisigTx(const PendingTransaction &multisig_ptx, const std::string &filename) const override;
std::string convertTxToStr(const PendingTransaction &ptxs) const override;
bool parseUnsignedTxFromStr(const std::string &unsigned_tx_str, UnsignedTransaction &exported_txs) const override;
bool parseTxFromStr(const std::string &signed_tx_str, PendingTransaction &ptx) const override;
void insertColdKeyImages(PendingTransaction &ptx) override;
bool parseMultisigTxFromStr(const std::string &multisig_tx_str, PendingTransaction &exported_txs) const override;
std::uint64_t getFeeMultiplier(std::uint32_t priority, int fee_algorithm) const override;
std::uint64_t getBaseFee() const override;
std::uint32_t adjustPriority(std::uint32_t priority) override;
void coldTxAuxImport(const PendingTransaction &ptx, const std::vector<std::string> &tx_device_aux) const override;
void coldSignTx(const PendingTransaction &ptx_in, PendingTransaction &exported_txs_out) const override;
void discardUnmixableEnotes() override;
void setTxKey(const std::string &txid, const std::string &tx_key, const std::vector<std::string> &additional_tx_keys, const std::string &single_destination_subaddress) override;
const std::pair<std::map<std::string, std::string>, std::vector<std::string>>& getAccountTags() const override;
void setAccountTag(const std::set<uint32_t> &account_indices, const std::string &tag) override;
void setAccountTagDescription(const std::string &tag, const std::string &description) override;
std::string exportEnotesToStr(bool all = false, std::uint32_t start = 0, std::uint32_t count = 0xffffffff) const override;
std::size_t importEnotesFromStr(const std::string &enotes_str) override;
std::uint64_t getBlockchainHeightByDate(std::uint16_t year, std::uint8_t month, std::uint8_t day) const override;
std::vector<std::pair<std::uint64_t, std::uint64_t>> estimateBacklog(const std::vector<std::pair<double, double>> &fee_levels) const override;
bool saveToFile(const std::string &path_to_file, const std::string &binary, bool is_printable = false) const override;
bool loadFromFile(const std::string &path_to_file, std::string &target_str, std::size_t max_size = 1000000000) const override;
std::uint64_t hashEnotes(std::uint64_t enote_idx, std::string &hash) const override;
void finishRescanBcKeepKeyImages(std::uint64_t enote_idx, const std::string &hash) override;
std::vector<std::tuple<std::string, std::uint16_t, std::uint64_t>> getPublicNodes(bool white_only = true) const override;
std::pair<std::size_t, std::uint64_t> estimateTxSizeAndWeight(bool use_rct, int n_inputs, int ring_size, int n_outputs, std::size_t extra_size) const override;
std::uint64_t importKeyImages(const std::vector<std::pair<std::string, std::string>> &signed_key_images, std::size_t offset, std::uint64_t &spent, std::uint64_t &unspent, bool check_spent = true) override;
bool importKeyImages(const std::vector<std::string> &key_images, std::size_t offset = 0, const std::unordered_set<std::size_t> &selected_enotes_indices = {}) override;
bool getAllowMismatchedDaemonVersion() const override;
void setAllowMismatchedDaemonVersion(bool allow_mismatch) override;
bool setDaemon(const std::string &daemon_address, const std::string &daemon_username = "", const std::string &daemon_password = "", bool trusted_daemon = true, const std::string &ssl_support = "autodetect", const std::string &ssl_private_key_path = "", const std::string &ssl_certificate_path = "", const std::string &ssl_ca_file_path = "", const std::vector<std::string> &ssl_allowed_fingerprints_str = {}, bool ssl_allow_any_cert = false, const std::string &proxy = "") override;
private:
void clearStatus() const;
void setStatusError(const std::string& message) const;
@ -248,6 +296,18 @@ private:
bool doInit(const std::string &daemon_address, const std::string &proxy_address, uint64_t upper_transaction_size_limit = 0, bool ssl = false);
bool checkBackgroundSync(const std::string &message) const;
/**
* brief: getEnoteIndex - get the index of an enote in local enote storage
* param: key_image - key image to identify the enote
* return: enote index
*/
std::size_t getEnoteIndex(const std::string &key_image) const;
/**
* brief: statusOk -
* return: true if status is ok, else false
*/
bool statusOk() const;
private:
friend class PendingTransactionImpl;
friend class UnsignedTransactionImpl;

View File

@ -38,8 +38,12 @@
#include <ctime>
#include <iostream>
#include <stdexcept>
#include <map>
#include <memory>
#include <unordered_set>
#include <cstdint>
// Public interface for libwallet library
namespace Monero {
@ -67,6 +71,39 @@ enum NetworkType : uint8_t {
bool set;
};
/**
* brief: EnoteDetails - Container for all the necessary information that belongs to an enote
*/
struct EnoteDetails
{
enum TxProtocol {
Tx_Protocol_CryptoNote,
Tx_Protocol_RingCT
};
virtual ~EnoteDetails() = 0;
virtual std::string onetimeAddress() const = 0;
virtual std::string viewTag() const = 0;
virtual std::uint64_t blockHeight() const = 0;
virtual std::string txId() const = 0;
virtual std::uint64_t internalEnoteIndex() const = 0;
virtual std::uint64_t globalEnoteIndex() const = 0;
virtual bool isSpent() const = 0;
virtual bool isFrozen() const = 0;
virtual std::uint64_t spentHeight() const = 0;
virtual std::string keyImage() const = 0;
virtual std::string mask() const = 0;
virtual std::uint64_t amount() const = 0;
virtual TxProtocol protocolVersion() const = 0;
virtual bool isKeyImageKnown() const = 0;
virtual bool isKeyImageRequest() const = 0;
virtual std::uint64_t pkIndex() const = 0;
virtual std::vector<std::pair<std::uint64_t, std::string>> uses() const = 0;
// Multisig
virtual bool isKeyImagePartial() const = 0;
};
/**
* @brief Transaction-like interface for sending money
*/
@ -173,6 +210,13 @@ struct TransactionInfo
Direction_Out
};
enum TxState {
pending,
pending_in_pool,
failed,
confirmed
};
struct Transfer {
Transfer(uint64_t _amount, const std::string &address);
const uint64_t amount;
@ -181,7 +225,9 @@ struct TransactionInfo
virtual ~TransactionInfo() = 0;
virtual int direction() const = 0;
// legacy : use txState() instead
virtual bool isPending() const = 0;
// legacy : use txState() instead
virtual bool isFailed() const = 0;
virtual bool isCoinbase() const = 0;
virtual uint64_t amount() const = 0;
@ -199,6 +245,10 @@ struct TransactionInfo
virtual std::string paymentId() const = 0;
//! only applicable for output transactions
virtual const std::vector<Transfer> & transfers() const = 0;
virtual std::uint64_t receivedChangeAmount() const = 0;
virtual TxState txState() const = 0;
virtual bool isDoubleSpendSeen() const = 0;
};
/**
* @brief The TransactionHistory - interface for displaying transaction history
@ -304,7 +354,6 @@ private:
std::string m_balance;
std::string m_unlockedBalance;
public:
std::string extra;
std::string getAddress() const {return m_address;}
std::string getLabel() const {return m_label;}
std::string getBalance() const {return m_balance;}
@ -420,6 +469,18 @@ struct WalletListener
* @brief If the listener is created before the wallet this enables to set created wallet object
*/
virtual void onSetWallet(Wallet * wallet) { (void)wallet; };
/**
* brief: onReorg - called on blockchain reorg
*/
virtual void onReorg(std::uint64_t height, std::uint64_t blocks_detached, std::size_t transfers_detached) = 0;
/**
* brief: onGetPassword - called by scan_output() to decrypt keys
*/
virtual optional<std::string> onGetPassword(const char *reason) = 0;
/**
* brief: onPoolTxRemoved - when obsolete pool transactions get removed
*/
virtual void onPoolTxRemoved(const std::string &txid) = 0;
};
@ -452,6 +513,13 @@ struct Wallet
BackgroundSync_CustomPassword = 2
};
struct WalletState {
// is wallet file format deprecated
bool is_deprecated;
std::uint64_t ring_size;
std::string daemon_address;
};
virtual ~Wallet() = 0;
virtual std::string seed(const std::string& seed_offset = "") const = 0;
virtual std::string getSeedLanguage() const = 0;
@ -699,6 +767,14 @@ struct Wallet
return paymentIdFromAddress(str, testnet ? TESTNET : MAINNET);
}
static uint64_t maximumAllowedAmount();
/**
* brief: walletExists - check if wallet file and .keys file exist for given path
* param: path - filename
* outparam: keys_file_exists -
* outparam: wallet_file_exists -
* return: true if (key_file_exists || wallet_file_exists)
*/
static bool walletExists(const std::string &path, bool &key_file_exists, bool &wallet_file_exists);
// Easylogger wrapper
static void init(const char *argv0, const char *default_log_base_name) { init(argv0, default_log_base_name, "", true); }
static void init(const char *argv0, const char *default_log_base_name, const std::string &log_path, bool console);
@ -1043,12 +1119,15 @@ struct Wallet
virtual std::string getReserveProof(bool all, uint32_t account_index, uint64_t amount, const std::string &message) const = 0;
virtual bool checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const = 0;
/*
* \brief signMessage - sign a message with the spend private key
* \param message - the message to sign (arbitrary byte data)
* \return the signature
*/
virtual std::string signMessage(const std::string &message, const std::string &address = "") = 0;
/**
* brief: signMessage - sign a message with your private key (SigV2)
* param: message - message to sign (arbitrary byte data)
* param: address - address used to sign the message (use main address if empty)
* param: sign_with_view_key - (default: false, use spend key to sign)
* return: proof type prefix + base58 encoded signature, else empty string
* note: sets status error on fail
*/
virtual std::string signMessage(const std::string &message, const std::string &address = "", bool sign_with_view_key = false) = 0;
/*!
* \brief verifySignedMessage - verify a signature matches a given message
* \param message - the message (arbitrary byte data)
@ -1144,6 +1223,342 @@ struct Wallet
//! get bytes sent
virtual uint64_t getBytesSent() = 0;
/**
* brief: getMultisigSeed - get seed for multisig wallet
* param: seed_offset - passphrase
* return: seed if succeeded, else empty string
* note: sets status error on fail
*/
virtual std::string getMultisigSeed(const std::string &seed_offset) const = 0;
/**
* brief: getSubaddressIndex - get major and minor index of provided subaddress
* param: address - main- or sub-address to get the index from
* return: [major_index, minor_index] if succeeded
* note: sets status error on fail
*/
virtual std::pair<std::uint32_t, std::uint32_t> getSubaddressIndex(const std::string &address) const = 0;
/**
* brief: freeze - freeze enote "so they don't appear in balance, nor are considered when creating a transaction, etc." (https://github.com/monero-project/monero/pull/5333)
* param: idx - index of enote in local enote storage
* param: key_image - key image of enote
* note: sets status error on fail
*/
virtual void freeze(std::size_t idx) = 0;
virtual void freeze(const std::string &key_image) = 0;
/**
* brief: thaw - thaw enote that is frozen, so it appears in balance and can be spent in a transaction
* param: idx - index of enote in local enote storage
* param: key_image - key image of enote
* note: sets status error on fail
*/
virtual void thaw(std::size_t idx) = 0;
virtual void thaw(const std::string &key_image) = 0;
/**
* brief: isFrozen - check if enote is frozen
* param: idx - index of enote in local enote storage
* param: key_image - key image of enote
* return : true if enote is frozen, else false
* note: sets status error on fail
*/
virtual bool isFrozen(std::size_t idx) const = 0;
virtual bool isFrozen(const std::string &key_image) const = 0;
/**
* brief: createOneOffSubaddress - create a subaddress for given index
* param: account_index - major index
* param: address_index - minor index
*/
virtual void createOneOffSubaddress(std::uint32_t account_index, std::uint32_t address_index) = 0;
/**
* brief: getWalletState - get information about the wallet
* return: WalletState object
*/
virtual WalletState getWalletState() const = 0;
/**
* brief: rewriteWalletFile - rewrite the wallet file for wallet update
* param: wallet_name - name of the wallet file (should exist)
* param: password - wallet password
* note: sets status error on fail
*/
virtual void rewriteWalletFile(const std::string &wallet_name, const std::string &password) = 0;
/**
* brief: writeWatchOnlyWallet - create a new watch-only wallet file with view keys from current wallet
* param: password - password for new watch-only wallet
* outparam: new_keys_file_name - wallet_name + "-watchonly.keys"
* note: sets status error on fail
*/
virtual void writeWatchOnlyWallet(const std::string &password, std::string &new_keys_file_name) = 0;
/**
* brief: refreshPoolOnly - calls wallet2 update_pool_state and process_pool_state
* param: refreshed - (default: false)
* param: try_incremental - (default: false)
* note: sets status error on fail
*/
virtual void refreshPoolOnly(bool refreshed = false, bool try_incremental = false) = 0;
/**
* brief: getEnoteDetails - get information about all enotes
* outparam: enote_details -
*/
virtual void getEnoteDetails(std::vector<std::unique_ptr<EnoteDetails>> &enote_details) const = 0;
/**
* brief: convertMultisigTxToString - get the encrypted unsigned multisig transaction as hex string from a multisig pending transaction
* param: multisig_ptx - multisig pending transaction
* return: encrypted tx data as hex string if succeeded, else empty string
* note: sets status error on fail
*/
virtual std::string convertMultisigTxToStr(const PendingTransaction &multisig_ptx) const = 0;
/**
* brief: saveMultisigTx - save a multisig pending transaction to file
* param: multisig_ptx - multisig pending transaction
* param: filename -
* return: true if succeeded
* note: sets status error on fail
*/
virtual bool saveMultisigTx(const PendingTransaction &multisig_ptx, const std::string &filename) const = 0;
/**
* brief: convertTxToStr - get the encrypted data from a vector of pending transactions as hex string
* param: ptxs -
* return: unsigned tx data as encrypted hex string if succeeded, else empty string
* note: sets status error on fail
*/
virtual std::string convertTxToStr(const PendingTransaction &ptxs) const = 0;
/**
* brief: parseUnsignedTxFromStr - get an unsigned transaction set from encrypted unsigned transaction as hex string
* param: unsigned_tx_str - encrypted hex string
* outparam: exported_txs -
* return: true if succeeded
*/
virtual bool parseUnsignedTxFromStr(const std::string &unsigned_tx_str, UnsignedTransaction &exported_txs) const = 0;
/**
* brief: parseTxFromStr - get transactions from encrypted signed transaction as hex string
* param: signed_tx_str -
* outparam: ptx -
* return: true if succeeded
*/
virtual bool parseTxFromStr(const std::string &signed_tx_str, PendingTransaction &ptx) const = 0;
/**
* brief: insertColdKeyImages - remember cold key images for parsed tx, for when we get those txes from the blockchain
* Call:
* - parseTxFromStr()
* - accept_func() (optional)
* - importKeyImages()
* - insertColdKeyImages()
* param: ptx - PendingTransaction obtained from parseTxFromStr() outparam ptx
*/
virtual void insertColdKeyImages(PendingTransaction &ptx) = 0;
/**
* brief: parseMultisigTxFromStr - get pending multisig transaction from encrypted unsigned multisig transaction as hex string
* param: multisig_tx_str -
* outparam: exported_txs -
* return: true if succeeded
* note: sets status error on fail
*/
virtual bool parseMultisigTxFromStr(const std::string &multisig_tx_str, PendingTransaction &exported_txs) const = 0;
/**
* brief: getFeeMultiplier -
* param: priority -
* param: fee_algorithm -
* return: fee multiplier
* note: sets status error on fail
*/
virtual std::uint64_t getFeeMultiplier(std::uint32_t priority, int fee_algorithm) const = 0;
/**
* brief: getBaseFee -
* return: dynamic base fee estimate if using dynamic fee, else FEE_PER_KB
*/
virtual std::uint64_t getBaseFee() const = 0;
/**
* brief: adjustPriority - adjust priority depending on how "full" last N blocks are
* param: priority -
* return: adjusted priority
* warning: doesn't tell if it failed
*/
virtual std::uint32_t adjustPriority(std::uint32_t priority) = 0;
/**
* brief: coldTxAuxImport -
* param: ptx -
* param: tx_device_aux -
* note: sets status error on fail
*/
virtual void coldTxAuxImport(const PendingTransaction &ptx, const std::vector<std::string> &tx_device_aux) const = 0;
/**
* brief: coldSignTx -
* param: ptx_in -
* outparam: exported_txs_out -
*/
virtual void coldSignTx(const PendingTransaction &ptx_in, PendingTransaction &exported_txs_out) const = 0;
/**
* brief: discardUnmixableEnotes - freeze all unmixable enotes
* note: sets status error on fail
*/
virtual void discardUnmixableEnotes() = 0;
/**
* brief: setTxKey - set the transaction key (r) for a given <txid> in case the tx was made by some other device or 3rd party wallet
* param: txid -
* param: tx_key - secret transaction key r
* param: additional_tx_keys -
* param: single_destination_subaddress -
* note: sets status error on fail
*/
virtual void setTxKey(const std::string &txid, const std::string &tx_key, const std::vector<std::string> &additional_tx_keys, const std::string &single_destination_subaddress) = 0;
/**
* brief: getAccountTags - get the list of registered account tags
* return: first.Key=(tag's name), first.Value=(tag's label), second[i]=(i-th account's tag)
*/
virtual const std::pair<std::map<std::string, std::string>, std::vector<std::string>>& getAccountTags() const = 0;
/**
* brief: setAccountTag - set a tag to a set of subaddress accounts by index
* param: account_index - major index
* param: tag -
* note: sets status error on fail
*/
virtual void setAccountTag(const std::set<std::uint32_t> &account_indices, const std::string &tag) = 0;
/**
* brief: setAccountTagDescription - set a description for a tag, tag must already exist
* param: tag -
* param: description -
* note: sets status error on fail
*/
virtual void setAccountTagDescription(const std::string &tag, const std::string &description) = 0;
/**
* brief: exportEnotesToStr - export enotes and return encrypted data
* (comparable with legacy exportOutputs(), with the difference that this returns a string, the other one saves to file)
* param: all - go from `start` for `count` enotes if true, else go incremental from last exported enote for `count` enotes (default: false)
* param: start - offset index in enote storage, needs to be 0 for incremental mode (default: 0)
* param: count - try to export this amount of enotes (default: 0xffffffff)
* return: encrypted data of exported enotes as hex string if succeeded, else empty string
* note: sets status error on fail
*/
virtual std::string exportEnotesToStr(bool all = false, std::uint32_t start = 0, std::uint32_t count = 0xffffffff) const = 0;
/**
* brief: importEnotesFromStr - import enotes from encrypted hex string
* param: enotes_str - enotes data as encrypted hex string
* return: total size of enote storage
* note: sets status error on fail
*/
virtual std::size_t importEnotesFromStr(const std::string &enotes_str) = 0;
/**
* brief: getBlockchainHeightByDate -
* param: year -
* param: month - in range 1-12
* param: day - in range 1-31
* return: blockchain height
* note: sets status error on fail
*/
virtual std::uint64_t getBlockchainHeightByDate(std::uint16_t year, std::uint8_t month, std::uint8_t day) const = 0;
/**
* brief: estimateBacklog -
* param: fee_levels - [ [fee per byte min, fee per byte max], ... ]
* return: [ [number of blocks min, number of blocks max], ... ]
* note: sets status error on fail
*/
virtual std::vector<std::pair<std::uint64_t, std::uint64_t>> estimateBacklog(const std::vector<std::pair<double, double>> &fee_levels) const = 0;
/**
* brief: saveToFile - save hex string to file
* param: path_to_file - file name
* param: binary - hex string data
* param: is_printable - (default: false)
* return: true if succeeded
*/
virtual bool saveToFile(const std::string &path_to_file, const std::string &binary, bool is_printable = false) const = 0;
/**
* brief: loadFromFile - load hex string from file
* param: path_to_file - file name
* outparam: target_str - hex string data
* param: max_size - maximum size in bytes (default: 1000000000)
* return: true if succeeded
*/
virtual bool loadFromFile(const std::string &path_to_file, std::string &target_str, std::size_t max_size = 1000000000) const = 0;
/**
* brief: hashEnotes - get hash of all enotes in local enote store up until `enote_idx`
* (formerly in wallet2: `uint64_t wallet2::hash_m_transfers(boost::optional<uint64_t> transfer_height, crypto::hash &hash)`)
* param: enote_idx - include all enotes below this index
* outparam: hash - hash as hex string
* return: number of hashed enotes
* note: sets status error on fail
*/
virtual std::uint64_t hashEnotes(std::uint64_t enote_idx, std::string &hash) const = 0;
/**
* brief: finishRescanBcKeepKeyImages -
* param: enote_idx -
* param: hash -
* note: sets status error on fail
*/
virtual void finishRescanBcKeepKeyImages(std::uint64_t enote_idx, const std::string &hash) = 0;
/**
* brief: getPublicNodes - get a list of public notes with information when they were last seen
* param: white_only - include gray nodes if false (default: true)
* return: [ [ host_ip, host_rpc_port, last_seen ], ... ]
* note: sets status error on fail
*/
virtual std::vector<std::tuple<std::string, std::uint16_t, std::uint64_t>> getPublicNodes(bool white_only = true) const = 0;
/**
* brief: estimateTxSizeAndWeight -
* param: use_rct -
* param: n_inputs - number of input enotes
* param: ring_size -
* param: n_outputs - number of output enotes
* param: extra_size - size of tx_extra
* return: [estimated tx size, estimated tx weight]
* note: sets status error on fail
*/
virtual std::pair<std::size_t, std::uint64_t> estimateTxSizeAndWeight(bool use_rct, int n_inputs, int ring_size, int n_outputs, std::size_t extra_size) const = 0;
/**
* brief: importKeyImages -
* param: signed_key_images - [ [key_image, signature c || signature r], ... ]
* param: offset - offset in local enote storage
* outparam: spent - total spent amount of the wallet
* outparam: unspent - total unspent amount of the wallet
* param: check_spent -
* return: blockchain height of last signed key image, can be 0 if height unknown
* note: sets status error on fail
*/
virtual std::uint64_t importKeyImages(const std::vector<std::pair<std::string, std::string>> &signed_key_images, std::size_t offset, std::uint64_t &spent, std::uint64_t &unspent, bool check_spent = true) = 0;
/**
* brief: importKeyImages -
* param: key_images -
* param: offset - offset in local enote storage
* param: selected_enotes_indices -
* return: true if succeeded
* note: sets status error on fail
*/
virtual bool importKeyImages(const std::vector<std::string> &key_images, std::size_t offset = 0, const std::unordered_set<std::size_t> &selected_enotes_indices = {}) = 0;
/**
* brief: getAllowMismatchedDaemonVersion -
*/
virtual bool getAllowMismatchedDaemonVersion() const = 0;
/**
* brief: setAllowMismatchedDaemonVersion -
* param: allow_mismatch -
*/
virtual void setAllowMismatchedDaemonVersion(bool allow_mismatch) = 0;
/**
* brief: setDaemon -
* param: daemon_address -
* param: daemon_username - for daemon login (default: empty string)
* param: daemon_password - for daemon login (default: empty string)
* param: trusted_daemon - (default: true)
* param: ssl_support - "disabled" | "enabled" | "autodetect" (default: "autodetect")
* param: ssl_private_key_path - (default: empty string)
* param: ssl_certificate_path - (default: empty string)
* param: ssl_ca_file_path - (default: empty string)
* param: ssl_allowed_fingerprints_str - (default: empty vector)
* param: ssl_allow_any_cert - (default: false)
* param: proxy - (default: empty string)
* return: true if succeeded
* note: sets status error on fail
*/
virtual bool setDaemon(const std::string &daemon_address,
const std::string &daemon_username = "",
const std::string &daemon_password = "",
bool trusted_daemon = true,
const std::string &ssl_support = "autodetect",
const std::string &ssl_private_key_path = "",
const std::string &ssl_certificate_path = "",
const std::string &ssl_ca_file_path = "",
const std::vector<std::string> &ssl_allowed_fingerprints_str = {},
bool ssl_allow_any_cert = false,
const std::string &proxy = "") = 0;
};
/**

View File

@ -7979,7 +7979,7 @@ bool wallet2::load_tx(const std::string &signed_filename, std::vector<tools::wal
return parse_tx_from_str(s, ptx, accept_func);
}
//----------------------------------------------------------------------------------------------------
bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set &)> accept_func)
bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set &)> accept_func, tools::wallet2::signed_tx_set *signed_txs_out /* = nullptr */, bool do_handle_key_images /* = true */)
{
std::string s = signed_tx_st;
signed_tx_set signed_txs;
@ -8073,19 +8073,31 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too
return false;
}
// import key images
bool r = import_key_images(signed_txs.key_images);
if (!r) return false;
// Make signed_tx_set available to caller
if (signed_txs_out)
*signed_txs_out = std::move(signed_txs);
// remember key images for this tx, for when we get those txes from the blockchain
for (const auto &e: signed_txs.tx_key_images)
m_cold_key_images.insert(e);
// `do_handle_key_images = true` was (and is) the default behavior, but for more flexibility in the Wallet API it can be turned off now
if (do_handle_key_images)
{
// import key images
bool r = import_key_images(signed_txs.key_images);
if (!r) return false;
// remember key images for this tx, for when we get those txes from the blockchain
insert_cold_key_images(signed_txs.tx_key_images);
}
ptx = signed_txs.ptx;
return true;
}
//----------------------------------------------------------------------------------------------------
void wallet2::insert_cold_key_images(std::unordered_map<crypto::public_key, crypto::key_image> &cold_key_images)
{
for (const auto &ki: cold_key_images)
m_cold_key_images.insert(ki);
}
//----------------------------------------------------------------------------------------------------
std::string wallet2::save_multisig_tx(multisig_tx_set txs)
{
LOG_PRINT_L0("saving " << txs.m_ptx.size() << " multisig transactions");

View File

@ -1198,7 +1198,8 @@ private:
bool load_unsigned_tx(const std::string &unsigned_filename, unsigned_tx_set &exported_txs) const;
bool parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsigned_tx_set &exported_txs) const;
bool load_tx(const std::string &signed_filename, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set&)> accept_func = NULL);
bool parse_tx_from_str(const std::string &signed_tx_st, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set &)> accept_func);
bool parse_tx_from_str(const std::string &signed_tx_st, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set &)> accept_func, signed_tx_set *signed_tx_set_out = nullptr, bool do_handle_key_images = true);
void insert_cold_key_images(std::unordered_map<crypto::public_key, crypto::key_image> &cold_key_images);
std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const unique_index_container& subtract_fee_from_outputs = {}); // pass subaddr_indices by value on purpose
std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices);
std::vector<wallet2::pending_tx> create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra);