Skip to content

Commit 827de03

Browse files
ryanofskyjnewbery
authored andcommitted
Remove direct bitcoin calls from qt/coincontroldialog.cpp
1 parent a0704a8 commit 827de03

File tree

7 files changed

+140
-70
lines changed

7 files changed

+140
-70
lines changed

src/interface/node.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#include <net_processing.h>
1616
#include <netaddress.h>
1717
#include <netbase.h>
18+
#include <policy/feerate.h>
19+
#include <policy/fees.h>
20+
#include <policy/policy.h>
1821
#include <primitives/block.h>
1922
#include <rpc/server.h>
2023
#include <scheduler.h>
@@ -29,6 +32,7 @@
2932
#include <config/bitcoin-config.h>
3033
#endif
3134
#ifdef ENABLE_WALLET
35+
#include <wallet/fees.h>
3236
#include <wallet/wallet.h>
3337
#define CHECK_WALLET(x) x
3438
#else
@@ -186,7 +190,31 @@ class NodeImpl : public Node
186190
}
187191
bool getNetworkActive() override { return g_connman && g_connman->GetNetworkActive(); }
188192
unsigned int getTxConfirmTarget() override { CHECK_WALLET(return ::nTxConfirmTarget); }
193+
CAmount getRequiredFee(unsigned int tx_bytes) override { CHECK_WALLET(return GetRequiredFee(tx_bytes)); }
194+
CAmount getMinimumFee(unsigned int tx_bytes,
195+
const CCoinControl& coin_control,
196+
int* returned_target,
197+
FeeReason* reason) override
198+
{
199+
FeeCalculation fee_calc;
200+
CAmount result;
201+
CHECK_WALLET(result = GetMinimumFee(tx_bytes, coin_control, ::mempool, ::feeEstimator, &fee_calc));
202+
if (returned_target) *returned_target = fee_calc.returnedTarget;
203+
if (reason) *reason = fee_calc.reason;
204+
return result;
205+
}
189206
CAmount getMaxTxFee() override { return ::maxTxFee; }
207+
CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override
208+
{
209+
FeeCalculation fee_calc;
210+
CFeeRate result = ::feeEstimator.estimateSmartFee(num_blocks, &fee_calc, conservative);
211+
if (returned_target) {
212+
*returned_target = fee_calc.returnedTarget;
213+
}
214+
return result;
215+
}
216+
CFeeRate getDustRelayFee() override { return ::dustRelayFee; }
217+
CFeeRate getPayTxFee() override { CHECK_WALLET(return ::payTxFee); }
190218
UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
191219
{
192220
JSONRPCRequest req;

src/interface/node.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@
1919
#include <tuple>
2020
#include <vector>
2121

22+
class CCoinControl;
23+
class CFeeRate;
2224
class CNodeStats;
2325
class RPCTimerInterface;
2426
class UniValue;
2527
class proxyType;
28+
enum class FeeReason;
2629
struct CNodeStateStats;
2730

2831
namespace interface {
@@ -145,9 +148,27 @@ class Node
145148
//! Get tx confirm target.
146149
virtual unsigned int getTxConfirmTarget() = 0;
147150

151+
//! Get required fee.
152+
virtual CAmount getRequiredFee(unsigned int tx_bytes) = 0;
153+
154+
//! Get minimum fee.
155+
virtual CAmount getMinimumFee(unsigned int tx_bytes,
156+
const CCoinControl& coin_control,
157+
int* returned_target,
158+
FeeReason* reason) = 0;
159+
148160
//! Get max tx fee.
149161
virtual CAmount getMaxTxFee() = 0;
150162

163+
//! Estimate smart fee.
164+
virtual CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) = 0;
165+
166+
//! Get dust relay fee.
167+
virtual CFeeRate getDustRelayFee() = 0;
168+
169+
//! Get pay tx fee.
170+
virtual CFeeRate getPayTxFee() = 0;
171+
151172
//! Execute rpc command.
152173
virtual UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) = 0;
153174

src/interface/wallet.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ class PendingWalletTxImpl : public PendingWalletTx
5454
CReserveKey m_key;
5555
};
5656

