BSHA3  0.17.99
P2P Blockchain, based on Bitcoin
feebumper.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2018 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <consensus/validation.h>
6 #include <wallet/coincontrol.h>
7 #include <wallet/feebumper.h>
8 #include <wallet/fees.h>
9 #include <wallet/wallet.h>
10 #include <policy/fees.h>
11 #include <policy/policy.h>
12 #include <policy/rbf.h>
13 #include <validation.h> //for mempool access
14 #include <txmempool.h>
15 #include <utilmoneystr.h>
16 #include <util.h>
17 #include <net.h>
18 
21 static feebumper::Result PreconditionChecks(const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(cs_main, wallet->cs_wallet)
22 {
23  if (wallet->HasWalletSpend(wtx.GetHash())) {
24  errors.push_back("Transaction has descendants in the wallet");
26  }
27 
28  {
29  LOCK(mempool.cs);
30  auto it_mp = mempool.mapTx.find(wtx.GetHash());
31  if (it_mp != mempool.mapTx.end() && it_mp->GetCountWithDescendants() > 1) {
32  errors.push_back("Transaction has descendants in the mempool");
34  }
35  }
36 
37  if (wtx.GetDepthInMainChain() != 0) {
38  errors.push_back("Transaction has been mined, or is conflicted with a mined transaction");
40  }
41 
42  if (!SignalsOptInRBF(*wtx.tx)) {
43  errors.push_back("Transaction is not BIP 125 replaceable");
45  }
46 
47  if (wtx.mapValue.count("replaced_by_txid")) {
48  errors.push_back(strprintf("Cannot bump transaction %s which was already bumped by transaction %s", wtx.GetHash().ToString(), wtx.mapValue.at("replaced_by_txid")));
50  }
51 
52  // check that original tx consists entirely of our inputs
53  // if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee)
54  if (!wallet->IsAllFromMe(*wtx.tx, ISMINE_SPENDABLE)) {
55  errors.push_back("Transaction contains inputs that don't belong to this wallet");
57  }
58 
59 
60  return feebumper::Result::OK;
61 }
62 
63 namespace feebumper {
64 
65 bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid)
66 {
67  LOCK2(cs_main, wallet->cs_wallet);
68  const CWalletTx* wtx = wallet->GetWalletTx(txid);
69  if (wtx == nullptr) return false;
70 
71  std::vector<std::string> errors_dummy;
72  feebumper::Result res = PreconditionChecks(wallet, *wtx, errors_dummy);
73  return res == feebumper::Result::OK;
74 }
75 
76 Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, CAmount total_fee, std::vector<std::string>& errors,
77  CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx)
78 {
79  LOCK2(cs_main, wallet->cs_wallet);
80  errors.clear();
81  auto it = wallet->mapWallet.find(txid);
82  if (it == wallet->mapWallet.end()) {
83  errors.push_back("Invalid or non-wallet transaction id");
85  }
86  const CWalletTx& wtx = it->second;
87 
88  Result result = PreconditionChecks(wallet, wtx, errors);
89  if (result != Result::OK) {
90  return result;
91  }
92 
93  // figure out which output was change
94  // if there was no change output or multiple change outputs, fail
95  int nOutput = -1;
96  for (size_t i = 0; i < wtx.tx->vout.size(); ++i) {
97  if (wallet->IsChange(wtx.tx->vout[i])) {
98  if (nOutput != -1) {
99  errors.push_back("Transaction has multiple change outputs");
100  return Result::WALLET_ERROR;
101  }
102  nOutput = i;
103  }
104  }
105  if (nOutput == -1) {
106  errors.push_back("Transaction does not have a change output");
107  return Result::WALLET_ERROR;
108  }
109 
110  // Calculate the expected size of the new transaction.
111  int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
112  const int64_t maxNewTxSize = CalculateMaximumSignedTxSize(*wtx.tx, wallet);
113  if (maxNewTxSize < 0) {
114  errors.push_back("Transaction contains inputs that cannot be signed");
116  }
117 
118  // calculate the old fee and fee-rate
119  old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut();
120  CFeeRate nOldFeeRate(old_fee, txSize);
121  CFeeRate nNewFeeRate;
122  // The wallet uses a conservative WALLET_INCREMENTAL_RELAY_FEE value to
123  // future proof against changes to network wide policy for incremental relay
124  // fee that our node may not be aware of.
125  CFeeRate walletIncrementalRelayFee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE);
126  if (::incrementalRelayFee > walletIncrementalRelayFee) {
127  walletIncrementalRelayFee = ::incrementalRelayFee;
128  }
129 
130  if (total_fee > 0) {
131  CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + ::incrementalRelayFee.GetFee(maxNewTxSize);
132  if (total_fee < minTotalFee) {
133  errors.push_back(strprintf("Insufficient totalFee, must be at least %s (oldFee %s + incrementalFee %s)",
134  FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxNewTxSize)), FormatMoney(::incrementalRelayFee.GetFee(maxNewTxSize))));
136  }
137  CAmount requiredFee = GetRequiredFee(*wallet, maxNewTxSize);
138  if (total_fee < requiredFee) {
139  errors.push_back(strprintf("Insufficient totalFee (cannot be less than required fee %s)",
140  FormatMoney(requiredFee)));
142  }
143  new_fee = total_fee;
144  nNewFeeRate = CFeeRate(total_fee, maxNewTxSize);
145  } else {
146  new_fee = GetMinimumFee(*wallet, maxNewTxSize, coin_control, mempool, ::feeEstimator, nullptr /* FeeCalculation */);
147  nNewFeeRate = CFeeRate(new_fee, maxNewTxSize);
148 
149  // New fee rate must be at least old rate + minimum incremental relay rate
150  // walletIncrementalRelayFee.GetFeePerK() should be exact, because it's initialized
151  // in that unit (fee per kb).
152  // However, nOldFeeRate is a calculated value from the tx fee/size, so
153  // add 1 satoshi to the result, because it may have been rounded down.
154  if (nNewFeeRate.GetFeePerK() < nOldFeeRate.GetFeePerK() + 1 + walletIncrementalRelayFee.GetFeePerK()) {
155  nNewFeeRate = CFeeRate(nOldFeeRate.GetFeePerK() + 1 + walletIncrementalRelayFee.GetFeePerK());
156  new_fee = nNewFeeRate.GetFee(maxNewTxSize);
157  }
158  }
159 
160  // Check that in all cases the new fee doesn't violate maxTxFee
161  if (new_fee > maxTxFee) {
162  errors.push_back(strprintf("Specified or calculated fee %s is too high (cannot be higher than maxTxFee %s)",
163  FormatMoney(new_fee), FormatMoney(maxTxFee)));
164  return Result::WALLET_ERROR;
165  }
166 
167  // check that fee rate is higher than mempool's minimum fee
168  // (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
169  // This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps,
170  // in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a
171  // moment earlier. In this case, we report an error to the user, who may use total_fee to make an adjustment.
172  CFeeRate minMempoolFeeRate = mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
173  if (nNewFeeRate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) {
174  errors.push_back(strprintf(
175  "New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- "
176  "the totalFee value should be at least %s or the settxfee value should be at least %s to add transaction",
177  FormatMoney(nNewFeeRate.GetFeePerK()),
178  FormatMoney(minMempoolFeeRate.GetFeePerK()),
179  FormatMoney(minMempoolFeeRate.GetFee(maxNewTxSize)),
180  FormatMoney(minMempoolFeeRate.GetFeePerK())));
181  return Result::WALLET_ERROR;
182  }
183 
184  // Now modify the output to increase the fee.
185  // If the output is not large enough to pay the fee, fail.
186  CAmount nDelta = new_fee - old_fee;
187  assert(nDelta > 0);
188  mtx = CMutableTransaction{*wtx.tx};
189  CTxOut* poutput = &(mtx.vout[nOutput]);
190  if (poutput->nValue < nDelta) {
191  errors.push_back("Change output is too small to bump the fee");
192  return Result::WALLET_ERROR;
193  }
194 
195  // If the output would become dust, discard it (converting the dust to fee)
196  poutput->nValue -= nDelta;
197  if (poutput->nValue <= GetDustThreshold(*poutput, GetDiscardRate(*wallet, ::feeEstimator))) {
198  wallet->WalletLogPrintf("Bumping fee and discarding dust output\n");
199  new_fee += poutput->nValue;
200  mtx.vout.erase(mtx.vout.begin() + nOutput);
201  }
202 
203  // Mark new tx not replaceable, if requested.
204  if (!coin_control.m_signal_bip125_rbf.get_value_or(wallet->m_signal_rbf)) {
205  for (auto& input : mtx.vin) {
206  if (input.nSequence < 0xfffffffe) input.nSequence = 0xfffffffe;
207  }
208  }
209 
210 
211  return Result::OK;
212 }
213 
215  LOCK2(cs_main, wallet->cs_wallet);
216  return wallet->SignTransaction(mtx);
217 }
218 
219 Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid)
220 {
221  LOCK2(cs_main, wallet->cs_wallet);
222  if (!errors.empty()) {
223  return Result::MISC_ERROR;
224  }
225  auto it = txid.IsNull() ? wallet->mapWallet.end() : wallet->mapWallet.find(txid);
226  if (it == wallet->mapWallet.end()) {
227  errors.push_back("Invalid or non-wallet transaction id");
228  return Result::MISC_ERROR;
229  }
230  CWalletTx& oldWtx = it->second;
231 
232  // make sure the transaction still has no descendants and hasn't been mined in the meantime
233  Result result = PreconditionChecks(wallet, oldWtx, errors);
234  if (result != Result::OK) {
235  return result;
236  }
237 
238  // commit/broadcast the tx
239  CTransactionRef tx = MakeTransactionRef(std::move(mtx));
240  mapValue_t mapValue = oldWtx.mapValue;
241  mapValue["replaces_txid"] = oldWtx.GetHash().ToString();
242 
243  CReserveKey reservekey(wallet);
244  CValidationState state;
245  if (!wallet->CommitTransaction(tx, std::move(mapValue), oldWtx.vOrderForm, reservekey, g_connman.get(), state)) {
246  // NOTE: CommitTransaction never returns false, so this should never happen.
247  errors.push_back(strprintf("The transaction was rejected: %s", FormatStateMessage(state)));
248  return Result::WALLET_ERROR;
249  }
250 
251  bumped_txid = tx->GetHash();
252  if (state.IsInvalid()) {
253  // This can happen if the mempool rejected the transaction. Report
254  // what happened in the "errors" response.
255  errors.push_back(strprintf("Error: The transaction was rejected: %s", FormatStateMessage(state)));
256  }
257 
258  // mark the original tx as bumped
259  if (!wallet->MarkReplaced(oldWtx.GetHash(), bumped_txid)) {
260  // TODO: see if JSON-RPC has a standard way of returning a response
261  // along with an exception. It would be good to return information about
262  // wtxBumped to the caller even if marking the original transaction
263  // replaced does not succeed for some reason.
264  errors.push_back("Created new bumpfee transaction but could not mark the original transaction as replaced");
265  }
266  return Result::OK;
267 }
268 
269 } // namespace feebumper
CAmount nValue
Definition: transaction.h:134
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost)
Compute the virtual transaction size (weight reinterpreted as bytes).
Definition: policy.cpp:246
CTxMemPool mempool
CAmount GetMinimumFee(const CWallet &wallet, unsigned int nTxBytes, const CCoinControl &coin_control, const CTxMemPool &pool, const CBlockPolicyEstimator &estimator, FeeCalculation *feeCalc)
Estimate the minimum fee considering user set parameters and the required fee.
Definition: fees.cpp:22
Result CreateTransaction(const CWallet *wallet, const uint256 &txid, const CCoinControl &coin_control, CAmount total_fee, std::vector< std::string > &errors, CAmount &old_fee, CAmount &new_fee, CMutableTransaction &mtx)
Create bumpfee transaction.
Definition: feebumper.cpp:76
const CWalletTx * GetWalletTx(const uint256 &hash) const
Definition: wallet.cpp:169
std::map< std::string, std::string > mapValue_t
Definition: wallet.h:182
#define strprintf
Definition: tinyformat.h:1066
const uint256 & GetHash() const
Definition: wallet.h:283
CAmount maxTxFee
Absolute maximum transaction fee (in satoshis) used by wallet and mempool (rejects high fee in sendra...
Definition: validation.cpp:242
std::vector< CTxIn > vin
Definition: transaction.h:362
CAmount GetDebit(const isminefilter &filter) const
filter decides which addresses will count towards the debit
Definition: wallet.cpp:1774
bool CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector< std::pair< std::string, std::string >> orderForm, CReserveKey &reservekey, CConnman *connman, CValidationState &state)
Call after CreateTransaction unless you want to abort.
Definition: wallet.cpp:2958
bool MarkReplaced(const uint256 &originalHash, const uint256 &newHash)
Mark a transaction as replaced by another transaction (e.g., BIP 125).
Definition: wallet.cpp:814
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:402
bool IsChange(const CTxOut &txout) const
Definition: wallet.cpp:1263
bool IsNull() const
Definition: uint256.h:32
Coin Control Features.
Definition: coincontrol.h:16
mapValue_t mapValue
Key/value map with information about the transaction.
Definition: wallet.h:326
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
CBlockPolicyEstimator feeEstimator
Definition: validation.cpp:244
#define LOCK2(cs1, cs2)
Definition: sync.h:182
bool SignTransaction(CWallet *wallet, CMutableTransaction &mtx)
Sign the new transaction,.
Definition: feebumper.cpp:214
CCriticalSection cs_main
Definition: validation.cpp:216
bool IsInvalid() const
Definition: validation.h:68
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
Definition: wallet.h:1136
CTransactionRef tx
Definition: wallet.h:218
#define LOCK(cs)
Definition: sync.h:181
bool SignTransaction(CMutableTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2456
An output of a transaction.
Definition: transaction.h:131
std::string ToString() const
Definition: uint256.cpp:62
CCriticalSection cs_wallet
Definition: wallet.h:709
std::vector< CTxOut > vout
Definition: transaction.h:363
CFeeRate GetMinFee(size_t sizelimit) const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized transactions...
Definition: txmempool.cpp:986
std::string FormatMoney(const CAmount &n)
Money parsing/formatting utilities.
CAmount GetDustThreshold(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
Definition: policy.cpp:18
boost::optional< bool > m_signal_bip125_rbf
Override the wallet&#39;s m_signal_rbf if set.
Definition: coincontrol.h:34
CCriticalSection cs
Definition: txmempool.h:487
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:295
bool TransactionCanBeBumped(const CWallet *wallet, const uint256 &txid)
Return whether transaction can be bumped.
Definition: feebumper.cpp:65
Capture information about block/transaction validation.
Definition: validation.h:26
256-bit opaque blob.
Definition: uint256.h:122
ArgsManager gArgs
Definition: util.cpp:88
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:51
std::string FormatStateMessage(const CValidationState &state)
Convert CValidationState to a human-readable message for logging.
Definition: validation.cpp:453
A key allocated from the key pool.
Definition: wallet.h:1145
Result CommitTransaction(CWallet *wallet, const uint256 &txid, CMutableTransaction &&mtx, std::vector< std::string > &errors, uint256 &bumped_txid)
Commit the bumpfee transaction.
Definition: feebumper.cpp:219
CFeeRate GetDiscardRate(const CWallet &wallet, const CBlockPolicyEstimator &estimator)
Return the maximum feerate for discarding change.
Definition: fees.cpp:93
bool SignalsOptInRBF(const CTransaction &tx)
Definition: rbf.cpp:7
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: util.cpp:526
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:599
Fee rate in satoshis per kilobyte: CAmount / kB.
Definition: feerate.h:19
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:74
A mutable version of CTransaction.
Definition: transaction.h:360
CAmount GetRequiredFee(const CWallet &wallet, unsigned int nTxBytes)
Return the minimum required absolute fee for this size based on the required fee rate.
Definition: fees.cpp:16
bool m_signal_rbf
Definition: wallet.h:921
CFeeRate incrementalRelayFee
Definition: policy.cpp:242
CAmount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:41
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig)
Definition: wallet.cpp:1488
std::vector< std::pair< std::string, std::string > > vOrderForm
Definition: wallet.h:327
CAmount GetFee(size_t nBytes) const
Return the fee in satoshis for the given size in bytes.
Definition: feerate.cpp:23