Changeset View
Changeset View
Standalone View
Standalone View
src/interfaces/wallet.cpp
Show First 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | public: | ||||
} | } | ||||
CTransactionRef m_tx; | CTransactionRef m_tx; | ||||
CWallet &m_wallet; | CWallet &m_wallet; | ||||
CReserveKey m_key; | CReserveKey m_key; | ||||
}; | }; | ||||
//! Construct wallet tx struct. | //! Construct wallet tx struct. | ||||
static WalletTx MakeWalletTx(CWallet &wallet, const CWalletTx &wtx) | static WalletTx MakeWalletTx(interfaces::Chain::Lock &locked_chain, | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | CWallet &wallet, const CWalletTx &wtx) { | ||||
WalletTx result; | WalletTx result; | ||||
result.tx = wtx.tx; | result.tx = wtx.tx; | ||||
result.txin_is_mine.reserve(wtx.tx->vin.size()); | result.txin_is_mine.reserve(wtx.tx->vin.size()); | ||||
for (const auto &txin : wtx.tx->vin) { | for (const auto &txin : wtx.tx->vin) { | ||||
result.txin_is_mine.emplace_back(wallet.IsMine(txin)); | result.txin_is_mine.emplace_back(wallet.IsMine(txin)); | ||||
} | } | ||||
result.txout_is_mine.reserve(wtx.tx->vout.size()); | result.txout_is_mine.reserve(wtx.tx->vout.size()); | ||||
result.txout_address.reserve(wtx.tx->vout.size()); | result.txout_address.reserve(wtx.tx->vout.size()); | ||||
result.txout_address_is_mine.reserve(wtx.tx->vout.size()); | result.txout_address_is_mine.reserve(wtx.tx->vout.size()); | ||||
for (const auto &txout : wtx.tx->vout) { | for (const auto &txout : wtx.tx->vout) { | ||||
result.txout_is_mine.emplace_back(wallet.IsMine(txout)); | result.txout_is_mine.emplace_back(wallet.IsMine(txout)); | ||||
result.txout_address.emplace_back(); | result.txout_address.emplace_back(); | ||||
result.txout_address_is_mine.emplace_back( | result.txout_address_is_mine.emplace_back( | ||||
ExtractDestination(txout.scriptPubKey, | ExtractDestination(txout.scriptPubKey, | ||||
result.txout_address.back()) | result.txout_address.back()) | ||||
? IsMine(wallet, result.txout_address.back()) | ? IsMine(wallet, result.txout_address.back()) | ||||
: ISMINE_NO); | : ISMINE_NO); | ||||
} | } | ||||
result.credit = wtx.GetCredit(ISMINE_ALL); | result.credit = wtx.GetCredit(locked_chain, ISMINE_ALL); | ||||
result.debit = wtx.GetDebit(ISMINE_ALL); | result.debit = wtx.GetDebit(ISMINE_ALL); | ||||
result.change = wtx.GetChange(); | result.change = wtx.GetChange(); | ||||
result.time = wtx.GetTxTime(); | result.time = wtx.GetTxTime(); | ||||
result.value_map = wtx.mapValue; | result.value_map = wtx.mapValue; | ||||
result.is_coinbase = wtx.IsCoinBase(); | result.is_coinbase = wtx.IsCoinBase(); | ||||
return result; | return result; | ||||
} | } | ||||
//! Construct wallet tx status struct. | //! Construct wallet tx status struct. | ||||
static WalletTxStatus MakeWalletTxStatus(const CWalletTx &wtx) | static WalletTxStatus | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | MakeWalletTxStatus(interfaces::Chain::Lock &locked_chain, | ||||
const CWalletTx &wtx) { | |||||
// Temporary, for CheckFinalTx below. Removed in upcoming commit. | |||||
LockAnnotation lock(::cs_main); | |||||
WalletTxStatus result; | WalletTxStatus result; | ||||
CBlockIndex *block = LookupBlockIndex(wtx.hashBlock); | CBlockIndex *block = LookupBlockIndex(wtx.hashBlock); | ||||
result.block_height = | result.block_height = | ||||
(block ? block->nHeight : std::numeric_limits<int>::max()); | (block ? block->nHeight : std::numeric_limits<int>::max()); | ||||
result.blocks_to_maturity = wtx.GetBlocksToMaturity(); | result.blocks_to_maturity = wtx.GetBlocksToMaturity(locked_chain); | ||||
result.depth_in_main_chain = wtx.GetDepthInMainChain(); | result.depth_in_main_chain = wtx.GetDepthInMainChain(locked_chain); | ||||
result.time_received = wtx.nTimeReceived; | result.time_received = wtx.nTimeReceived; | ||||
result.lock_time = wtx.tx->nLockTime; | result.lock_time = wtx.tx->nLockTime; | ||||
result.is_final = CheckFinalTx(*wtx.tx); | result.is_final = CheckFinalTx(*wtx.tx); | ||||
result.is_trusted = wtx.IsTrusted(); | result.is_trusted = wtx.IsTrusted(locked_chain); | ||||
result.is_abandoned = wtx.isAbandoned(); | result.is_abandoned = wtx.isAbandoned(); | ||||
result.is_coinbase = wtx.IsCoinBase(); | result.is_coinbase = wtx.IsCoinBase(); | ||||
result.is_in_main_chain = wtx.IsInMainChain(); | result.is_in_main_chain = wtx.IsInMainChain(locked_chain); | ||||
return result; | return result; | ||||
} | } | ||||
//! Construct wallet TxOut struct. | //! Construct wallet TxOut struct. | ||||
static WalletTxOut MakeWalletTxOut(CWallet &wallet, const CWalletTx &wtx, | static WalletTxOut MakeWalletTxOut(interfaces::Chain::Lock &locked_chain, | ||||
CWallet &wallet, const CWalletTx &wtx, | |||||
int n, int depth) | int n, int depth) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main, wallet.cs_wallet) { | EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) { | ||||
WalletTxOut result; | WalletTxOut result; | ||||
result.txout = wtx.tx->vout[n]; | result.txout = wtx.tx->vout[n]; | ||||
result.time = wtx.GetTxTime(); | result.time = wtx.GetTxTime(); | ||||
result.depth_in_main_chain = depth; | result.depth_in_main_chain = depth; | ||||
result.is_spent = wallet.IsSpent(COutPoint(wtx.GetId(), n)); | result.is_spent = | ||||
wallet.IsSpent(locked_chain, COutPoint(wtx.GetId(), n)); | |||||
return result; | return result; | ||||
} | } | ||||
class WalletImpl : public Wallet { | class WalletImpl : public Wallet { | ||||
public: | public: | ||||
WalletImpl(const std::shared_ptr<CWallet> &wallet) | WalletImpl(const std::shared_ptr<CWallet> &wallet) | ||||
: m_shared_wallet(wallet), m_wallet(*wallet.get()) {} | : m_shared_wallet(wallet), m_wallet(*wallet.get()) {} | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | public: | ||||
std::unique_ptr<PendingWalletTx> | std::unique_ptr<PendingWalletTx> | ||||
createTransaction(const std::vector<CRecipient> &recipients, | createTransaction(const std::vector<CRecipient> &recipients, | ||||
const CCoinControl &coin_control, bool sign, | const CCoinControl &coin_control, bool sign, | ||||
int &change_pos, Amount &fee, | int &change_pos, Amount &fee, | ||||
std::string &fail_reason) override { | std::string &fail_reason) override { | ||||
auto locked_chain = m_wallet.chain().lock(); | auto locked_chain = m_wallet.chain().lock(); | ||||
LOCK(m_wallet.cs_wallet); | LOCK(m_wallet.cs_wallet); | ||||
auto pending = std::make_unique<PendingWalletTxImpl>(m_wallet); | auto pending = std::make_unique<PendingWalletTxImpl>(m_wallet); | ||||
if (!m_wallet.CreateTransaction(recipients, pending->m_tx, | if (!m_wallet.CreateTransaction( | ||||
pending->m_key, fee, change_pos, | *locked_chain, recipients, pending->m_tx, pending->m_key, | ||||
fail_reason, coin_control, sign)) { | fee, change_pos, fail_reason, coin_control, sign)) { | ||||
return {}; | return {}; | ||||
} | } | ||||
return pending; | return pending; | ||||
} | } | ||||
bool transactionCanBeAbandoned(const TxId &txid) override { | bool transactionCanBeAbandoned(const TxId &txid) override { | ||||
return m_wallet.TransactionCanBeAbandoned(txid); | return m_wallet.TransactionCanBeAbandoned(txid); | ||||
} | } | ||||
bool abandonTransaction(const TxId &txid) override { | bool abandonTransaction(const TxId &txid) override { | ||||
auto locked_chain = m_wallet.chain().lock(); | auto locked_chain = m_wallet.chain().lock(); | ||||
LOCK(m_wallet.cs_wallet); | LOCK(m_wallet.cs_wallet); | ||||
return m_wallet.AbandonTransaction(txid); | return m_wallet.AbandonTransaction(*locked_chain, txid); | ||||
} | } | ||||
CTransactionRef getTx(const TxId &txid) override { | CTransactionRef getTx(const TxId &txid) override { | ||||
auto locked_chain = m_wallet.chain().lock(); | auto locked_chain = m_wallet.chain().lock(); | ||||
LOCK(m_wallet.cs_wallet); | LOCK(m_wallet.cs_wallet); | ||||
auto mi = m_wallet.mapWallet.find(txid); | auto mi = m_wallet.mapWallet.find(txid); | ||||
if (mi != m_wallet.mapWallet.end()) { | if (mi != m_wallet.mapWallet.end()) { | ||||
return mi->second.tx; | return mi->second.tx; | ||||
} | } | ||||
return {}; | return {}; | ||||
} | } | ||||
WalletTx getWalletTx(const TxId &txid) override { | WalletTx getWalletTx(const TxId &txid) override { | ||||
auto locked_chain = m_wallet.chain().lock(); | auto locked_chain = m_wallet.chain().lock(); | ||||
LOCK(m_wallet.cs_wallet); | LOCK(m_wallet.cs_wallet); | ||||
auto mi = m_wallet.mapWallet.find(txid); | auto mi = m_wallet.mapWallet.find(txid); | ||||
if (mi != m_wallet.mapWallet.end()) { | if (mi != m_wallet.mapWallet.end()) { | ||||
return MakeWalletTx(m_wallet, mi->second); | return MakeWalletTx(*locked_chain, m_wallet, mi->second); | ||||
} | } | ||||
return {}; | return {}; | ||||
} | } | ||||
std::vector<WalletTx> getWalletTxs() override { | std::vector<WalletTx> getWalletTxs() override { | ||||
auto locked_chain = m_wallet.chain().lock(); | auto locked_chain = m_wallet.chain().lock(); | ||||
LOCK(m_wallet.cs_wallet); | LOCK(m_wallet.cs_wallet); | ||||
std::vector<WalletTx> result; | std::vector<WalletTx> result; | ||||
result.reserve(m_wallet.mapWallet.size()); | result.reserve(m_wallet.mapWallet.size()); | ||||
for (const auto &entry : m_wallet.mapWallet) { | for (const auto &entry : m_wallet.mapWallet) { | ||||
result.emplace_back(MakeWalletTx(m_wallet, entry.second)); | result.emplace_back( | ||||
MakeWalletTx(*locked_chain, m_wallet, entry.second)); | |||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
bool tryGetTxStatus(const TxId &txid, | bool tryGetTxStatus(const TxId &txid, | ||||
interfaces::WalletTxStatus &tx_status, | interfaces::WalletTxStatus &tx_status, | ||||
int &num_blocks, int64_t &block_time) override { | int &num_blocks, int64_t &block_time) override { | ||||
auto locked_chain = m_wallet.chain().lock(true /* try_lock */); | auto locked_chain = m_wallet.chain().lock(true /* try_lock */); | ||||
if (!locked_chain) { | if (!locked_chain) { | ||||
return false; | return false; | ||||
} | } | ||||
TRY_LOCK(m_wallet.cs_wallet, locked_wallet); | TRY_LOCK(m_wallet.cs_wallet, locked_wallet); | ||||
if (!locked_wallet) { | if (!locked_wallet) { | ||||
return false; | return false; | ||||
} | } | ||||
auto mi = m_wallet.mapWallet.find(txid); | auto mi = m_wallet.mapWallet.find(txid); | ||||
if (mi == m_wallet.mapWallet.end()) { | if (mi == m_wallet.mapWallet.end()) { | ||||
return false; | return false; | ||||
} | } | ||||
num_blocks = ::chainActive.Height(); | num_blocks = ::chainActive.Height(); | ||||
block_time = ::chainActive.Tip()->GetBlockTime(); | block_time = ::chainActive.Tip()->GetBlockTime(); | ||||
tx_status = MakeWalletTxStatus(mi->second); | tx_status = MakeWalletTxStatus(*locked_chain, mi->second); | ||||
return true; | return true; | ||||
} | } | ||||
WalletTx getWalletTxDetails(const TxId &txid, WalletTxStatus &tx_status, | WalletTx getWalletTxDetails(const TxId &txid, WalletTxStatus &tx_status, | ||||
WalletOrderForm &order_form, | WalletOrderForm &order_form, | ||||
bool &in_mempool, | bool &in_mempool, | ||||
int &num_blocks) override { | int &num_blocks) override { | ||||
auto locked_chain = m_wallet.chain().lock(); | auto locked_chain = m_wallet.chain().lock(); | ||||
LOCK(m_wallet.cs_wallet); | LOCK(m_wallet.cs_wallet); | ||||
auto mi = m_wallet.mapWallet.find(txid); | auto mi = m_wallet.mapWallet.find(txid); | ||||
if (mi != m_wallet.mapWallet.end()) { | if (mi != m_wallet.mapWallet.end()) { | ||||
num_blocks = ::chainActive.Height(); | num_blocks = ::chainActive.Height(); | ||||
in_mempool = mi->second.InMempool(); | in_mempool = mi->second.InMempool(); | ||||
order_form = mi->second.vOrderForm; | order_form = mi->second.vOrderForm; | ||||
tx_status = MakeWalletTxStatus(mi->second); | tx_status = MakeWalletTxStatus(*locked_chain, mi->second); | ||||
return MakeWalletTx(m_wallet, mi->second); | return MakeWalletTx(*locked_chain, m_wallet, mi->second); | ||||
} | } | ||||
return {}; | return {}; | ||||
} | } | ||||
WalletBalances getBalances() override { | WalletBalances getBalances() override { | ||||
WalletBalances result; | WalletBalances result; | ||||
result.balance = m_wallet.GetBalance(); | result.balance = m_wallet.GetBalance(); | ||||
result.unconfirmed_balance = m_wallet.GetUnconfirmedBalance(); | result.unconfirmed_balance = m_wallet.GetUnconfirmedBalance(); | ||||
result.immature_balance = m_wallet.GetImmatureBalance(); | result.immature_balance = m_wallet.GetImmatureBalance(); | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | public: | ||||
auto locked_chain = m_wallet.chain().lock(); | auto locked_chain = m_wallet.chain().lock(); | ||||
LOCK(m_wallet.cs_wallet); | LOCK(m_wallet.cs_wallet); | ||||
return m_wallet.GetCredit(txout, filter); | return m_wallet.GetCredit(txout, filter); | ||||
} | } | ||||
CoinsList listCoins() override { | CoinsList listCoins() override { | ||||
auto locked_chain = m_wallet.chain().lock(); | auto locked_chain = m_wallet.chain().lock(); | ||||
LOCK(m_wallet.cs_wallet); | LOCK(m_wallet.cs_wallet); | ||||
CoinsList result; | CoinsList result; | ||||
for (const auto &entry : m_wallet.ListCoins()) { | for (const auto &entry : m_wallet.ListCoins(*locked_chain)) { | ||||
auto &group = result[entry.first]; | auto &group = result[entry.first]; | ||||
for (const auto &coin : entry.second) { | for (const auto &coin : entry.second) { | ||||
group.emplace_back(COutPoint(coin.tx->GetId(), coin.i), | group.emplace_back(COutPoint(coin.tx->GetId(), coin.i), | ||||
MakeWalletTxOut(m_wallet, *coin.tx, | MakeWalletTxOut(*locked_chain, m_wallet, | ||||
coin.i, coin.nDepth)); | *coin.tx, coin.i, | ||||
coin.nDepth)); | |||||
} | } | ||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
std::vector<WalletTxOut> | std::vector<WalletTxOut> | ||||
getCoins(const std::vector<COutPoint> &outputs) override { | getCoins(const std::vector<COutPoint> &outputs) override { | ||||
auto locked_chain = m_wallet.chain().lock(); | auto locked_chain = m_wallet.chain().lock(); | ||||
LOCK(m_wallet.cs_wallet); | LOCK(m_wallet.cs_wallet); | ||||
std::vector<WalletTxOut> result; | std::vector<WalletTxOut> result; | ||||
result.reserve(outputs.size()); | result.reserve(outputs.size()); | ||||
for (const auto &output : outputs) { | for (const auto &output : outputs) { | ||||
result.emplace_back(); | result.emplace_back(); | ||||
auto it = m_wallet.mapWallet.find(output.GetTxId()); | auto it = m_wallet.mapWallet.find(output.GetTxId()); | ||||
if (it != m_wallet.mapWallet.end()) { | if (it != m_wallet.mapWallet.end()) { | ||||
int depth = it->second.GetDepthInMainChain(); | int depth = it->second.GetDepthInMainChain(*locked_chain); | ||||
if (depth >= 0) { | if (depth >= 0) { | ||||
result.back() = MakeWalletTxOut(m_wallet, it->second, | result.back() = | ||||
MakeWalletTxOut(*locked_chain, m_wallet, it->second, | |||||
output.GetN(), depth); | output.GetN(), depth); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
bool hdEnabled() override { return m_wallet.IsHDEnabled(); } | bool hdEnabled() override { return m_wallet.IsHDEnabled(); } | ||||
OutputType getDefaultAddressType() override { | OutputType getDefaultAddressType() override { | ||||
return m_wallet.m_default_address_type; | return m_wallet.m_default_address_type; | ||||
▲ Show 20 Lines • Show All 80 Lines • Show Last 20 Lines |