57+
//! Construct wallet TxOut struct.
58+
WalletTxOut MakeWalletTxOut(CWallet& wallet, const CWalletTx& wtx, int n, int depth)
59+
{
60+
WalletTxOut result;
61+
result.txout = wtx.tx->vout[n];
62+
result.time = wtx.GetTxTime();
63+
result.depth_in_main_chain = depth;
64+
result.is_spent = wallet.IsSpent(wtx.GetHash(), n);
65+
return result;
66+
}
67+
5768
class WalletImpl : public Wallet
5869
{
5970
public:
@@ -207,6 +218,36 @@ class WalletImpl : public Wallet
207218
{
208219
return m_wallet.GetAvailableBalance(&coin_control);
209220
}
221+
CoinsList listCoins() override
222+
{
223+
LOCK2(::cs_main, m_wallet.cs_wallet);
224+
CoinsList result;
225+
for (const auto& entry : m_wallet.ListCoins()) {
226+
auto& group = result[entry.first];
227+
for (const auto& coin : entry.second) {
228+
group.emplace_back(
229+
COutPoint(coin.tx->GetHash(), coin.i), MakeWalletTxOut(m_wallet, *coin.tx, coin.i, coin.nDepth));
230+
}
231+
}
232+
return result;
233+
}
234+
std::vector<WalletTxOut> getCoins(const std::vector<COutPoint>& outputs) override
235+
{
236+
LOCK2(::cs_main, m_wallet.cs_wallet);
237+
std::vector<WalletTxOut> result;
238+
result.reserve(outputs.size());
239+
for (const auto& output : outputs) {
240+
result.emplace_back();
241+
auto it = m_wallet.mapWallet.find(output.hash);
242+
if (it != m_wallet.mapWallet.end()) {
243+
int depth = it->second.GetDepthInMainChain();
244+
if (depth >= 0) {
245+
result.back() = MakeWalletTxOut(m_wallet, it->second, output.n, depth);
246+
}
247+
}
248+
}
249+
return result;
250+
}
210251
bool hdEnabled() override { return m_wallet.IsHDEnabled(); }
211252
OutputType getDefaultAddressType() override { return m_wallet.m_default_address_type; }
212253
OutputType getDefaultChangeType() override { return m_wallet.m_default_change_type; }

src/interface/wallet.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <memory>
1717
#include <stdint.h>
1818
#include <string>
19+
#include <tuple>
1920
#include <utility>
2021
#include <vector>
2122

@@ -30,6 +31,7 @@ namespace interface {
3031
class Handler;
3132
class PendingWalletTx;
3233
struct WalletBalances;
34+
struct WalletTxOut;
3335

3436
using WalletOrderForm = std::vector<std::pair<std::string, std::string>>;
3537
using WalletValueMap = std::map<std::string, std::string>;
@@ -153,6 +155,14 @@ class Wallet
153155
//! Get available balance.
154156
virtual CAmount getAvailableBalance(const CCoinControl& coin_control) = 0;
155157

158+
//! Return AvailableCoins + LockedCoins grouped by wallet address.
159+
//! (put change in one group with wallet address)
160+
using CoinsList = std::map<CTxDestination, std::vector<std::tuple<COutPoint, WalletTxOut>>>;
161+
virtual CoinsList listCoins() = 0;
162+
163+
//! Return wallet transaction output information.
164+
virtual std::vector<WalletTxOut> getCoins(const std::vector<COutPoint>& outputs) = 0;
165+
156166
// Return whether HD enabled.
157167
virtual bool hdEnabled() = 0;
158168

@@ -226,6 +236,15 @@ struct WalletBalances
226236
}
227237
};
228238

239+
//! Wallet transaction output.
240+
struct WalletTxOut
241+
{
242+
CTxOut txout;
243+
int64_t time;
244+
int depth_in_main_chain = -1;
245+
bool is_spent = false;
246+
};
247+
229248
//! Return implementation of Wallet interface. This function will be undefined
230249
//! in builds where ENABLE_WALLET is false.
231250
std::unique_ptr<Wallet> MakeWallet(CWallet& wallet);

src/qt/coincontroldialog.cpp

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include <qt/walletmodel.h>
1515

1616
#include <wallet/coincontrol.h>
17-
#include <init.h>
17+
#include <interface/node.h>
1818
#include <key_io.h>
1919
#include <policy/fees.h>
2020
#include <policy/policy.h>
@@ -431,7 +431,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
431431
{
432432
CTxOut txout(amount, static_cast<CScript>(std::vector<unsigned char>(24, 0)));
433433
txDummy.vout.push_back(txout);
434-
fDust |= IsDust(txout, ::dustRelayFee);
434+
fDust |= IsDust(txout, model->node().getDustRelayFee());
435435
}
436436
}
437437

@@ -445,16 +445,16 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
445445
bool fWitness = false;
446446

