3
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
4
5
5
#include < interfaces/chain.h>
6
- #include < wallet/coincontrol.h>
7
- #include < wallet/feebumper.h>
8
- #include < wallet/fees.h>
9
- #include < wallet/wallet.h>
10
6
#include < policy/fees.h>
11
7
#include < policy/policy.h>
12
8
#include < util/moneystr.h>
13
9
#include < util/rbf.h>
14
10
#include < util/system.h>
11
+ #include < util/translation.h>
12
+ #include < wallet/coincontrol.h>
13
+ #include < wallet/feebumper.h>
14
+ #include < wallet/fees.h>
15
+ #include < wallet/wallet.h>
15
16
16
17
// ! Check whether transaction has descendant in wallet or mempool, or has been
17
18
// ! mined, or conflicts with a mined transaction. Return a feebumper::Result.
18
- static feebumper::Result PreconditionChecks (const CWallet& wallet, const CWalletTx& wtx, std::vector<std::string >& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
19
+ static feebumper::Result PreconditionChecks (const CWallet& wallet, const CWalletTx& wtx, std::vector<bilingual_str >& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
19
20
{
20
21
if (wallet.HasWalletSpend (wtx.GetHash ())) {
21
- errors.push_back (" Transaction has descendants in the wallet" );
22
+ errors.push_back (Untranslated ( " Transaction has descendants in the wallet" ) );
22
23
return feebumper::Result::INVALID_PARAMETER;
23
24
}
24
25
25
26
{
26
27
if (wallet.chain ().hasDescendantsInMempool (wtx.GetHash ())) {
27
- errors.push_back (" Transaction has descendants in the mempool" );
28
+ errors.push_back (Untranslated ( " Transaction has descendants in the mempool" ) );
28
29
return feebumper::Result::INVALID_PARAMETER;
29
30
}
30
31
}
31
32
32
33
if (wtx.GetDepthInMainChain () != 0 ) {
33
- errors.push_back (" Transaction has been mined, or is conflicted with a mined transaction" );
34
+ errors.push_back (Untranslated ( " Transaction has been mined, or is conflicted with a mined transaction" ) );
34
35
return feebumper::Result::WALLET_ERROR;
35
36
}
36
37
37
38
if (!SignalsOptInRBF (*wtx.tx )) {
38
- errors.push_back (" Transaction is not BIP 125 replaceable" );
39
+ errors.push_back (Untranslated ( " Transaction is not BIP 125 replaceable" ) );
39
40
return feebumper::Result::WALLET_ERROR;
40
41
}
41
42
42
43
if (wtx.mapValue .count (" replaced_by_txid" )) {
43
- errors.push_back (strprintf (" Cannot bump transaction %s which was already bumped by transaction %s" , wtx.GetHash ().ToString (), wtx.mapValue .at (" replaced_by_txid" )));
44
+ errors.push_back (strprintf (Untranslated ( " Cannot bump transaction %s which was already bumped by transaction %s" ) , wtx.GetHash ().ToString (), wtx.mapValue .at (" replaced_by_txid" )));
44
45
return feebumper::Result::WALLET_ERROR;
45
46
}
46
47
47
48
// check that original tx consists entirely of our inputs
48
49
// 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)
49
50
isminefilter filter = wallet.GetLegacyScriptPubKeyMan () && wallet.IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS) ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE;
50
51
if (!wallet.IsAllFromMe (*wtx.tx , filter)) {
51
- errors.push_back (" Transaction contains inputs that don't belong to this wallet" );
52
+ errors.push_back (Untranslated ( " Transaction contains inputs that don't belong to this wallet" ) );
52
53
return feebumper::Result::WALLET_ERROR;
53
54
}
54
55
@@ -57,7 +58,8 @@ static feebumper::Result PreconditionChecks(const CWallet& wallet, const CWallet
57
58
}
58
59
59
60
// ! Check if the user provided a valid feeRate
60
- static feebumper::Result CheckFeeRate (const CWallet& wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, std::vector<std::string>& errors) {
61
+ static feebumper::Result CheckFeeRate (const CWallet& wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, std::vector<bilingual_str>& errors)
62
+ {
61
63
// check that fee rate is higher than mempool's minimum fee
62
64
// (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
63
65
// This may occur if the user set fee_rate or paytxfee too low, if fallbackfee is too low, or, perhaps,
@@ -67,7 +69,7 @@ static feebumper::Result CheckFeeRate(const CWallet& wallet, const CWalletTx& wt
67
69
68
70
if (newFeerate.GetFeePerK () < minMempoolFeeRate.GetFeePerK ()) {
69
71
errors.push_back (strprintf (
70
- " New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- " ,
72
+ Untranslated ( " New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- " ) ,
71
73
FormatMoney (newFeerate.GetFeePerK ()),
72
74
FormatMoney (minMempoolFeeRate.GetFeePerK ())));
73
75
return feebumper::Result::WALLET_ERROR;
@@ -86,23 +88,23 @@ static feebumper::Result CheckFeeRate(const CWallet& wallet, const CWalletTx& wt
86
88
CAmount minTotalFee = nOldFeeRate.GetFee (maxTxSize) + incrementalRelayFee.GetFee (maxTxSize);
87
89
88
90
if (new_total_fee < minTotalFee) {
89
- errors.push_back (strprintf (" Insufficient total fee %s, must be at least %s (oldFee %s + incrementalFee %s)" ,
91
+ errors.push_back (strprintf (Untranslated ( " Insufficient total fee %s, must be at least %s (oldFee %s + incrementalFee %s)" ) ,
90
92
FormatMoney (new_total_fee), FormatMoney (minTotalFee), FormatMoney (nOldFeeRate.GetFee (maxTxSize)), FormatMoney (incrementalRelayFee.GetFee (maxTxSize))));
91
93
return feebumper::Result::INVALID_PARAMETER;
92
94
}
93
95
94
96
CAmount requiredFee = GetRequiredFee (wallet, maxTxSize);
95
97
if (new_total_fee < requiredFee) {
96
- errors.push_back (strprintf (" Insufficient total fee (cannot be less than required fee %s)" ,
98
+ errors.push_back (strprintf (Untranslated ( " Insufficient total fee (cannot be less than required fee %s)" ) ,
97
99
FormatMoney (requiredFee)));
98
100
return feebumper::Result::INVALID_PARAMETER;
99
101
}
100
102
101
103
// Check that in all cases the new fee doesn't violate maxTxFee
102
104
const CAmount max_tx_fee = wallet.m_default_max_tx_fee ;
103
105
if (new_total_fee > max_tx_fee) {
104
- errors.push_back (strprintf (" Specified or calculated fee %s is too high (cannot be higher than -maxtxfee %s)" ,
105
- FormatMoney (new_total_fee), FormatMoney (max_tx_fee)));
106
+ errors.push_back (strprintf (Untranslated ( " Specified or calculated fee %s is too high (cannot be higher than -maxtxfee %s)" ) ,
107
+ FormatMoney (new_total_fee), FormatMoney (max_tx_fee)));
106
108
return feebumper::Result::WALLET_ERROR;
107
109
}
108
110
@@ -144,12 +146,12 @@ bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid)
144
146
const CWalletTx* wtx = wallet.GetWalletTx (txid);
145
147
if (wtx == nullptr ) return false ;
146
148
147
- std::vector<std::string > errors_dummy;
149
+ std::vector<bilingual_str > errors_dummy;
148
150
feebumper::Result res = PreconditionChecks (wallet, *wtx, errors_dummy);
149
151
return res == feebumper::Result::OK;
150
152
}
151
153
152
- Result CreateRateBumpTransaction (CWallet& wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<std::string >& errors,
154
+ Result CreateRateBumpTransaction (CWallet& wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<bilingual_str >& errors,
153
155
CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx)
154
156
{
155
157
// We are going to modify coin control later, copy to re-use
@@ -159,7 +161,7 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
159
161
errors.clear ();
160
162
auto it = wallet.mapWallet .find (txid);
161
163
if (it == wallet.mapWallet .end ()) {
162
- errors.push_back (" Invalid or non-wallet transaction id" );
164
+ errors.push_back (Untranslated ( " Invalid or non-wallet transaction id" ) );
163
165
return Result::INVALID_ADDRESS_OR_KEY;
164
166
}
165
167
const CWalletTx& wtx = it->second ;
@@ -216,9 +218,9 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
216
218
CTransactionRef tx_new = MakeTransactionRef ();
217
219
CAmount fee_ret;
218
220
int change_pos_in_out = -1 ; // No requested location for change
219
- std::string fail_reason;
221
+ bilingual_str fail_reason;
220
222
if (!wallet.CreateTransaction (recipients, tx_new, fee_ret, change_pos_in_out, fail_reason, new_coin_control, false )) {
221
- errors.push_back (" Unable to create transaction: " + fail_reason);
223
+ errors.push_back (Untranslated ( " Unable to create transaction: " ) + Untranslated ( " " ) + fail_reason);
222
224
return Result::WALLET_ERROR;
223
225
}
224
226
@@ -242,15 +244,15 @@ bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx) {
242
244
return wallet.SignTransaction (mtx);
243
245
}
244
246
245
- Result CommitTransaction (CWallet& wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string >& errors, uint256& bumped_txid)
247
+ Result CommitTransaction (CWallet& wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<bilingual_str >& errors, uint256& bumped_txid)
246
248
{
247
249
LOCK (wallet.cs_wallet );
248
250
if (!errors.empty ()) {
249
251
return Result::MISC_ERROR;
250
252
}
251
253
auto it = txid.IsNull () ? wallet.mapWallet .end () : wallet.mapWallet .find (txid);
252
254
if (it == wallet.mapWallet .end ()) {
253
- errors.push_back (" Invalid or non-wallet transaction id" );
255
+ errors.push_back (Untranslated ( " Invalid or non-wallet transaction id" ) );
254
256
return Result::MISC_ERROR;
255
257
}
256
258
CWalletTx& oldWtx = it->second ;
@@ -275,7 +277,7 @@ Result CommitTransaction(CWallet& wallet, const uint256& txid, CMutableTransacti
275
277
// along with an exception. It would be good to return information about
276
278
// wtxBumped to the caller even if marking the original transaction
277
279
// replaced does not succeed for some reason.
278
- errors.push_back (" Created new bumpfee transaction but could not mark the original transaction as replaced" );
280
+ errors.push_back (Untranslated ( " Created new bumpfee transaction but could not mark the original transaction as replaced" ) );
279
281
}
280
282
return Result::OK;
281
283
}
0 commit comments