Skip to content

Commit 7d839eb

Browse files
committed
wallet: CInputCoin store weight
1 parent 2715817 commit 7d839eb

File tree

4 files changed

+32
-26
lines changed

4 files changed

+32
-26
lines changed

src/wallet/coinselection.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ class CInputCoin {
3232
effective_value = txout.nValue;
3333
}
3434

35-
CInputCoin(const CTransactionRef& tx, unsigned int i, int input_bytes) : CInputCoin(tx, i)
35+
CInputCoin(const CTransactionRef& tx, unsigned int i, int input_bytes, int input_weight) : CInputCoin(tx, i)
3636
{
3737
m_input_bytes = input_bytes;
38+
m_input_weight = input_weight;
3839
}
3940

4041
CInputCoin(const COutPoint& outpoint_in, const CTxOut& txout_in)
@@ -44,9 +45,10 @@ class CInputCoin {
4445
effective_value = txout.nValue;
4546
}
4647

47-
CInputCoin(const COutPoint& outpoint_in, const CTxOut& txout_in, int input_bytes) : CInputCoin(outpoint_in, txout_in)
48+
CInputCoin(const COutPoint& outpoint_in, const CTxOut& txout_in, int input_bytes, int input_weight) : CInputCoin(outpoint_in, txout_in)
4849
{
4950
m_input_bytes = input_bytes;
51+
m_input_weight = input_weight;
5052
}
5153

5254
COutPoint outpoint;
@@ -57,6 +59,7 @@ class CInputCoin {
5759

5860
/** Pre-computed estimated size of this output as a fully-signed input in a transaction. Can be -1 if it could not be calculated */
5961
int m_input_bytes{-1};
62+
int m_input_weight{-1};
6063

6164
bool operator<(const CInputCoin& rhs) const {
6265
return outpoint < rhs.outpoint;

src/wallet/spend.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ using interfaces::FoundBlock;
2323

2424
static constexpr size_t OUTPUT_GROUP_MAX_ENTRIES{100};
2525

26-
int GetTxSpendSize(const CWallet& wallet, const CWalletTx& wtx, unsigned int out, const CCoinControl* coin_control)
26+
TxSize GetTxSpendSize(const CWallet& wallet, const CWalletTx& wtx, unsigned int out, const CCoinControl* coin_control)
2727
{
2828
return CalculateMaximumSignedInputSize(wtx.tx->vout[out], &wallet, coin_control);
2929
}
@@ -33,17 +33,19 @@ std::string COutput::ToString() const
3333
return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->tx->vout[i].nValue));
3434
}
3535

36-
int CalculateMaximumSignedInputSize(const CTxOut& txout, const COutPoint outpoint, const SigningProvider* provider, const CCoinControl* coin_control)
36+
TxSize CalculateMaximumSignedInputSize(const CTxOut& txout, const COutPoint outpoint, const SigningProvider* provider, const CCoinControl* coin_control)
3737
{
3838
CMutableTransaction txn;
3939
txn.vin.push_back(CTxIn(outpoint));
4040
if (!provider || !DummySignInput(*provider, txn.vin[0], txout, coin_control)) {
41-
return -1;
41+
return {-1, -1};
4242
}
43-
return GetVirtualTransactionInputSize(txn.vin[0]);
43+
int64_t vsize = GetVirtualTransactionInputSize(txn.vin[0]);
44+
int64_t weight = GetTransactionInputWeight(txn.vin[0]);
45+
return TxSize{vsize, weight};
4446
}
4547