447447
std::vector<COutPoint> vCoinControl;
448-
std::vector<COutput> vOutputs;
449448
coinControl()->ListSelected(vCoinControl);
450-
model->getOutputs(vCoinControl, vOutputs);
451449

452-
for (const COutput& out : vOutputs) {
450+
size_t i = 0;
451+
for (const auto& out : model->wallet().getCoins(vCoinControl)) {
452+
if (out.depth_in_main_chain < 0) continue;
453+
453454
// unselect already spent, very unlikely scenario, this could happen
454455
// when selected are spent elsewhere, like rpc or another computer
455-
uint256 txhash = out.tx->GetHash();
456-
COutPoint outpt(txhash, out.i);
457-
if (model->isSpent(outpt))
456+
const COutPoint& outpt = vCoinControl[i++];
457+
if (out.is_spent)
458458
{
459459
coinControl()->UnSelect(outpt);
460460
continue;
@@ -464,18 +464,18 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
464464
nQuantity++;
465465

466466
// Amount
467-
nAmount += out.tx->tx->vout[out.i].nValue;
467+
nAmount += out.txout.nValue;
468468

469469
// Bytes
470470
CTxDestination address;
471471
int witnessversion = 0;
472472
std::vector<unsigned char> witnessprogram;
473-
if (out.tx->tx->vout[out.i].scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram))
473+
if (out.txout.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram))
474474
{
475475
nBytesInputs += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);
476476
fWitness = true;
477477
}
478-
else if(ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, address))
478+
else if(ExtractDestination(out.txout.scriptPubKey, address))
479479
{
480480
CPubKey pubkey;
481481
CKeyID *keyid = boost::get<CKeyID>(&address);
@@ -509,7 +509,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
509509
nBytes -= 34;
510510

511511
// Fee
512-
nPayFee = GetMinimumFee(nBytes, *coinControl(), ::mempool, ::feeEstimator, nullptr /* FeeCalculation */);
512+
nPayFee = model->node().getMinimumFee(nBytes, *coinControl(), nullptr /* returned_target */, nullptr /* reason */);
513513

514514
if (nPayAmount > 0)
515515
{
@@ -521,7 +521,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
521521
if (nChange > 0 && nChange < MIN_CHANGE)
522522
{
523523
CTxOut txout(nChange, static_cast<CScript>(std::vector<unsigned char>(24, 0)));
524-
if (IsDust(txout, ::dustRelayFee))
524+
if (IsDust(txout, model->node().getDustRelayFee()))
525525
{
526526
nPayFee += nChange;
527527
nChange = 0;
@@ -621,13 +621,10 @@ void CoinControlDialog::updateView()
621621

622622
int nDisplayUnit = model->getOptionsModel()->getDisplayUnit();
623623

624-
std::map<QString, std::vector<COutput> > mapCoins;
625-
model->listCoins(mapCoins);
626-
627-
for (const std::pair<QString, std::vector<COutput>>& coins : mapCoins) {
624+
for (const auto& coins : model->wallet().listCoins()) {
628625
CCoinControlWidgetItem *itemWalletAddress = new CCoinControlWidgetItem();
629626
itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);
630-
QString sWalletAddress = coins.first;
627+
QString sWalletAddress = QString::fromStdString(EncodeDestination(coins.first));
631628
QString sWalletLabel = model->getAddressTableModel()->labelForAddress(sWalletAddress);
632629
if (sWalletLabel.isEmpty())
633630
sWalletLabel = tr("(no label)");
@@ -649,8 +646,10 @@ void CoinControlDialog::updateView()
649646

650647
CAmount nSum = 0;
651648
int nChildren = 0;
652-
for (const COutput& out : coins.second) {
653-
nSum += out.tx->tx->vout[out.i].nValue;
649+
for (const auto& outpair : coins.second) {
650+
const COutPoint& output = std::get<0>(outpair);
651+
const interface::WalletTxOut& out = std::get<1>(outpair);
652+
nSum += out.txout.nValue;
654653
nChildren++;
655654

656655
CCoinControlWidgetItem *itemOutput;
@@ -662,7 +661,7 @@ void CoinControlDialog::updateView()
662661
// address
663662
CTxDestination outputAddress;
664663
QString sAddress = "";
665-
if(ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, outputAddress))
664+
if(ExtractDestination(out.txout.scriptPubKey, outputAddress))
666665
{
667666
sAddress = QString::fromStdString(EncodeDestination(outputAddress));
668667

@@ -687,35 +686,33 @@ void CoinControlDialog::updateView()
687686
}
688687

689688
// amount
690-
itemOutput->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, out.tx->tx->vout[out.i].nValue));
691-
itemOutput->setData(COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)out.tx->tx->vout[out.i].nValue)); // padding so that sorting works correctly
689+
itemOutput->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, out.txout.nValue));
690+
itemOutput->setData(COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)out.txout.nValue)); // padding so that sorting works correctly
692691

693692
// date
694-
itemOutput->setText(COLUMN_DATE, GUIUtil::dateTimeStr(out.tx->GetTxTime()));
695-
itemOutput->setData(COLUMN_DATE, Qt::UserRole, QVariant((qlonglong)out.tx->GetTxTime()));
693+
itemOutput->setText(COLUMN_DATE, GUIUtil::dateTimeStr(out.time));
694+
itemOutput->setData(COLUMN_DATE, Qt::UserRole, QVariant((qlonglong)out.time));
696695

697696
// confirmations
698-
itemOutput->setText(COLUMN_CONFIRMATIONS, QString::number(out.nDepth));
699-
itemOutput->setData(COLUMN_CONFIRMATIONS, Qt::UserRole, QVariant((qlonglong)out.nDepth));
697+
itemOutput->setText(COLUMN_CONFIRMATIONS, QString::number(out.depth_in_main_chain));
698+
itemOutput->setData(COLUMN_CONFIRMATIONS, Qt::UserRole, QVariant((qlonglong)out.depth_in_main_chain));
700699

701700
// transaction hash
702-
uint256 txhash = out.tx->GetHash();
703-
itemOutput->setText(COLUMN_TXHASH, QString::fromStdString(txhash.GetHex()));
701+
itemOutput->setText(COLUMN_TXHASH, QString::fromStdString(output.hash.GetHex()));
704702

705703
// vout index
706-
itemOutput->setText(COLUMN_VOUT_INDEX, QString::number(out.i));
704+
itemOutput->setText(COLUMN_VOUT_INDEX, QString::number(output.n));
707705

708706
// disable locked coins
709-
if (model->wallet().isLockedCoin(COutPoint(txhash, out.i)))
707+
if (model->wallet().isLockedCoin(output))
710708
{
711-
COutPoint outpt(txhash, out.i);
712-
coinControl()->UnSelect(outpt); // just to be sure
709+
coinControl()->UnSelect(output); // just to be sure
713710
itemOutput->setDisabled(true);
714711
itemOutput->setIcon(COLUMN_CHECKBOX, platformStyle->SingleColorIcon(":/icons/lock_closed"));
715712
}
716713

717714
// set checkbox
718-
if (coinControl()->IsSelected(COutPoint(txhash, out.i)))
715+
if (coinControl()->IsSelected(output))
719716
itemOutput->setCheckState(COLUMN_CHECKBOX, Qt::Checked);
720717
}
721718

src/qt/walletmodel.cpp

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -475,38 +475,6 @@ void WalletModel::UnlockContext::CopyFrom(const UnlockContext& rhs)
475475
rhs.relock = false;
476476
}
477477

478-
// returns a list of COutputs from COutPoints
479-
void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs)
480-
{
481-
LOCK2(cs_main, cwallet->cs_wallet);
482-
for (const COutPoint& outpoint : vOutpoints)
483-
{
484-
auto it = cwallet->mapWallet.find(outpoint.hash);
485-
if (it == cwallet->mapWallet.end()) continue;
486-
int nDepth = it->second.GetDepthInMainChain();
487-
if (nDepth < 0) continue;
488-
COutput out(&it->second, outpoint.n, nDepth, true /* spendable */, true /* solvable */, true /* safe */);
489-
vOutputs.push_back(out);
490-
}
491-
}
492-
493-
bool WalletModel::isSpent(const COutPoint& outpoint) const
494-
{
495-
LOCK2(cs_main, cwallet->cs_wallet);
496-
return cwallet->IsSpent(outpoint.hash, outpoint.n);
497-
}
498-
499-
// AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address)
500-
void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const
501-
{
502-
for (auto& group : cwallet->ListCoins()) {
503-
auto& resultGroup = mapCoins[QString::fromStdString(EncodeDestination(group.first))];
504-
for (auto& coin : group.second) {
505-
resultGroup.emplace_back(std::move(coin));
506-
}
507-
}
508-
}
509-
510478
void WalletModel::loadReceiveRequests(std::vector<std::string>& vReceiveRequests)
511479
{
512480
vReceiveRequests = m_wallet->getDestValues("rr"); // receive request

0 commit comments

Comments
 (0)