46-
int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet, const CCoinControl* coin_control)
48+
TxSize CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet, const CCoinControl* coin_control)
4749
{
4850
const std::unique_ptr<SigningProvider> provider = wallet->GetSolvingProvider(txout.scriptPubKey);
4951
return CalculateMaximumSignedInputSize(txout, COutPoint(), provider.get(), coin_control);
@@ -446,7 +448,7 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
446448
std::vector<COutPoint> vPresetInputs;
447449
coin_control.ListSelected(vPresetInputs);
448450
for (const COutPoint& outpoint : vPresetInputs) {
449-
int input_bytes = -1;
451+
TxSize input_size{-1, -1};
450452
CTxOut txout;
451453
std::map<uint256, CWalletTx>::const_iterator it = wallet.mapWallet.find(outpoint.hash);
452454
if (it != wallet.mapWallet.end()) {
@@ -455,19 +457,19 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
455457
if (wtx.tx->vout.size() <= outpoint.n) {
456458
return std::nullopt;
457459
}
458-
input_bytes = GetTxSpendSize(wallet, wtx, outpoint.n, &coin_control);
460+
input_size = GetTxSpendSize(wallet, wtx, outpoint.n, &coin_control);
459461
txout = wtx.tx->vout.at(outpoint.n);
460462
}
461-
if (input_bytes == -1) {
463+
if (input_size.vsize == -1) {
462464
// The input is external. We either did not find the tx in mapWallet, or we did but couldn't compute the input size with wallet data
463465
if (!coin_control.GetExternalOutput(outpoint, txout)) {
464466
// Not ours, and we don't have solving data.
465467
return std::nullopt;
466468
}
467-
input_bytes = CalculateMaximumSignedInputSize(txout, outpoint, &coin_control.m_external_provider, &coin_control);
469+
input_size = CalculateMaximumSignedInputSize(txout, outpoint, &coin_control.m_external_provider, &coin_control);
468470
}
469471

470-
CInputCoin coin(outpoint, txout, input_bytes);
472+
CInputCoin coin(outpoint, txout, input_size.vsize, input_size.weight);
471473
if (coin.m_input_bytes == -1) {
472474
return std::nullopt; // Not solvable, can't estimate size for fee
473475
}
@@ -700,7 +702,7 @@ static bool CreateTransactionInternal(
700702
coin_selection_params.change_output_size = GetSerializeSize(change_prototype_txout);
701703

702704
// Get size of spending the change output
703-
int change_spend_size = CalculateMaximumSignedInputSize(change_prototype_txout, &wallet);
705+
int change_spend_size = CalculateMaximumSignedInputSize(change_prototype_txout, &wallet).vsize;
704706
// If the wallet doesn't know how to sign change output, assume p2sh-p2wpkh
705707
// as lower-bound to allow BnB to do it's thing
706708
if (change_spend_size == -1) {

src/wallet/spend.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,13 @@
1010
#include <wallet/transaction.h>
1111
#include <wallet/wallet.h>
1212

13+
struct TxSize {
14+
int64_t vsize{-1};
15+
int64_t weight{-1};
16+
};
17+
1318
/** Get the marginal bytes if spending the specified output from this transaction */
14-
int GetTxSpendSize(const CWallet& wallet, const CWalletTx& wtx, unsigned int out, const CCoinControl* coin_control = nullptr);
19+
TxSize GetTxSpendSize(const CWallet& wallet, const CWalletTx& wtx, unsigned int out, const CCoinControl* coin_control = nullptr);
1520

1621
class COutput
1722
{
@@ -29,7 +34,7 @@ class COutput
2934
int nDepth;
3035

3136
/** Pre-computed estimated size of this output as a fully-signed input in a transaction. Can be -1 if it could not be calculated */
32-
int nInputBytes;
37+
TxSize nInputSize;
3338

3439
/** Whether we have the private keys to spend this output */
3540
bool fSpendable;
@@ -46,30 +51,26 @@ class COutput
4651

4752
COutput(const CWallet& wallet, const CWalletTx& wtx, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn, bool fSafeIn, const CCoinControl* coin_control = nullptr)
4853
{
49-
tx = &wtx; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn; fSafe = fSafeIn; nInputBytes = -1;
54+
tx = &wtx; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn; fSafe = fSafeIn; nInputSize = {-1, -1};
5055
// If known and signable by the given wallet, compute nInputSize
5156
// Failure will keep this value -1
5257
if (fSpendable) {
53-
nInputBytes = GetTxSpendSize(wallet, wtx, i, coin_control);
58+
nInputSize = GetTxSpendSize(wallet, wtx, i, coin_control);
5459
}
5560
}
5661

5762
std::string ToString() const;
5863

5964
inline CInputCoin GetInputCoin() const
6065
{
61-
return CInputCoin(tx->tx, i, nInputBytes);
66+
return CInputCoin(tx->tx, i, nInputSize.vsize, nInputSize.weight);
6267
}
6368
};
6469

6570
//Get the marginal bytes of spending the specified output
66-
struct TxSize {
67-
int64_t vsize{-1};
68-
int64_t weight{-1};
69-
};
71+
TxSize CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet, const CCoinControl* coin_control = nullptr);
72+
TxSize CalculateMaximumSignedInputSize(const CTxOut& txout, const COutPoint outpoint, const SigningProvider* pwallet, const CCoinControl* coin_control = nullptr);
7073

71-
int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet, const CCoinControl* coin_control = nullptr);
72-
int CalculateMaximumSignedInputSize(const CTxOut& txout, const COutPoint outpoint, const SigningProvider* pwallet, const CCoinControl* coin_control = nullptr);
7374
/** Calculate the size of the transaction assuming all signatures are max size
7475
* Use DummySignatureCreator, which inserts 71 byte signatures everywhere.
7576
* NOTE: this requires that all inputs must be in mapWallet (eg the tx should

src/wallet/test/coinselector_tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,13 +314,13 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
314314
std::vector<COutput> coins;
315315

316316
add_coin(coins, *wallet, 1);
317-
coins.at(0).nInputBytes = 40; // Make sure that it has a negative effective value. The next check should assert if this somehow got through. Otherwise it will fail
317+
coins.at(0).nInputSize.vsize = 40; // Make sure that it has a negative effective value. The next check should assert if this somehow got through. Otherwise it will fail
318318
BOOST_CHECK(!SelectCoinsBnB(GroupCoins(coins), 1 * CENT, coin_selection_params_bnb.m_cost_of_change));
319319

320320
// Test fees subtracted from output:
321321
coins.clear();
322322
add_coin(coins, *wallet, 1 * CENT);
323-
coins.at(0).nInputBytes = 40;
323+
coins.at(0).nInputSize.vsize = 40;
324324
coin_selection_params_bnb.m_subtract_fee_outputs = true;
325325
const auto result9 = SelectCoinsBnB(GroupCoins(coins), 1 * CENT, coin_selection_params_bnb.m_cost_of_change);
326326
BOOST_CHECK(result9);

0 commit comments

Comments
 (0)