wallet, rpc:remove settxfee and paytxfee

This commit is contained in:
Pol Espinasa committed 2026-02-13 10:52:25 +01:00
1 parent 4ae00e9a71
commit 331a5279d2
26 files changed
+118 -255

No files matched your search

-2
View File
@@ -367,7 +367,6 @@ struct GetinfoRequestHandler : BaseRequestHandler {
if (!batch[ID_WALLETINFO]["result"]["unlocked_until"].isNull()) { if (!batch[ID_WALLETINFO]["result"]["unlocked_until"].isNull()) {
result.pushKV("unlocked_until", batch[ID_WALLETINFO]["result"]["unlocked_until"]); result.pushKV("unlocked_until", batch[ID_WALLETINFO]["result"]["unlocked_until"]);
} }
result.pushKV("paytxfee", batch[ID_WALLETINFO]["result"]["paytxfee"]);
} }
if (!batch[ID_BALANCES]["result"].isNull()) { if (!batch[ID_BALANCES]["result"].isNull()) {
result.pushKV("balance", batch[ID_BALANCES]["result"]["mine"]["trusted"]); result.pushKV("balance", batch[ID_BALANCES]["result"]["mine"]["trusted"]);
@@ -1152,7 +1151,6 @@ static void ParseGetInfoResult(UniValue& result)
if (!result["unlocked_until"].isNull()) { if (!result["unlocked_until"].isNull()) {
result_string += strprintf("Unlocked until: %s\n", result["unlocked_until"].getValStr()); result_string += strprintf("Unlocked until: %s\n", result["unlocked_until"].getValStr());
} }
result_string += strprintf("Transaction fee rate (-paytxfee) (%s/kvB): %s\n\n", CURRENCY_UNIT, result["paytxfee"].getValStr());
} }
if (!result["balance"].isNull()) { if (!result["balance"].isNull()) {
result_string += strprintf("%sBalance:%s %s\n\n", CYAN, RESET, result["balance"].getValStr()); result_string += strprintf("%sBalance:%s %s\n\n", CYAN, RESET, result["balance"].getValStr());
-1
View File
@@ -33,7 +33,6 @@ std::string StringForFeeReason(FeeReason reason)
{FeeReason::DOUBLE_ESTIMATE, "Double Target 95% Threshold"}, {FeeReason::DOUBLE_ESTIMATE, "Double Target 95% Threshold"},
{FeeReason::CONSERVATIVE, "Conservative Double Target longer horizon"}, {FeeReason::CONSERVATIVE, "Conservative Double Target longer horizon"},
{FeeReason::MEMPOOL_MIN, "Mempool Min Fee"}, {FeeReason::MEMPOOL_MIN, "Mempool Min Fee"},
{FeeReason::PAYTXFEE, "PayTxFee set"},
{FeeReason::FALLBACK, "Fallback fee"}, {FeeReason::FALLBACK, "Fallback fee"},
{FeeReason::REQUIRED, "Minimum Required Fee"}, {FeeReason::REQUIRED, "Minimum Required Fee"},
}; };
-1
View File
@@ -38,7 +38,6 @@ void DummyWalletInit::AddWalletOptions(ArgsManager& argsman) const
"-maxapsfee=<n>", "-maxapsfee=<n>",
"-maxtxfee=<amt>", "-maxtxfee=<amt>",
"-mintxfee=<amt>", "-mintxfee=<amt>",
"-paytxfee=<amt>",
"-signer=<cmd>", "-signer=<cmd>",
"-spendzeroconfchange", "-spendzeroconfchange",
"-txconfirmtarget=<n>", "-txconfirmtarget=<n>",
-1
View File
@@ -64,7 +64,6 @@ enum class FeeReason {
DOUBLE_ESTIMATE, DOUBLE_ESTIMATE,
CONSERVATIVE, CONSERVATIVE,
MEMPOOL_MIN, MEMPOOL_MIN,
PAYTXFEE,
FALLBACK, FALLBACK,
REQUIRED, REQUIRED,
}; };
-3
View File
@@ -40,7 +40,6 @@
using common::PSBTError; using common::PSBTError;
using wallet::CCoinControl; using wallet::CCoinControl;
using wallet::DEFAULT_PAY_TX_FEE;
static constexpr std::array confTargets{2, 4, 6, 12, 24, 48, 144, 504, 1008}; static constexpr std::array confTargets{2, 4, 6, 12, 24, 48, 144, 504, 1008};
int getConfTargetForIndex(int index) { int getConfTargetForIndex(int index) {
@@ -125,8 +124,6 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p
settings.setValue("nFeeRadio", 0); // recommended settings.setValue("nFeeRadio", 0); // recommended
if (!settings.contains("nSmartFeeSliderPosition")) if (!settings.contains("nSmartFeeSliderPosition"))
settings.setValue("nSmartFeeSliderPosition", 0); settings.setValue("nSmartFeeSliderPosition", 0);
if (!settings.contains("nTransactionFee"))
settings.setValue("nTransactionFee", (qint64)DEFAULT_PAY_TX_FEE);
ui->groupFee->setId(ui->radioSmartFee, 0); ui->groupFee->setId(ui->radioSmartFee, 0);
ui->groupFee->setId(ui->radioCustomFee, 1); ui->groupFee->setId(ui->radioCustomFee, 1);
ui->groupFee->button((int)std::max(0, std::min(1, settings.value("nFeeRadio").toInt())))->setChecked(true); ui->groupFee->button((int)std::max(0, std::min(1, settings.value("nFeeRadio").toInt())))->setChecked(true);
-1
View File
@@ -79,7 +79,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "sendtoaddress", 8, "avoid_reuse" }, { "sendtoaddress", 8, "avoid_reuse" },
{ "sendtoaddress", 9, "fee_rate"}, { "sendtoaddress", 9, "fee_rate"},
{ "sendtoaddress", 10, "verbose"}, { "sendtoaddress", 10, "verbose"},
{ "settxfee", 0, "amount" },
{ "getreceivedbyaddress", 1, "minconf" }, { "getreceivedbyaddress", 1, "minconf" },
{ "getreceivedbyaddress", 2, "include_immature_coinbase" }, { "getreceivedbyaddress", 2, "include_immature_coinbase" },
{ "getreceivedbylabel", 0, "label", ParamFormat::STRING }, { "getreceivedbylabel", 0, "label", ParamFormat::STRING },
+1 -1
View File
@@ -26,6 +26,6 @@ FUZZ_TARGET(fees)
const CAmount rounded_fee = fee_filter_rounder.round(current_minimum_fee); const CAmount rounded_fee = fee_filter_rounder.round(current_minimum_fee);
assert(MoneyRange(rounded_fee)); assert(MoneyRange(rounded_fee));
} }
const FeeReason fee_reason = fuzzed_data_provider.PickValueInArray({FeeReason::NONE, FeeReason::HALF_ESTIMATE, FeeReason::FULL_ESTIMATE, FeeReason::DOUBLE_ESTIMATE, FeeReason::CONSERVATIVE, FeeReason::MEMPOOL_MIN, FeeReason::PAYTXFEE, FeeReason::FALLBACK, FeeReason::REQUIRED}); const FeeReason fee_reason = fuzzed_data_provider.PickValueInArray({FeeReason::NONE, FeeReason::HALF_ESTIMATE, FeeReason::FULL_ESTIMATE, FeeReason::DOUBLE_ESTIMATE, FeeReason::CONSERVATIVE, FeeReason::MEMPOOL_MIN, FeeReason::FALLBACK, FeeReason::REQUIRED});
(void)StringForFeeReason(fee_reason); (void)StringForFeeReason(fee_reason);
} }
+1 -1
View File
@@ -93,7 +93,7 @@ public:
bool m_allow_other_inputs = true; bool m_allow_other_inputs = true;
//! Override automatic min/max checks on fee, m_feerate must be set if true //! Override automatic min/max checks on fee, m_feerate must be set if true
bool fOverrideFeeRate = false; bool fOverrideFeeRate = false;
//! Override the wallet's m_pay_tx_fee if set //! Override the wallet's fee rate if set
std::optional<CFeeRate> m_feerate; std::optional<CFeeRate> m_feerate;
//! Override the default confirmation target if set //! Override the default confirmation target if set
std::optional<unsigned int> m_confirm_target; std::optional<unsigned int> m_confirm_target;
+1 -1
View File
@@ -61,7 +61,7 @@ static feebumper::Result CheckFeeRate(const CWallet& wallet, const CMutableTrans
{ {
// check that fee rate is higher than mempool's minimum fee // check that fee rate is higher than mempool's minimum fee
// (no point in bumping fee if we know that the new tx won't be accepted to the mempool) // (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
// This may occur if the user set fee_rate or paytxfee too low, if fallbackfee is too low, or, perhaps, // This may occur if fallbackfee is too low, or, perhaps,
// in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a // in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a
// moment earlier. In this case, we report an error to the user, who may adjust the fee. // moment earlier. In this case, we report an error to the user, who may adjust the fee.
CFeeRate minMempoolFeeRate = wallet.chain().mempoolMinFee(); CFeeRate minMempoolFeeRate = wallet.chain().mempoolMinFee();
+2 -8
View File
@@ -31,22 +31,16 @@ CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_contr
/* User control of how to calculate fee uses the following parameter precedence: /* User control of how to calculate fee uses the following parameter precedence:
1. coin_control.m_feerate 1. coin_control.m_feerate
2. coin_control.m_confirm_target 2. coin_control.m_confirm_target
3. m_pay_tx_fee (user-set member variable of wallet) 3. m_confirm_target (user-set member variable of wallet)
4. m_confirm_target (user-set member variable of wallet)
The first parameter that is set is used. The first parameter that is set is used.
*/ */
CFeeRate feerate_needed; CFeeRate feerate_needed;
if (coin_control.m_feerate) { // 1. if (coin_control.m_feerate) { // 1.
feerate_needed = *(coin_control.m_feerate); feerate_needed = *(coin_control.m_feerate);
if (feeCalc) feeCalc->reason = FeeReason::PAYTXFEE;
// Allow to override automatic min/max check over coin control instance // Allow to override automatic min/max check over coin control instance
if (coin_control.fOverrideFeeRate) return feerate_needed; if (coin_control.fOverrideFeeRate) return feerate_needed;
} }
else if (!coin_control.m_confirm_target && wallet.m_pay_tx_fee != CFeeRate(0)) { // 3. TODO: remove magic value of 0 for wallet member m_pay_tx_fee else { // 2. or 3.
feerate_needed = wallet.m_pay_tx_fee;
if (feeCalc) feeCalc->reason = FeeReason::PAYTXFEE;
}
else { // 2. or 4.
// We will use smart fee estimation // We will use smart fee estimation
unsigned int target = coin_control.m_confirm_target ? *coin_control.m_confirm_target : wallet.m_confirm_target; unsigned int target = coin_control.m_confirm_target ? *coin_control.m_confirm_target : wallet.m_confirm_target;
// By default estimates are economical iff we are signaling opt-in-RBF // By default estimates are economical iff we are signaling opt-in-RBF
+1 -3
View File
@@ -63,13 +63,11 @@ void WalletInit::AddWalletOptions(ArgsManager& argsman) const
CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE)), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE)), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-mintxfee=<amt>", strprintf("Fee rates (in %s/kvB) smaller than this are considered zero fee for transaction creation (default: %s)", argsman.AddArg("-mintxfee=<amt>", strprintf("Fee rates (in %s/kvB) smaller than this are considered zero fee for transaction creation (default: %s)",
CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-paytxfee=<amt>", strprintf("(DEPRECATED) Fee rate (in %s/kvB) to add to transactions you send (default: %s)",
CURRENCY_UNIT, FormatMoney(CFeeRate{DEFAULT_PAY_TX_FEE}.GetFeePerK())), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
#ifdef ENABLE_EXTERNAL_SIGNER #ifdef ENABLE_EXTERNAL_SIGNER
argsman.AddArg("-signer=<cmd>", "External signing tool, see doc/external-signer.md", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); argsman.AddArg("-signer=<cmd>", "External signing tool, see doc/external-signer.md", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
#endif #endif
argsman.AddArg("-spendzeroconfchange", strprintf("Spend unconfirmed change when sending transactions (default: %u)", DEFAULT_SPEND_ZEROCONF_CHANGE), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); argsman.AddArg("-spendzeroconfchange", strprintf("Spend unconfirmed change when sending transactions (default: %u)", DEFAULT_SPEND_ZEROCONF_CHANGE), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-txconfirmtarget=<n>", strprintf("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)", DEFAULT_TX_CONFIRM_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); argsman.AddArg("-txconfirmtarget=<n>", strprintf("Include enough fee so transactions begin confirmation on average within n blocks (default: %u)", DEFAULT_TX_CONFIRM_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-wallet=<path>", "Specify wallet path to load at startup. Can be used multiple times to load multiple wallets. Path is to a directory containing wallet data and log files. If the path is not absolute, it is interpreted relative to <walletdir>. This only loads existing wallets and does not create new ones. For backwards compatibility this also accepts names of existing top-level data files in <walletdir>.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET); argsman.AddArg("-wallet=<path>", "Specify wallet path to load at startup. Can be used multiple times to load multiple wallets. Path is to a directory containing wallet data and log files. If the path is not absolute, it is interpreted relative to <walletdir>. This only loads existing wallets and does not create new ones. For backwards compatibility this also accepts names of existing top-level data files in <walletdir>.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET);
argsman.AddArg("-walletbroadcast", strprintf("Make the wallet broadcast transactions (default: %u)", DEFAULT_WALLETBROADCAST), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); argsman.AddArg("-walletbroadcast", strprintf("Make the wallet broadcast transactions (default: %u)", DEFAULT_WALLETBROADCAST), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET); argsman.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET);
-48
View File
@@ -427,54 +427,6 @@ RPCHelpMan sendmany()
}; };
} }
RPCHelpMan settxfee()
{
return RPCHelpMan{
"settxfee",
"(DEPRECATED) Set the transaction fee rate in " + CURRENCY_UNIT + "/kvB for this wallet. Overrides the global -paytxfee command line parameter.\n"
"Can be deactivated by passing 0 as the fee. In that case automatic fee selection will be used by default.\n",
{
{"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee rate in " + CURRENCY_UNIT + "/kvB"},
},
RPCResult{
RPCResult::Type::BOOL, "", "Returns true if successful"
},
RPCExamples{
HelpExampleCli("settxfee", "0.00001")
+ HelpExampleRpc("settxfee", "0.00001")
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
if (!pwallet->chain().rpcEnableDeprecated("settxfee")) {
throw JSONRPCError(RPC_METHOD_DEPRECATED, "settxfee is deprecated and will be fully removed in v31.0."
"\nTo use settxfee restart bitcoind with -deprecatedrpc=settxfee.");
}
CAmount nAmount = AmountFromValue(request.params[0]);
CFeeRate tx_fee_rate(nAmount, 1000);
CFeeRate max_tx_fee_rate(pwallet->m_default_max_tx_fee, 1000);
if (tx_fee_rate == CFeeRate(0)) {
// automatic selection
} else if (tx_fee_rate < pwallet->chain().relayMinFee()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than min relay tx fee (%s)", pwallet->chain().relayMinFee().ToString()));
} else if (tx_fee_rate < pwallet->m_min_fee) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than wallet min fee (%s)", pwallet->m_min_fee.ToString()));
} else if (tx_fee_rate > max_tx_fee_rate) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be more than wallet max tx fee (%s)", max_tx_fee_rate.ToString()));
}
pwallet->m_pay_tx_fee = tx_fee_rate;
return true;
},
};
}
// Only includes key documentation where the key is snake_case in all RPC methods. MixedCase keys can be added later. // Only includes key documentation where the key is snake_case in all RPC methods. MixedCase keys can be added later.
static std::vector<RPCArg> FundTxDoc(bool solving_data = true) static std::vector<RPCArg> FundTxDoc(bool solving_data = true)
{ {
-4
View File
@@ -47,7 +47,6 @@ static RPCHelpMan getwalletinfo()
{RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"}, {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"},
{RPCResult::Type::NUM, "keypoolsize_hd_internal", /*optional=*/true, "how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)"}, {RPCResult::Type::NUM, "keypoolsize_hd_internal", /*optional=*/true, "how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)"},
{RPCResult::Type::NUM_TIME, "unlocked_until", /*optional=*/true, "the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked (only present for passphrase-encrypted wallets)"}, {RPCResult::Type::NUM_TIME, "unlocked_until", /*optional=*/true, "the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked (only present for passphrase-encrypted wallets)"},
{RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kvB"},
{RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"}, {RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"},
{RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"}, {RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"},
{RPCResult::Type::OBJ, "scanning", "current scanning details, or false if no scan is in progress", {RPCResult::Type::OBJ, "scanning", "current scanning details, or false if no scan is in progress",
@@ -96,7 +95,6 @@ static RPCHelpMan getwalletinfo()
if (pwallet->HasEncryptionKeys()) { if (pwallet->HasEncryptionKeys()) {
obj.pushKV("unlocked_until", pwallet->nRelockTime); obj.pushKV("unlocked_until", pwallet->nRelockTime);
} }
obj.pushKV("paytxfee", ValueFromAmount(pwallet->m_pay_tx_fee.GetFeePerK()));
obj.pushKV("private_keys_enabled", !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)); obj.pushKV("private_keys_enabled", !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
obj.pushKV("avoid_reuse", pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)); obj.pushKV("avoid_reuse", pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE));
if (pwallet->IsScanning()) { if (pwallet->IsScanning()) {
@@ -881,7 +879,6 @@ RPCHelpMan encryptwallet();
// spend // spend
RPCHelpMan sendtoaddress(); RPCHelpMan sendtoaddress();
RPCHelpMan sendmany(); RPCHelpMan sendmany();
RPCHelpMan settxfee();
RPCHelpMan fundrawtransaction(); RPCHelpMan fundrawtransaction();
RPCHelpMan bumpfee(); RPCHelpMan bumpfee();
RPCHelpMan psbtbumpfee(); RPCHelpMan psbtbumpfee();
@@ -951,7 +948,6 @@ std::span<const CRPCCommand> GetWalletRPCCommands()
{"wallet", &sendmany}, {"wallet", &sendmany},
{"wallet", &sendtoaddress}, {"wallet", &sendtoaddress},
{"wallet", &setlabel}, {"wallet", &setlabel},
{"wallet", &settxfee},
{"wallet", &setwalletflag}, {"wallet", &setwalletflag},
{"wallet", &signmessage}, {"wallet", &signmessage},
{"wallet", &signrawtransactionwithwallet}, {"wallet", &signrawtransactionwithwallet},
-1
View File
@@ -98,7 +98,6 @@ FUZZ_TARGET(wallet_fees, .init = initialize_setup)
const auto tx_bytes{fuzzed_data_provider.ConsumeIntegralInRange(0, std::numeric_limits<int32_t>::max())}; const auto tx_bytes{fuzzed_data_provider.ConsumeIntegralInRange(0, std::numeric_limits<int32_t>::max())};
if (fuzzed_data_provider.ConsumeBool()) { if (fuzzed_data_provider.ConsumeBool()) {
wallet.m_pay_tx_fee = CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)};
wallet.m_min_fee = CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)}; wallet.m_min_fee = CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)};
} }
-21
View File
@@ -3027,27 +3027,6 @@ bool CWallet::LoadWalletArgs(std::shared_ptr<CWallet> wallet, const WalletContex
wallet->m_discard_rate = CFeeRate{discard_fee.value()}; wallet->m_discard_rate = CFeeRate{discard_fee.value()};
} }
if (const auto arg{args.GetArg("-paytxfee")}) {
warnings.push_back(_("-paytxfee is deprecated and will be fully removed in v31.0."));
std::optional<CAmount> pay_tx_fee = ParseMoney(*arg);
if (!pay_tx_fee) {
error = AmountErrMsg("paytxfee", *arg);
return false;
} else if (pay_tx_fee.value() > HIGH_TX_FEE_PER_KB) {
warnings.push_back(AmountHighWarn("-paytxfee") + Untranslated(" ") +
_("This is the transaction fee you will pay if you send a transaction."));
}
wallet->m_pay_tx_fee = CFeeRate{pay_tx_fee.value(), 1000};
if (chain && wallet->m_pay_tx_fee < chain->relayMinFee()) {
error = strprintf(_("Invalid amount for %s=<amount>: '%s' (must be at least %s)"),
"-paytxfee", *arg, chain->relayMinFee().ToString());
return false;
}
}
if (const auto arg{args.GetArg("-maxtxfee")}) { if (const auto arg{args.GetArg("-maxtxfee")}) {
std::optional<CAmount> max_fee = ParseMoney(*arg); std::optional<CAmount> max_fee = ParseMoney(*arg);
if (!max_fee) { if (!max_fee) {
+1 -4
View File
@@ -102,8 +102,6 @@ std::unique_ptr<interfaces::Handler> HandleLoadWallet(WalletContext& context, Lo
void NotifyWalletLoaded(WalletContext& context, const std::shared_ptr<CWallet>& wallet); void NotifyWalletLoaded(WalletContext& context, const std::shared_ptr<CWallet>& wallet);
std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error); std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
//! -paytxfee default
constexpr CAmount DEFAULT_PAY_TX_FEE = 0;
//! -fallbackfee default //! -fallbackfee default
static const CAmount DEFAULT_FALLBACK_FEE = 0; static const CAmount DEFAULT_FALLBACK_FEE = 0;
//! -discardfee default //! -discardfee default
@@ -705,14 +703,13 @@ public:
/** Updates wallet birth time if 'time' is below it */ /** Updates wallet birth time if 'time' is below it */
void MaybeUpdateBirthTime(int64_t time); void MaybeUpdateBirthTime(int64_t time);
CFeeRate m_pay_tx_fee{DEFAULT_PAY_TX_FEE};
unsigned int m_confirm_target{DEFAULT_TX_CONFIRM_TARGET}; unsigned int m_confirm_target{DEFAULT_TX_CONFIRM_TARGET};
/** Allow Coin Selection to pick unconfirmed UTXOs that were sent from our own wallet if it /** Allow Coin Selection to pick unconfirmed UTXOs that were sent from our own wallet if it
* cannot fund the transaction otherwise. */ * cannot fund the transaction otherwise. */
bool m_spend_zero_conf_change{DEFAULT_SPEND_ZEROCONF_CHANGE}; bool m_spend_zero_conf_change{DEFAULT_SPEND_ZEROCONF_CHANGE};
bool m_signal_rbf{DEFAULT_WALLET_RBF}; bool m_signal_rbf{DEFAULT_WALLET_RBF};
bool m_allow_fallback_fee{true}; //!< will be false if -fallbackfee=0 bool m_allow_fallback_fee{true}; //!< will be false if -fallbackfee=0
CFeeRate m_min_fee{DEFAULT_TRANSACTION_MINFEE}; //!< Override with -mintxfee CFeeRate m_min_fee{DEFAULT_TRANSACTION_MINFEE};
/** /**
* If fee estimation does not have enough data to provide estimates, use this fee instead. * If fee estimation does not have enough data to provide estimates, use this fee instead.
* Has no effect if not using fee estimation * Has no effect if not using fee estimation
-1
View File
@@ -249,7 +249,6 @@ class TestBitcoinCli(BitcoinTestFramework):
wallet_info = self.nodes[0].getwalletinfo() wallet_info = self.nodes[0].getwalletinfo()
assert_equal(int(cli_get_info['Keypool size']), wallet_info['keypoolsize']) assert_equal(int(cli_get_info['Keypool size']), wallet_info['keypoolsize'])
assert_equal(int(cli_get_info['Unlocked until']), wallet_info['unlocked_until']) assert_equal(int(cli_get_info['Unlocked until']), wallet_info['unlocked_until'])
assert_equal(Decimal(cli_get_info['Transaction fee rate (-paytxfee) (BTC/kvB)']), wallet_info['paytxfee'])
assert_equal(Decimal(cli_get_info['Min tx relay fee rate (BTC/kvB)']), network_info['relayfee']) assert_equal(Decimal(cli_get_info['Min tx relay fee rate (BTC/kvB)']), network_info['relayfee'])
assert_equal(self.nodes[0].cli.getwalletinfo(), wallet_info) assert_equal(self.nodes[0].cli.getwalletinfo(), wallet_info)
+1 -6
View File
@@ -4,7 +4,6 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test deprecation of RPC calls.""" """Test deprecation of RPC calls."""
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_raises_rpc_error
class DeprecatedRpcTest(BitcoinTestFramework): class DeprecatedRpcTest(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
@@ -27,12 +26,8 @@ class DeprecatedRpcTest(BitcoinTestFramework):
# Please don't delete nor modify this comment # Please don't delete nor modify this comment
self.log.info("Tests for deprecated RPC methods (if any)") self.log.info("Tests for deprecated RPC methods (if any)")
self.log.info("Currently no tests for deprecated RPC methods")
if self.is_wallet_compiled():
self.log.info("Tests for deprecated wallet-related RPC methods (if any)")
self.log.info("Test settxfee RPC deprecation")
self.nodes[0].createwallet("settxfeerpc")
assert_raises_rpc_error(-32, 'settxfee is deprecated and will be fully removed in v31.0.', self.nodes[0].settxfee, 0.01)
if __name__ == '__main__': if __name__ == '__main__':
DeprecatedRpcTest(__file__).main() DeprecatedRpcTest(__file__).main()
+3 -3
View File
@@ -55,10 +55,10 @@ class GetblockstatsTest(BitcoinTestFramework):
self.nodes[0].sendtoaddress(address=address, amount=10, subtractfeefromamount=True) self.nodes[0].sendtoaddress(address=address, amount=10, subtractfeefromamount=True)
self.nodes[0].sendtoaddress(address=address, amount=10, subtractfeefromamount=False) self.nodes[0].sendtoaddress(address=address, amount=10, subtractfeefromamount=False)
self.nodes[0].settxfee(amount=0.003) self.fee_rate=300
self.nodes[0].sendtoaddress(address=address, amount=1, subtractfeefromamount=True) self.nodes[0].sendtoaddress(address=address, amount=1, subtractfeefromamount=True, fee_rate=self.fee_rate)
# Send to OP_RETURN output to test its exclusion from statistics # Send to OP_RETURN output to test its exclusion from statistics
self.nodes[0].send(outputs={"data": "21"}) self.nodes[0].send(outputs={"data": "21"}, fee_rate=self.fee_rate)
self.sync_all() self.sync_all()
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
+7 -7
View File
@@ -32,7 +32,7 @@ class WalletTest(BitcoinTestFramework):
# whitelist peers to speed up tx relay / mempool sync # whitelist peers to speed up tx relay / mempool sync
self.noban_tx_relay = True self.noban_tx_relay = True
self.extra_args = [[ self.extra_args = [[
"-dustrelayfee=0", "-walletrejectlongchains=0", "-deprecatedrpc=settxfee" "-dustrelayfee=0", "-walletrejectlongchains=0"
]] * self.num_nodes ]] * self.num_nodes
self.setup_clean_chain = True self.setup_clean_chain = True
self.supports_cli = False self.supports_cli = False
@@ -240,14 +240,14 @@ class WalletTest(BitcoinTestFramework):
# Send 10 BTC normal # Send 10 BTC normal
address = self.nodes[0].getnewaddress("test") address = self.nodes[0].getnewaddress("test")
fee_per_byte = Decimal('0.001') / 1000 fee_per_byte = Decimal('0.001') / 1000
self.nodes[2].settxfee(fee_per_byte * 1000) fee_rate_sat_vb = fee_per_byte * Decimal(1e8)
txid = self.nodes[2].sendtoaddress(address, 10, "", "", False) txid = self.nodes[2].sendtoaddress(address, 10, "", "", False, fee_rate=fee_rate_sat_vb)
self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3])) self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])) node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
assert_equal(self.nodes[0].getbalance(), Decimal('10')) assert_equal(self.nodes[0].getbalance(), Decimal('10'))
# Send 10 BTC with subtract fee from amount # Send 10 BTC with subtract fee from amount
txid = self.nodes[2].sendtoaddress(address, 10, "", "", True) txid = self.nodes[2].sendtoaddress(address, 10, "", "", True, fee_rate=fee_rate_sat_vb)
self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3])) self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
node_2_bal -= Decimal('10') node_2_bal -= Decimal('10')
assert_equal(self.nodes[2].getbalance(), node_2_bal) assert_equal(self.nodes[2].getbalance(), node_2_bal)
@@ -256,14 +256,14 @@ class WalletTest(BitcoinTestFramework):
self.log.info("Test sendmany") self.log.info("Test sendmany")
# Sendmany 10 BTC # Sendmany 10 BTC
txid = self.nodes[2].sendmany('', {address: 10}, 0, "", []) txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [], fee_rate=fee_rate_sat_vb)
self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3])) self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
node_0_bal += Decimal('10') node_0_bal += Decimal('10')
node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])) node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
assert_equal(self.nodes[0].getbalance(), node_0_bal) assert_equal(self.nodes[0].getbalance(), node_0_bal)
# Sendmany 10 BTC with subtract fee from amount # Sendmany 10 BTC with subtract fee from amount
txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [address]) txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [address], fee_rate=fee_rate_sat_vb)
self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3])) self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
node_2_bal -= Decimal('10') node_2_bal -= Decimal('10')
assert_equal(self.nodes[2].getbalance(), node_2_bal) assert_equal(self.nodes[2].getbalance(), node_2_bal)
@@ -272,7 +272,7 @@ class WalletTest(BitcoinTestFramework):
# Sendmany 5 BTC to two addresses with subtracting fee from both addresses # Sendmany 5 BTC to two addresses with subtracting fee from both addresses
a0 = self.nodes[0].getnewaddress() a0 = self.nodes[0].getnewaddress()
a1 = self.nodes[0].getnewaddress() a1 = self.nodes[0].getnewaddress()
txid = self.nodes[2].sendmany(dummy='', amounts={a0: 5, a1: 5}, subtractfeefrom=[a0, a1]) txid = self.nodes[2].sendmany(dummy='', amounts={a0: 5, a1: 5}, subtractfeefrom=[a0, a1], fee_rate=fee_rate_sat_vb)
self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3])) self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
node_2_bal -= Decimal('10') node_2_bal -= Decimal('10')
assert_equal(self.nodes[2].getbalance(), node_2_bal) assert_equal(self.nodes[2].getbalance(), node_2_bal)
-27
View File
@@ -59,7 +59,6 @@ class BumpFeeTest(BitcoinTestFramework):
"-walletrbf={}".format(i), "-walletrbf={}".format(i),
"-mintxfee=0.00002", "-mintxfee=0.00002",
"-addresstype=bech32", "-addresstype=bech32",
"-deprecatedrpc=settxfee"
] for i in range(self.num_nodes)] ] for i in range(self.num_nodes)]
def skip_test_if_missing_module(self): def skip_test_if_missing_module(self):
@@ -105,7 +104,6 @@ class BumpFeeTest(BitcoinTestFramework):
test_bumpfee_metadata(self, rbf_node, dest_address) test_bumpfee_metadata(self, rbf_node, dest_address)
test_locked_wallet_fails(self, rbf_node, dest_address) test_locked_wallet_fails(self, rbf_node, dest_address)
test_change_script_match(self, rbf_node, dest_address) test_change_script_match(self, rbf_node, dest_address)
test_settxfee(self, rbf_node, dest_address)
test_maxtxfee_fails(self, rbf_node, dest_address) test_maxtxfee_fails(self, rbf_node, dest_address)
# These tests wipe out a number of utxos that are expected in other tests # These tests wipe out a number of utxos that are expected in other tests
test_small_output_with_feerate_succeeds(self, rbf_node, dest_address) test_small_output_with_feerate_succeeds(self, rbf_node, dest_address)
@@ -532,31 +530,6 @@ def test_dust_to_fee(self, rbf_node, dest_address):
assert_equal(full_bumped_tx["vout"][0]['value'], Decimal("0.00050000")) assert_equal(full_bumped_tx["vout"][0]['value'], Decimal("0.00050000"))
self.clear_mempool() self.clear_mempool()
def test_settxfee(self, rbf_node, dest_address):
self.log.info('Test settxfee')
assert_raises_rpc_error(-8, "txfee cannot be less than min relay tx fee", rbf_node.settxfee, Decimal('0.0000005'))
assert_raises_rpc_error(-8, "txfee cannot be less than wallet min fee", rbf_node.settxfee, Decimal('0.000015'))
# check that bumpfee reacts correctly to the use of settxfee (paytxfee)
rbfid = spend_one_input(rbf_node, dest_address)
requested_feerate = Decimal("0.00025000")
rbf_node.settxfee(requested_feerate)
bumped_tx = rbf_node.bumpfee(rbfid)
actual_feerate = bumped_tx["fee"] * 1000 / rbf_node.getrawtransaction(bumped_tx["txid"], True)["vsize"]
# Assert that the difference between the requested feerate and the actual
# feerate of the bumped transaction is small.
assert_greater_than(Decimal("0.00001000"), abs(requested_feerate - actual_feerate))
rbf_node.settxfee(Decimal("0.00000000")) # unset paytxfee
# check that settxfee respects -maxtxfee
self.restart_node(1, ['-maxtxfee=0.000025'] + self.extra_args[1])
assert_raises_rpc_error(-8, "txfee cannot be more than wallet max tx fee", rbf_node.settxfee, Decimal('0.00003'))
self.restart_node(1, self.extra_args[1])
rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
self.connect_nodes(1, 0)
self.clear_mempool()
def test_maxtxfee_fails(self, rbf_node, dest_address): def test_maxtxfee_fails(self, rbf_node, dest_address):
self.log.info('Test that bumpfee fails when it hits -maxtxfee') self.log.info('Test that bumpfee fails when it hits -maxtxfee')
# size of bumped transaction (p2wpkh, 1 input, 2 outputs): 141 vbytes # size of bumped transaction (p2wpkh, 1 input, 2 outputs): 141 vbytes
+10 -8
View File
@@ -15,12 +15,13 @@ from test_framework.blocktools import (
TIME_GENESIS_BLOCK, TIME_GENESIS_BLOCK,
) )
from decimal import Decimal
class CreateTxWalletTest(BitcoinTestFramework): class CreateTxWalletTest(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.setup_clean_chain = True self.setup_clean_chain = True
self.num_nodes = 1 self.num_nodes = 1
self.extra_args = [["-deprecatedrpc=settxfee"]] self.extra_args = [[]]
def skip_test_if_missing_module(self): def skip_test_if_missing_module(self):
self.skip_if_no_wallet() self.skip_if_no_wallet()
@@ -54,7 +55,7 @@ class CreateTxWalletTest(BitcoinTestFramework):
outputs = {self.nodes[0].getnewaddress(address_type='bech32'): 0.000025 for _ in range(400)} outputs = {self.nodes[0].getnewaddress(address_type='bech32'): 0.000025 for _ in range(400)}
raw_tx = self.nodes[0].createrawtransaction(inputs=[], outputs=outputs) raw_tx = self.nodes[0].createrawtransaction(inputs=[], outputs=outputs)
for fee_setting in ['-minrelaytxfee=0.01', '-mintxfee=0.01', '-paytxfee=0.01']: for fee_setting in ['-minrelaytxfee=0.01', '-mintxfee=0.01']:
self.log.info('Check maxtxfee in combination with {}'.format(fee_setting)) self.log.info('Check maxtxfee in combination with {}'.format(fee_setting))
self.restart_node(0, extra_args=[fee_setting]) self.restart_node(0, extra_args=[fee_setting])
assert_raises_rpc_error( assert_raises_rpc_error(
@@ -68,20 +69,21 @@ class CreateTxWalletTest(BitcoinTestFramework):
lambda: self.nodes[0].fundrawtransaction(hexstring=raw_tx), lambda: self.nodes[0].fundrawtransaction(hexstring=raw_tx),
) )
self.log.info('Check maxtxfee in combination with settxfee') # Hit maxtxfee with explicit fee rate
self.restart_node(0, expected_stderr='Warning: -paytxfee is deprecated and will be fully removed in v31.0.') self.log.info('Check maxtxfee in combination with explicit fee_rate=1000 sat/vB')
self.nodes[0].settxfee(0.01)
fee_rate_sats_per_vb = Decimal('0.01') * Decimal(1e8) / 1000 # Convert 0.01 BTC/kvB to sat/vB
assert_raises_rpc_error( assert_raises_rpc_error(
-6, -6,
"Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)",
lambda: self.nodes[0].sendmany(dummy="", amounts=outputs), lambda: self.nodes[0].sendmany(dummy="", amounts=outputs, fee_rate=fee_rate_sats_per_vb),
) )
assert_raises_rpc_error( assert_raises_rpc_error(
-4, -4,
"Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)",
lambda: self.nodes[0].fundrawtransaction(hexstring=raw_tx), lambda: self.nodes[0].fundrawtransaction(hexstring=raw_tx, options={'fee_rate': fee_rate_sats_per_vb}),
) )
self.nodes[0].settxfee(0)
def test_create_too_long_mempool_chain(self): def test_create_too_long_mempool_chain(self):
self.log.info('Check too-long mempool chain error') self.log.info('Check too-long mempool chain error')
+71 -71
View File
@@ -43,9 +43,9 @@ class RawTransactionsTest(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.num_nodes = 4 self.num_nodes = 4
self.extra_args = [[ self.extra_args = [[
"-deprecatedrpc=settxfee",
"-minrelaytxfee=0.00001000", "-minrelaytxfee=0.00001000",
] for i in range(self.num_nodes)] ] for i in range(self.num_nodes)]
self.setup_clean_chain = True self.setup_clean_chain = True
# whitelist peers to speed up tx relay / mempool sync # whitelist peers to speed up tx relay / mempool sync
self.noban_tx_relay = True self.noban_tx_relay = True
@@ -100,8 +100,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee'] self.min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee']
# This test is not meant to test fee estimation and we'd like # This test is not meant to test fee estimation and we'd like
# to be sure all txs are sent at a consistent desired feerate # to be sure all txs are sent at a consistent desired feerate
for node in self.nodes: self.fee_rate_sats_per_vb = self.min_relay_tx_fee * Decimal(1e8) / 1000
node.settxfee(self.min_relay_tx_fee)
# if the fee's positive delta is higher than this value tests will fail, # if the fee's positive delta is higher than this value tests will fail,
# neg. delta always fail the tests. # neg. delta always fail the tests.
@@ -162,7 +161,7 @@ class RawTransactionsTest(BitcoinTestFramework):
w = self.nodes[1].get_wallet_rpc("fundtx_duplicate_outputs") w = self.nodes[1].get_wallet_rpc("fundtx_duplicate_outputs")
addr = w.getnewaddress(address_type="bech32") addr = w.getnewaddress(address_type="bech32")
self.nodes[0].sendtoaddress(addr, 5) self.nodes[0].sendtoaddress(addr, 5, fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
address = self.nodes[0].getnewaddress("bech32") address = self.nodes[0].getnewaddress("bech32")
@@ -171,14 +170,14 @@ class RawTransactionsTest(BitcoinTestFramework):
tx.vout = [CTxOut(1 * COIN, bytearray(address_to_scriptpubkey(address)))] * 2 tx.vout = [CTxOut(1 * COIN, bytearray(address_to_scriptpubkey(address)))] * 2
tx.nLockTime = 0 tx.nLockTime = 0
tx_hex = tx.serialize().hex() tx_hex = tx.serialize().hex()
res = w.fundrawtransaction(tx_hex, add_inputs=True) res = w.fundrawtransaction(tx_hex, add_inputs=True, fee_rate=self.fee_rate_sats_per_vb)
signed_res = w.signrawtransactionwithwallet(res["hex"]) signed_res = w.signrawtransactionwithwallet(res["hex"])
txid = w.sendrawtransaction(signed_res["hex"]) txid = w.sendrawtransaction(signed_res["hex"])
assert self.nodes[1].getrawtransaction(txid) assert self.nodes[1].getrawtransaction(txid)
self.log.info("Test SFFO with duplicate outputs") self.log.info("Test SFFO with duplicate outputs")
res_sffo = w.fundrawtransaction(tx_hex, add_inputs=True, subtractFeeFromOutputs=[0,1]) res_sffo = w.fundrawtransaction(tx_hex, add_inputs=True, subtractFeeFromOutputs=[0,1], fee_rate=self.fee_rate_sats_per_vb)
signed_res_sffo = w.signrawtransactionwithwallet(res_sffo["hex"]) signed_res_sffo = w.signrawtransactionwithwallet(res_sffo["hex"])
txid_sffo = w.sendrawtransaction(signed_res_sffo["hex"]) txid_sffo = w.sendrawtransaction(signed_res_sffo["hex"])
assert self.nodes[1].getrawtransaction(txid_sffo) assert self.nodes[1].getrawtransaction(txid_sffo)
@@ -187,7 +186,7 @@ class RawTransactionsTest(BitcoinTestFramework):
"""Ensure setting changePosition in fundraw with an exact match is handled properly.""" """Ensure setting changePosition in fundraw with an exact match is handled properly."""
self.log.info("Test fundrawtxn changePosition option") self.log.info("Test fundrawtxn changePosition option")
rawmatch = self.nodes[2].createrawtransaction([], {self.nodes[2].getnewaddress():50}) rawmatch = self.nodes[2].createrawtransaction([], {self.nodes[2].getnewaddress():50})
rawmatch = self.nodes[2].fundrawtransaction(rawmatch, changePosition=1, subtractFeeFromOutputs=[0]) rawmatch = self.nodes[2].fundrawtransaction(rawmatch, changePosition=1, subtractFeeFromOutputs=[0], fee_rate=self.fee_rate_sats_per_vb)
assert_equal(rawmatch["changepos"], -1) assert_equal(rawmatch["changepos"], -1)
self.nodes[3].createwallet(wallet_name="wwatch", disable_private_keys=True) self.nodes[3].createwallet(wallet_name="wwatch", disable_private_keys=True)
@@ -201,11 +200,11 @@ class RawTransactionsTest(BitcoinTestFramework):
# Lock UTXO so nodes[0] doesn't accidentally spend it # Lock UTXO so nodes[0] doesn't accidentally spend it
self.nodes[0].lockunspent(False, [self.watchonly_utxo]) self.nodes[0].lockunspent(False, [self.watchonly_utxo])
self.nodes[0].sendtoaddress(self.nodes[3].get_wallet_rpc(self.default_wallet_name).getnewaddress(), self.watchonly_amount / 10) self.nodes[0].sendtoaddress(self.nodes[3].get_wallet_rpc(self.default_wallet_name).getnewaddress(), self.watchonly_amount / 10, fee_rate=self.fee_rate_sats_per_vb)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5) self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5, fee_rate=self.fee_rate_sats_per_vb)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0) self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0, fee_rate=self.fee_rate_sats_per_vb)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 5.0) self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 5.0, fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
@@ -216,7 +215,7 @@ class RawTransactionsTest(BitcoinTestFramework):
inputs = [ ] inputs = [ ]
outputs = { self.nodes[0].getnewaddress() : 1.0 } outputs = { self.nodes[0].getnewaddress() : 1.0 }
rawtx = self.nodes[2].createrawtransaction(inputs, outputs) rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
rawtxfund = self.nodes[2].fundrawtransaction(rawtx) rawtxfund = self.nodes[2].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
assert len(dec_tx['vin']) > 0 #test that we have enough inputs assert len(dec_tx['vin']) > 0 #test that we have enough inputs
@@ -225,7 +224,7 @@ class RawTransactionsTest(BitcoinTestFramework):
inputs = [ ] inputs = [ ]
outputs = { self.nodes[0].getnewaddress() : 2.2 } outputs = { self.nodes[0].getnewaddress() : 2.2 }
rawtx = self.nodes[2].createrawtransaction(inputs, outputs) rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
rawtxfund = self.nodes[2].fundrawtransaction(rawtx) rawtxfund = self.nodes[2].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
assert len(dec_tx['vin']) > 0 #test if we have enough inputs assert len(dec_tx['vin']) > 0 #test if we have enough inputs
assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')
@@ -237,7 +236,7 @@ class RawTransactionsTest(BitcoinTestFramework):
outputs = { self.nodes[0].getnewaddress() : 2.6, self.nodes[1].getnewaddress() : 2.5 } outputs = { self.nodes[0].getnewaddress() : 2.6, self.nodes[1].getnewaddress() : 2.5 }
rawtx = self.nodes[2].createrawtransaction(inputs, outputs) rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
rawtxfund = self.nodes[2].fundrawtransaction(rawtx) rawtxfund = self.nodes[2].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
assert len(dec_tx['vin']) > 0 assert len(dec_tx['vin']) > 0
@@ -253,7 +252,7 @@ class RawTransactionsTest(BitcoinTestFramework):
dec_tx = self.nodes[2].decoderawtransaction(rawtx) dec_tx = self.nodes[2].decoderawtransaction(rawtx)
assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
rawtxfund = self.nodes[2].fundrawtransaction(rawtx) rawtxfund = self.nodes[2].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
fee = rawtxfund['fee'] fee = rawtxfund['fee']
self.test_no_change_fee = fee # Use the same fee for the next tx self.test_no_change_fee = fee # Use the same fee for the next tx
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
@@ -273,7 +272,7 @@ class RawTransactionsTest(BitcoinTestFramework):
dec_tx = self.nodes[2].decoderawtransaction(rawtx) dec_tx = self.nodes[2].decoderawtransaction(rawtx)
assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
rawtxfund = self.nodes[2].fundrawtransaction(rawtx) rawtxfund = self.nodes[2].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
fee = rawtxfund['fee'] fee = rawtxfund['fee']
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
totalOut = 0 totalOut = 0
@@ -322,7 +321,7 @@ class RawTransactionsTest(BitcoinTestFramework):
change = self.nodes[2].getnewaddress() change = self.nodes[2].getnewaddress()
assert_raises_rpc_error(-8, "changePosition out of bounds", self.nodes[2].fundrawtransaction, rawtx, changeAddress=change, changePosition=2) assert_raises_rpc_error(-8, "changePosition out of bounds", self.nodes[2].fundrawtransaction, rawtx, changeAddress=change, changePosition=2)
rawtxfund = self.nodes[2].fundrawtransaction(rawtx, changeAddress=change, changePosition=0) rawtxfund = self.nodes[2].fundrawtransaction(rawtx, changeAddress=change, changePosition=0, fee_rate=self.fee_rate_sats_per_vb)
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
out = dec_tx['vout'][0] out = dec_tx['vout'][0]
assert_equal(change, out['scriptPubKey']['address']) assert_equal(change, out['scriptPubKey']['address'])
@@ -336,7 +335,7 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtx = self.nodes[2].createrawtransaction(inputs, outputs) rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
assert_raises_rpc_error(-3, "JSON value of type null is not of expected type string", self.nodes[2].fundrawtransaction, rawtx, change_type=None) assert_raises_rpc_error(-3, "JSON value of type null is not of expected type string", self.nodes[2].fundrawtransaction, rawtx, change_type=None)
assert_raises_rpc_error(-5, "Unknown change type ''", self.nodes[2].fundrawtransaction, rawtx, change_type='') assert_raises_rpc_error(-5, "Unknown change type ''", self.nodes[2].fundrawtransaction, rawtx, change_type='')
rawtx = self.nodes[2].fundrawtransaction(rawtx, change_type='bech32') rawtx = self.nodes[2].fundrawtransaction(rawtx, change_type='bech32', fee_rate=self.fee_rate_sats_per_vb)
dec_tx = self.nodes[2].decoderawtransaction(rawtx['hex']) dec_tx = self.nodes[2].decoderawtransaction(rawtx['hex'])
assert_equal('witness_v0_keyhash', dec_tx['vout'][rawtx['changepos']]['scriptPubKey']['type']) assert_equal('witness_v0_keyhash', dec_tx['vout'][rawtx['changepos']]['scriptPubKey']['type'])
@@ -358,7 +357,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# Should fail without add_inputs: # Should fail without add_inputs:
assert_raises_rpc_error(-4, ERR_NOT_ENOUGH_PRESET_INPUTS, self.nodes[2].fundrawtransaction, rawtx, add_inputs=False) assert_raises_rpc_error(-4, ERR_NOT_ENOUGH_PRESET_INPUTS, self.nodes[2].fundrawtransaction, rawtx, add_inputs=False)
# add_inputs is enabled by default # add_inputs is enabled by default
rawtxfund = self.nodes[2].fundrawtransaction(rawtx) rawtxfund = self.nodes[2].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
matchingOuts = 0 matchingOuts = 0
@@ -387,7 +386,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# Should fail without add_inputs: # Should fail without add_inputs:
assert_raises_rpc_error(-4, ERR_NOT_ENOUGH_PRESET_INPUTS, self.nodes[2].fundrawtransaction, rawtx, add_inputs=False) assert_raises_rpc_error(-4, ERR_NOT_ENOUGH_PRESET_INPUTS, self.nodes[2].fundrawtransaction, rawtx, add_inputs=False)
rawtxfund = self.nodes[2].fundrawtransaction(rawtx, add_inputs=True) rawtxfund = self.nodes[2].fundrawtransaction(rawtx, add_inputs=True, fee_rate=self.fee_rate_sats_per_vb)
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
matchingOuts = 0 matchingOuts = 0
for out in dec_tx['vout']: for out in dec_tx['vout']:
@@ -418,7 +417,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# Should fail without add_inputs: # Should fail without add_inputs:
assert_raises_rpc_error(-4, ERR_NOT_ENOUGH_PRESET_INPUTS, self.nodes[2].fundrawtransaction, rawtx, add_inputs=False) assert_raises_rpc_error(-4, ERR_NOT_ENOUGH_PRESET_INPUTS, self.nodes[2].fundrawtransaction, rawtx, add_inputs=False)
rawtxfund = self.nodes[2].fundrawtransaction(rawtx, add_inputs=True) rawtxfund = self.nodes[2].fundrawtransaction(rawtx, add_inputs=True, fee_rate=self.fee_rate_sats_per_vb)
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
matchingOuts = 0 matchingOuts = 0
@@ -445,10 +444,10 @@ class RawTransactionsTest(BitcoinTestFramework):
inputs = [] inputs = []
outputs = {self.nodes[1].getnewaddress():1.1} outputs = {self.nodes[1].getnewaddress():1.1}
rawtx = self.nodes[0].createrawtransaction(inputs, outputs) rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
fundedTx = self.nodes[0].fundrawtransaction(rawtx) fundedTx = self.nodes[0].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
# Create same transaction over sendtoaddress. # Create same transaction over sendtoaddress.
txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1.1) txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1.1, fee_rate=self.fee_rate_sats_per_vb)
signedFee = self.nodes[0].getmempoolentry(txId)['fees']['base'] signedFee = self.nodes[0].getmempoolentry(txId)['fees']['base']
# Compare fee. # Compare fee.
@@ -471,10 +470,10 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[1].getnewaddress():0.3, self.nodes[1].getnewaddress():0.3,
} }
rawtx = self.nodes[0].createrawtransaction(inputs, outputs) rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
fundedTx = self.nodes[0].fundrawtransaction(rawtx) fundedTx = self.nodes[0].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
# Create same transaction over sendtoaddress. # Create same transaction over sendtoaddress.
txId = self.nodes[0].sendmany("", outputs) txId = self.nodes[0].sendmany("", outputs, fee_rate=self.fee_rate_sats_per_vb)
signedFee = self.nodes[0].getmempoolentry(txId)['fees']['base'] signedFee = self.nodes[0].getmempoolentry(txId)['fees']['base']
# Compare fee. # Compare fee.
@@ -498,10 +497,10 @@ class RawTransactionsTest(BitcoinTestFramework):
inputs = [] inputs = []
outputs = {mSigObj:1.1} outputs = {mSigObj:1.1}
rawtx = self.nodes[0].createrawtransaction(inputs, outputs) rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
fundedTx = self.nodes[0].fundrawtransaction(rawtx) fundedTx = self.nodes[0].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
# Create same transaction over sendtoaddress. # Create same transaction over sendtoaddress.
txId = self.nodes[0].sendtoaddress(mSigObj, 1.1) txId = self.nodes[0].sendtoaddress(mSigObj, 1.1, fee_rate=self.fee_rate_sats_per_vb)
signedFee = self.nodes[0].getmempoolentry(txId)['fees']['base'] signedFee = self.nodes[0].getmempoolentry(txId)['fees']['base']
# Compare fee. # Compare fee.
@@ -542,10 +541,10 @@ class RawTransactionsTest(BitcoinTestFramework):
inputs = [] inputs = []
outputs = {mSigObj:1.1} outputs = {mSigObj:1.1}
rawtx = self.nodes[0].createrawtransaction(inputs, outputs) rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
fundedTx = self.nodes[0].fundrawtransaction(rawtx) fundedTx = self.nodes[0].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
# Create same transaction over sendtoaddress. # Create same transaction over sendtoaddress.
txId = self.nodes[0].sendtoaddress(mSigObj, 1.1) txId = self.nodes[0].sendtoaddress(mSigObj, 1.1, fee_rate=self.fee_rate_sats_per_vb)
signedFee = self.nodes[0].getmempoolentry(txId)['fees']['base'] signedFee = self.nodes[0].getmempoolentry(txId)['fees']['base']
# Compare fee. # Compare fee.
@@ -579,7 +578,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(import_res[0]["success"], True) assert_equal(import_res[0]["success"], True)
# Send 1.2 BTC to msig addr. # Send 1.2 BTC to msig addr.
self.nodes[0].sendtoaddress(mSigObj["address"], 1.2) self.nodes[0].sendtoaddress(mSigObj["address"], 1.2, fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
oldBalance = self.nodes[1].getbalance() oldBalance = self.nodes[1].getbalance()
@@ -602,8 +601,6 @@ class RawTransactionsTest(BitcoinTestFramework):
df_wallet = self.nodes[1].get_wallet_rpc(self.default_wallet_name) df_wallet = self.nodes[1].get_wallet_rpc(self.default_wallet_name)
self.nodes[1].createwallet(wallet_name="locked_wallet") self.nodes[1].createwallet(wallet_name="locked_wallet")
wallet = self.nodes[1].get_wallet_rpc("locked_wallet") wallet = self.nodes[1].get_wallet_rpc("locked_wallet")
# This test is not meant to exercise fee estimation. Making sure all txs are sent at a consistent fee rate.
wallet.settxfee(self.min_relay_tx_fee)
# Add some balance to the wallet (this will be reverted at the end of the test) # Add some balance to the wallet (this will be reverted at the end of the test)
df_wallet.sendall(recipients=[wallet.getnewaddress()]) df_wallet.sendall(recipients=[wallet.getnewaddress()])
@@ -639,7 +636,7 @@ class RawTransactionsTest(BitcoinTestFramework):
outputs = {self.nodes[0].getnewaddress():value} outputs = {self.nodes[0].getnewaddress():value}
rawtx = wallet.createrawtransaction(inputs, outputs) rawtx = wallet.createrawtransaction(inputs, outputs)
# fund a transaction that does not require a new key for the change output # fund a transaction that does not require a new key for the change output
funded_tx = wallet.fundrawtransaction(rawtx) funded_tx = wallet.fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
assert_equal(funded_tx["changepos"], -1) assert_equal(funded_tx["changepos"], -1)
# fund a transaction that requires a new key for the change output # fund a transaction that requires a new key for the change output
@@ -659,7 +656,8 @@ class RawTransactionsTest(BitcoinTestFramework):
inputs = [] inputs = []
outputs = {self.nodes[0].getnewaddress():1.1} outputs = {self.nodes[0].getnewaddress():1.1}
rawtx = wallet.createrawtransaction(inputs, outputs) rawtx = wallet.createrawtransaction(inputs, outputs)
fundedTx = wallet.fundrawtransaction(rawtx)
fundedTx = wallet.fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
assert_not_equal(fundedTx["changepos"], -1) assert_not_equal(fundedTx["changepos"], -1)
# Now we need to unlock. # Now we need to unlock.
@@ -672,7 +670,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(oldBalance+Decimal('51.10000000'), self.nodes[0].getbalance()) assert_equal(oldBalance+Decimal('51.10000000'), self.nodes[0].getbalance())
# Restore pre-test wallet state # Restore pre-test wallet state
wallet.sendall(recipients=[df_wallet.getnewaddress(), df_wallet.getnewaddress(), df_wallet.getnewaddress()]) wallet.sendall(recipients=[df_wallet.getnewaddress(), df_wallet.getnewaddress(), df_wallet.getnewaddress()], fee_rate=self.fee_rate_sats_per_vb)
wallet.unloadwallet() wallet.unloadwallet()
self.generate(self.nodes[1], 1) self.generate(self.nodes[1], 1)
@@ -681,21 +679,21 @@ class RawTransactionsTest(BitcoinTestFramework):
self.log.info("Test fundrawtxn fee with many inputs") self.log.info("Test fundrawtxn fee with many inputs")
# Empty node1, send some small coins from node0 to node1. # Empty node1, send some small coins from node0 to node1.
self.nodes[1].sendall(recipients=[self.nodes[0].getnewaddress()]) self.nodes[1].sendall(recipients=[self.nodes[0].getnewaddress()], fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[1], 1) self.generate(self.nodes[1], 1)
for _ in range(20): for _ in range(20):
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01) self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01, fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
# Fund a tx with ~20 small inputs. # Fund a tx with ~20 small inputs.
inputs = [] inputs = []
outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04} outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04}
rawtx = self.nodes[1].createrawtransaction(inputs, outputs) rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
fundedTx = self.nodes[1].fundrawtransaction(rawtx) fundedTx = self.nodes[1].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
# Create same transaction over sendtoaddress. # Create same transaction over sendtoaddress.
txId = self.nodes[1].sendmany("", outputs) txId = self.nodes[1].sendmany("", outputs, fee_rate=self.fee_rate_sats_per_vb)
signedFee = self.nodes[1].getmempoolentry(txId)['fees']['base'] signedFee = self.nodes[1].getmempoolentry(txId)['fees']['base']
# Compare fee. # Compare fee.
@@ -707,11 +705,11 @@ class RawTransactionsTest(BitcoinTestFramework):
self.log.info("Test fundrawtxn sign+send with many inputs") self.log.info("Test fundrawtxn sign+send with many inputs")
# Again, empty node1, send some small coins from node0 to node1. # Again, empty node1, send some small coins from node0 to node1.
self.nodes[1].sendall(recipients=[self.nodes[0].getnewaddress()]) self.nodes[1].sendall(recipients=[self.nodes[0].getnewaddress()], fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[1], 1) self.generate(self.nodes[1], 1)
for _ in range(20): for _ in range(20):
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01) self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01, fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
# Fund a tx with ~20 small inputs. # Fund a tx with ~20 small inputs.
@@ -720,7 +718,7 @@ class RawTransactionsTest(BitcoinTestFramework):
inputs = [] inputs = []
outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04} outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04}
rawtx = self.nodes[1].createrawtransaction(inputs, outputs) rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
fundedTx = self.nodes[1].fundrawtransaction(rawtx) fundedTx = self.nodes[1].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
fundedAndSignedTx = self.nodes[1].signrawtransactionwithwallet(fundedTx['hex']) fundedAndSignedTx = self.nodes[1].signrawtransactionwithwallet(fundedTx['hex'])
self.nodes[1].sendrawtransaction(fundedAndSignedTx['hex']) self.nodes[1].sendrawtransaction(fundedAndSignedTx['hex'])
self.generate(self.nodes[1], 1) self.generate(self.nodes[1], 1)
@@ -735,7 +733,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(len(dec_tx['vin']), 0) assert_equal(len(dec_tx['vin']), 0)
assert_equal(len(dec_tx['vout']), 1) assert_equal(len(dec_tx['vout']), 1)
rawtxfund = self.nodes[2].fundrawtransaction(rawtx) rawtxfund = self.nodes[2].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
assert_greater_than(len(dec_tx['vin']), 0) # at least one vin assert_greater_than(len(dec_tx['vin']), 0) # at least one vin
@@ -810,7 +808,7 @@ class RawTransactionsTest(BitcoinTestFramework):
outputs = {node.getnewaddress() : 1} outputs = {node.getnewaddress() : 1}
rawtx = node.createrawtransaction(inputs, outputs) rawtx = node.createrawtransaction(inputs, outputs)
result = node.fundrawtransaction(rawtx) # uses self.min_relay_tx_fee (set by settxfee) result = node.fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb) # uses self.min_relay_tx_fee (set by fee_rate in sat/vB)
btc_kvb_to_sat_vb = 100000 # (1e5) btc_kvb_to_sat_vb = 100000 # (1e5)
result1 = node.fundrawtransaction(rawtx, fee_rate=str(2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee)) result1 = node.fundrawtransaction(rawtx, fee_rate=str(2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee))
result2 = node.fundrawtransaction(rawtx, feeRate=2 * self.min_relay_tx_fee) result2 = node.fundrawtransaction(rawtx, feeRate=2 * self.min_relay_tx_fee)
@@ -828,7 +826,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(self.nodes[3].fundrawtransaction(rawtx, {param: zero_value})["fee"], 0) assert_equal(self.nodes[3].fundrawtransaction(rawtx, {param: zero_value})["fee"], 0)
# With no arguments passed, expect fee of 141 satoshis. # With no arguments passed, expect fee of 141 satoshis.
assert_approx(node.fundrawtransaction(rawtx)["fee"], vexp=0.00000141, vspan=0.00000001) assert_approx(node.fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb)["fee"], vexp=0.00000141, vspan=0.00000001)
# Expect fee to be 10,000x higher when an explicit fee rate 10,000x greater is specified. # Expect fee to be 10,000x higher when an explicit fee rate 10,000x greater is specified.
result = node.fundrawtransaction(rawtx, fee_rate=10000) result = node.fundrawtransaction(rawtx, fee_rate=10000)
assert_approx(result["fee"], vexp=0.0141, vspan=0.0001) assert_approx(result["fee"], vexp=0.0141, vspan=0.0001)
@@ -916,9 +914,9 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtx = self.nodes[3].createrawtransaction(inputs, outputs) rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
# Test subtract fee from outputs with feeRate (BTC/kvB) # Test subtract fee from outputs with feeRate (BTC/kvB)
result = [self.nodes[3].fundrawtransaction(rawtx), # uses self.min_relay_tx_fee (set by settxfee) result = [self.nodes[3].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb),
self.nodes[3].fundrawtransaction(rawtx, subtractFeeFromOutputs=[]), # empty subtraction list self.nodes[3].fundrawtransaction(rawtx, subtractFeeFromOutputs=[], fee_rate=self.fee_rate_sats_per_vb), # empty subtraction list
self.nodes[3].fundrawtransaction(rawtx, subtractFeeFromOutputs=[0]), # uses self.min_relay_tx_fee (set by settxfee) self.nodes[3].fundrawtransaction(rawtx, subtractFeeFromOutputs=[0], fee_rate=self.fee_rate_sats_per_vb), # uses self.min_relay_tx_fee (set by fee_rate in sat/vB)
self.nodes[3].fundrawtransaction(rawtx, feeRate=2 * self.min_relay_tx_fee), self.nodes[3].fundrawtransaction(rawtx, feeRate=2 * self.min_relay_tx_fee),
self.nodes[3].fundrawtransaction(rawtx, feeRate=2 * self.min_relay_tx_fee, subtractFeeFromOutputs=[0]),] self.nodes[3].fundrawtransaction(rawtx, feeRate=2 * self.min_relay_tx_fee, subtractFeeFromOutputs=[0]),]
dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result] dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result]
@@ -936,9 +934,9 @@ class RawTransactionsTest(BitcoinTestFramework):
# Test subtract fee from outputs with fee_rate (sat/vB) # Test subtract fee from outputs with fee_rate (sat/vB)
btc_kvb_to_sat_vb = 100000 # (1e5) btc_kvb_to_sat_vb = 100000 # (1e5)
result = [self.nodes[3].fundrawtransaction(rawtx), # uses self.min_relay_tx_fee (set by settxfee) result = [self.nodes[3].fundrawtransaction(rawtx, fee_rate=self.fee_rate_sats_per_vb), # uses self.min_relay_tx_fee (set by fee_rate in sat/vB)
self.nodes[3].fundrawtransaction(rawtx, subtractFeeFromOutputs=[]), # empty subtraction list self.nodes[3].fundrawtransaction(rawtx, subtractFeeFromOutputs=[], fee_rate=self.fee_rate_sats_per_vb), # empty subtraction list
self.nodes[3].fundrawtransaction(rawtx, subtractFeeFromOutputs=[0]), # uses self.min_relay_tx_fee (set by settxfee) self.nodes[3].fundrawtransaction(rawtx, subtractFeeFromOutputs=[0], fee_rate=self.fee_rate_sats_per_vb), # uses self.min_relay_tx_fee (set by fee_rate in sat/vB)
self.nodes[3].fundrawtransaction(rawtx, fee_rate=2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee), self.nodes[3].fundrawtransaction(rawtx, fee_rate=2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee),
self.nodes[3].fundrawtransaction(rawtx, fee_rate=2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee, subtractFeeFromOutputs=[0]),] self.nodes[3].fundrawtransaction(rawtx, fee_rate=2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee, subtractFeeFromOutputs=[0]),]
dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result] dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result]
@@ -1001,7 +999,7 @@ class RawTransactionsTest(BitcoinTestFramework):
utxo = self.create_outpoints(self.nodes[0], outputs=[{addr: 10}])[0] utxo = self.create_outpoints(self.nodes[0], outputs=[{addr: 10}])[0]
rawtx = self.nodes[0].createrawtransaction([utxo], [{self.nodes[0].getnewaddress(): 5}]) rawtx = self.nodes[0].createrawtransaction([utxo], [{self.nodes[0].getnewaddress(): 5}])
fundedtx = self.nodes[0].fundrawtransaction(rawtx, subtractFeeFromOutputs=[0]) fundedtx = self.nodes[0].fundrawtransaction(rawtx, subtractFeeFromOutputs=[0], fee_rate=self.fee_rate_sats_per_vb)
signedtx = self.nodes[0].signrawtransactionwithwallet(fundedtx['hex']) signedtx = self.nodes[0].signrawtransactionwithwallet(fundedtx['hex'])
self.nodes[0].sendrawtransaction(signedtx['hex']) self.nodes[0].sendrawtransaction(signedtx['hex'])
@@ -1022,7 +1020,7 @@ class RawTransactionsTest(BitcoinTestFramework):
recipient.keypoolrefill(1500) recipient.keypoolrefill(1500)
for _ in range(1500): for _ in range(1500):
outputs[recipient.getnewaddress()] = 0.1 outputs[recipient.getnewaddress()] = 0.1
wallet.sendmany("", outputs) wallet.sendmany("", outputs, fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[0], 10) self.generate(self.nodes[0], 10)
assert_raises_rpc_error(-4, "The inputs size exceeds the maximum weight. " assert_raises_rpc_error(-4, "The inputs size exceeds the maximum weight. "
"Please try sending a smaller amount or manually consolidating your wallet's UTXOs", "Please try sending a smaller amount or manually consolidating your wallet's UTXOs",
@@ -1042,8 +1040,8 @@ class RawTransactionsTest(BitcoinTestFramework):
addr = self.nodes[0].deriveaddresses(desc)[0] addr = self.nodes[0].deriveaddresses(desc)[0]
addr_info = self.nodes[0].getaddressinfo(addr) addr_info = self.nodes[0].getaddressinfo(addr)
self.nodes[0].sendtoaddress(addr, 10) self.nodes[0].sendtoaddress(addr, 10, fee_rate=self.fee_rate_sats_per_vb)
self.nodes[0].sendtoaddress(wallet.getnewaddress(), 10) self.nodes[0].sendtoaddress(wallet.getnewaddress(), 10, fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[0], 6) self.generate(self.nodes[0], 6)
ext_utxo = self.nodes[0].listunspent(addresses=[addr])[0] ext_utxo = self.nodes[0].listunspent(addresses=[addr])[0]
@@ -1070,7 +1068,7 @@ class RawTransactionsTest(BitcoinTestFramework):
signed_tx = self.nodes[0].signrawtransactionwithwallet(signed_tx['hex']) signed_tx = self.nodes[0].signrawtransactionwithwallet(signed_tx['hex'])
assert signed_tx['complete'] assert signed_tx['complete']
funded_tx = wallet.fundrawtransaction(raw_tx, solving_data={"descriptors": [desc]}) funded_tx = wallet.fundrawtransaction(raw_tx, solving_data={"descriptors": [desc]}, fee_rate=self.fee_rate_sats_per_vb)
signed_tx1 = wallet.signrawtransactionwithwallet(funded_tx['hex']) signed_tx1 = wallet.signrawtransactionwithwallet(funded_tx['hex'])
assert not signed_tx1['complete'] assert not signed_tx1['complete']
signed_tx2 = self.nodes[0].signrawtransactionwithwallet(signed_tx1['hex']) signed_tx2 = self.nodes[0].signrawtransactionwithwallet(signed_tx1['hex'])
@@ -1119,7 +1117,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[2].createwallet("test_preset_inputs") self.nodes[2].createwallet("test_preset_inputs")
wallet = self.nodes[2].get_wallet_rpc("test_preset_inputs") wallet = self.nodes[2].get_wallet_rpc("test_preset_inputs")
addr1 = wallet.getnewaddress(address_type="bech32") addr1 = wallet.getnewaddress(address_type="bech32")
self.nodes[0].sendtoaddress(addr1, 5) self.nodes[0].sendtoaddress(addr1, 5, fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
# Covered cases: # Covered cases:
@@ -1139,7 +1137,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# Case (1), 'send' command # Case (1), 'send' command
# 'add_inputs' value is true unless "inputs" are specified, in such case, add_inputs=false. # 'add_inputs' value is true unless "inputs" are specified, in such case, add_inputs=false.
# So, the wallet will automatically select coins and create the transaction if only the outputs are provided. # So, the wallet will automatically select coins and create the transaction if only the outputs are provided.
tx = wallet.send(outputs=[{addr1: 3}]) tx = wallet.send(outputs=[{addr1: 3}], fee_rate=self.fee_rate_sats_per_vb)
assert tx["complete"] assert tx["complete"]
# Case (2), 'send' command # Case (2), 'send' command
@@ -1148,7 +1146,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# Fund wallet with 2 outputs, 5 BTC each. # Fund wallet with 2 outputs, 5 BTC each.
addr2 = wallet.getnewaddress(address_type="bech32") addr2 = wallet.getnewaddress(address_type="bech32")
source_tx = self.nodes[0].send(outputs=[{addr1: 5}, {addr2: 5}], change_position=0) source_tx = self.nodes[0].send(outputs=[{addr1: 5}, {addr2: 5}], change_position=0, fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
# Select only one input. # Select only one input.
@@ -1165,6 +1163,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# Case (3), Explicit add_inputs=true and preset inputs (with preset inputs not-covering the target amount) # Case (3), Explicit add_inputs=true and preset inputs (with preset inputs not-covering the target amount)
options["add_inputs"] = True options["add_inputs"] = True
options["add_to_wallet"] = False options["add_to_wallet"] = False
options["fee_rate"] = self.fee_rate_sats_per_vb
tx = wallet.send(outputs=[{addr1: 8}], **options) tx = wallet.send(outputs=[{addr1: 8}], **options)
assert tx["complete"] assert tx["complete"]
@@ -1196,7 +1195,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# Default add_inputs value with no preset inputs (add_inputs=true) # Default add_inputs value with no preset inputs (add_inputs=true)
inputs = [] inputs = []
outputs = {self.nodes[1].getnewaddress(): 8} outputs = {self.nodes[1].getnewaddress(): 8}
assert "psbt" in wallet.walletcreatefundedpsbt(inputs=inputs, outputs=outputs) assert "psbt" in wallet.walletcreatefundedpsbt(inputs=inputs, outputs=outputs, options={'fee_rate': self.fee_rate_sats_per_vb})
# Case (2), 'walletcreatefundedpsbt' command # Case (2), 'walletcreatefundedpsbt' command
# Default add_inputs value with preset inputs (add_inputs=false). # Default add_inputs value with preset inputs (add_inputs=false).
@@ -1205,7 +1204,7 @@ class RawTransactionsTest(BitcoinTestFramework):
"vout": 1 # change position was hardcoded to index 0 "vout": 1 # change position was hardcoded to index 0
}] }]
outputs = {self.nodes[1].getnewaddress(): 8} outputs = {self.nodes[1].getnewaddress(): 8}
assert_raises_rpc_error(-4, ERR_NOT_ENOUGH_PRESET_INPUTS, wallet.walletcreatefundedpsbt, inputs=inputs, outputs=outputs) assert_raises_rpc_error(-4, ERR_NOT_ENOUGH_PRESET_INPUTS, wallet.walletcreatefundedpsbt, inputs=inputs, outputs=outputs, options={'fee_rate': self.fee_rate_sats_per_vb})
# Case (3), Explicit add_inputs=true and preset inputs (with preset inputs not-covering the target amount) # Case (3), Explicit add_inputs=true and preset inputs (with preset inputs not-covering the target amount)
options["add_inputs"] = True options["add_inputs"] = True
@@ -1226,7 +1225,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# Case (5), 'walletcreatefundedpsbt' command # Case (5), 'walletcreatefundedpsbt' command
# Explicit add_inputs=true, no preset inputs # Explicit add_inputs=true, no preset inputs
options = { options = {
"add_inputs": True "add_inputs": True,
} }
assert "psbt" in wallet.walletcreatefundedpsbt(inputs=[], outputs=outputs, **options) assert "psbt" in wallet.walletcreatefundedpsbt(inputs=[], outputs=outputs, **options)
@@ -1245,7 +1244,7 @@ class RawTransactionsTest(BitcoinTestFramework):
outputs = {} outputs = {}
for _ in range(4): for _ in range(4):
outputs[wallet.getnewaddress(address_type="bech32")] = 5 outputs[wallet.getnewaddress(address_type="bech32")] = 5
self.nodes[0].sendmany("", outputs) self.nodes[0].sendmany("", outputs, fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
# Select the preset inputs # Select the preset inputs
@@ -1257,7 +1256,8 @@ class RawTransactionsTest(BitcoinTestFramework):
"inputs": preset_inputs, "inputs": preset_inputs,
"add_inputs": True, # automatically add coins from the wallet to fulfill the target "add_inputs": True, # automatically add coins from the wallet to fulfill the target
"subtract_fee_from_outputs": [0], # deduct fee from first output "subtract_fee_from_outputs": [0], # deduct fee from first output
"add_to_wallet": False "add_to_wallet": False,
"fee_rate": self.fee_rate_sats_per_vb
} }
# Attempt to send 29 BTC from a wallet that only has 20 BTC. The wallet should exclude # Attempt to send 29 BTC from a wallet that only has 20 BTC. The wallet should exclude
@@ -1290,7 +1290,7 @@ class RawTransactionsTest(BitcoinTestFramework):
ext_addr = self.nodes[0].getnewaddress(address_type="bech32") ext_addr = self.nodes[0].getnewaddress(address_type="bech32")
utxo, ext_utxo = self.create_outpoints(self.nodes[0], outputs=[{addr: 5}, {ext_addr: 5}]) utxo, ext_utxo = self.create_outpoints(self.nodes[0], outputs=[{addr: 5}, {ext_addr: 5}])
self.nodes[0].sendtoaddress(wallet.getnewaddress(address_type="bech32"), 5) self.nodes[0].sendtoaddress(wallet.getnewaddress(address_type="bech32"), 5, fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
rawtx = wallet.createrawtransaction([utxo], [{self.nodes[0].getnewaddress(address_type="bech32"): 8}]) rawtx = wallet.createrawtransaction([utxo], [{self.nodes[0].getnewaddress(address_type="bech32"): 8}])
@@ -1319,7 +1319,7 @@ class RawTransactionsTest(BitcoinTestFramework):
outputs = [] outputs = []
for _ in range(1472): for _ in range(1472):
outputs.append({wallet.getnewaddress(address_type="legacy"): 0.1}) outputs.append({wallet.getnewaddress(address_type="legacy"): 0.1})
txid = self.nodes[0].send(outputs=outputs, change_position=0)["txid"] txid = self.nodes[0].send(outputs=outputs, change_position=0, fee_rate=self.fee_rate_sats_per_vb)["txid"]
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
# 272 WU per input (273 when high-s); picking 1471 inputs will exceed the max standard tx weight. # 272 WU per input (273 when high-s); picking 1471 inputs will exceed the max standard tx weight.
@@ -1361,7 +1361,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_raises_rpc_error(-4, "Insufficient funds", wallet.fundrawtransaction, rawtx) assert_raises_rpc_error(-4, "Insufficient funds", wallet.fundrawtransaction, rawtx)
# But we can opt-in to use them for funding. # But we can opt-in to use them for funding.
fundedtx = wallet.fundrawtransaction(rawtx, include_unsafe=True) fundedtx = wallet.fundrawtransaction(rawtx, include_unsafe=True, fee_rate=self.fee_rate_sats_per_vb)
tx_dec = wallet.decoderawtransaction(fundedtx['hex']) tx_dec = wallet.decoderawtransaction(fundedtx['hex'])
assert all((txin["txid"], txin["vout"]) in inputs for txin in tx_dec["vin"]) assert all((txin["txid"], txin["vout"]) in inputs for txin in tx_dec["vin"])
signedtx = wallet.signrawtransactionwithwallet(fundedtx['hex']) signedtx = wallet.signrawtransactionwithwallet(fundedtx['hex'])
@@ -1369,7 +1369,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# And we can also use them once they're confirmed. # And we can also use them once they're confirmed.
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
fundedtx = wallet.fundrawtransaction(rawtx, include_unsafe=False) fundedtx = wallet.fundrawtransaction(rawtx, include_unsafe=False, fee_rate=self.fee_rate_sats_per_vb)
tx_dec = wallet.decoderawtransaction(fundedtx['hex']) tx_dec = wallet.decoderawtransaction(fundedtx['hex'])
assert all((txin["txid"], txin["vout"]) in inputs for txin in tx_dec["vin"]) assert all((txin["txid"], txin["vout"]) in inputs for txin in tx_dec["vin"])
signedtx = wallet.signrawtransactionwithwallet(fundedtx['hex']) signedtx = wallet.signrawtransactionwithwallet(fundedtx['hex'])
@@ -1443,7 +1443,7 @@ class RawTransactionsTest(BitcoinTestFramework):
w = self.nodes[1].get_wallet_rpc("roundtest") w = self.nodes[1].get_wallet_rpc("roundtest")
addr = w.getnewaddress(address_type="bech32") addr = w.getnewaddress(address_type="bech32")
self.nodes[0].sendtoaddress(addr, 1) self.nodes[0].sendtoaddress(addr, 1, fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
# A P2WPKH input costs 68 vbytes; With a single P2WPKH output, the rest of the tx is 42 vbytes for a total of 110 vbytes. # A P2WPKH input costs 68 vbytes; With a single P2WPKH output, the rest of the tx is 42 vbytes for a total of 110 vbytes.
@@ -1464,10 +1464,10 @@ class RawTransactionsTest(BitcoinTestFramework):
# Fund the wallet with different chain heights # Fund the wallet with different chain heights
for _ in range(2): for _ in range(2):
self.nodes[2].sendmany("", {wallet.getnewaddress():1, wallet.getnewaddress():1}) self.nodes[2].sendmany("", {wallet.getnewaddress():1, wallet.getnewaddress():1}, fee_rate=self.fee_rate_sats_per_vb)
self.generate(self.nodes[2], 1) self.generate(self.nodes[2], 1)
unconfirmed_txid = wallet.sendtoaddress(wallet.getnewaddress(), 0.5) unconfirmed_txid = wallet.sendtoaddress(wallet.getnewaddress(), 0.5, fee_rate=self.fee_rate_sats_per_vb)
self.log.info("Crafting TX using an unconfirmed input") self.log.info("Crafting TX using an unconfirmed input")
target_address = self.nodes[2].getnewaddress() target_address = self.nodes[2].getnewaddress()
+15 -16
View File
@@ -29,8 +29,7 @@ class WalletGroupTest(BitcoinTestFramework):
["-maxapsfee=0.00002720"], ["-maxapsfee=0.00002720"],
] ]
for args in self.extra_args: self.fee_rate = 20 # apply feerate of 20 sats/vB across all nodes
args.append(f"-paytxfee={20 * 1e3 / 1e8}") # apply feerate of 20 sats/vB across all nodes
self.rpc_timeout = 480 self.rpc_timeout = 480
@@ -48,8 +47,8 @@ class WalletGroupTest(BitcoinTestFramework):
addrs = addr1 + addr2 addrs = addr1 + addr2
# Send 1 + 0.5 coin to each address # Send 1 + 0.5 coin to each address
[self.nodes[0].sendtoaddress(addr, 1.0) for addr in addrs] [self.nodes[0].sendtoaddress(addr, 1.0, fee_rate=self.fee_rate) for addr in addrs]
[self.nodes[0].sendtoaddress(addr, 0.5) for addr in addrs] [self.nodes[0].sendtoaddress(addr, 0.5, fee_rate=self.fee_rate) for addr in addrs]
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
@@ -58,7 +57,7 @@ class WalletGroupTest(BitcoinTestFramework):
# - node[2] should pick one (1.0 + 0.5) UTXO group corresponding to a # - node[2] should pick one (1.0 + 0.5) UTXO group corresponding to a
# given address, and leave the rest # given address, and leave the rest
self.log.info("Test sending transactions picks one UTXO group and leaves the rest") self.log.info("Test sending transactions picks one UTXO group and leaves the rest")
txid1 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 0.2) txid1 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 0.2, fee_rate=self.fee_rate)
tx1 = self.nodes[1].getrawtransaction(txid1, True) tx1 = self.nodes[1].getrawtransaction(txid1, True)
# txid1 should have 1 input and 2 outputs # txid1 should have 1 input and 2 outputs
assert_equal(1, len(tx1["vin"])) assert_equal(1, len(tx1["vin"]))
@@ -69,7 +68,7 @@ class WalletGroupTest(BitcoinTestFramework):
assert_approx(v[0], vexp=0.2, vspan=0.0001) assert_approx(v[0], vexp=0.2, vspan=0.0001)
assert_approx(v[1], vexp=0.3, vspan=0.0001) assert_approx(v[1], vexp=0.3, vspan=0.0001)
txid2 = self.nodes[2].sendtoaddress(self.nodes[0].getnewaddress(), 0.2) txid2 = self.nodes[2].sendtoaddress(self.nodes[0].getnewaddress(), 0.2, fee_rate=self.fee_rate)
tx2 = self.nodes[2].getrawtransaction(txid2, True) tx2 = self.nodes[2].getrawtransaction(txid2, True)
# txid2 should have 2 inputs and 2 outputs # txid2 should have 2 inputs and 2 outputs
assert_equal(2, len(tx2["vin"])) assert_equal(2, len(tx2["vin"]))
@@ -97,7 +96,7 @@ class WalletGroupTest(BitcoinTestFramework):
# this could be (A / B0 / C0) + (B1 / C1 / D). We ensure that it is # this could be (A / B0 / C0) + (B1 / C1 / D). We ensure that it is
# B0 + B1 or C0 + C1, because this avoids partial spends while not being # B0 + B1 or C0 + C1, because this avoids partial spends while not being
# detrimental to transaction cost # detrimental to transaction cost
txid3 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.4) txid3 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.4, fee_rate=self.fee_rate)
tx3 = self.nodes[1].getrawtransaction(txid3, True) tx3 = self.nodes[1].getrawtransaction(txid3, True)
# tx3 should have 2 inputs and 2 outputs # tx3 should have 2 inputs and 2 outputs
assert_equal(2, len(tx3["vin"])) assert_equal(2, len(tx3["vin"]))
@@ -121,11 +120,11 @@ class WalletGroupTest(BitcoinTestFramework):
self.log.info("Test wallet option maxapsfee") self.log.info("Test wallet option maxapsfee")
addr_aps = self.nodes[3].getnewaddress() addr_aps = self.nodes[3].getnewaddress()
self.nodes[0].sendtoaddress(addr_aps, 1.0) self.nodes[0].sendtoaddress(addr_aps, 1.0, fee_rate=self.fee_rate)
self.nodes[0].sendtoaddress(addr_aps, 1.0) self.nodes[0].sendtoaddress(addr_aps, 1.0, fee_rate=self.fee_rate)
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
with self.nodes[3].assert_debug_log([f'Fee non-grouped = {tx4_ungrouped_fee}, grouped = {tx4_grouped_fee}, using grouped']): with self.nodes[3].assert_debug_log([f'Fee non-grouped = {tx4_ungrouped_fee}, grouped = {tx4_grouped_fee}, using grouped']):
txid4 = self.nodes[3].sendtoaddress(self.nodes[0].getnewaddress(), 0.1) txid4 = self.nodes[3].sendtoaddress(self.nodes[0].getnewaddress(), 0.1, fee_rate=self.fee_rate)
tx4 = self.nodes[3].getrawtransaction(txid4, True) tx4 = self.nodes[3].getrawtransaction(txid4, True)
# tx4 should have 2 inputs and 2 outputs although one output would # tx4 should have 2 inputs and 2 outputs although one output would
# have been enough and the transaction caused higher fees # have been enough and the transaction caused higher fees
@@ -133,10 +132,10 @@ class WalletGroupTest(BitcoinTestFramework):
assert_equal(2, len(tx4["vout"])) assert_equal(2, len(tx4["vout"]))
addr_aps2 = self.nodes[3].getnewaddress() addr_aps2 = self.nodes[3].getnewaddress()
[self.nodes[0].sendtoaddress(addr_aps2, 1.0) for _ in range(5)] [self.nodes[0].sendtoaddress(addr_aps2, 1.0, fee_rate=self.fee_rate) for _ in range(5)]
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
with self.nodes[3].assert_debug_log([f'Fee non-grouped = {tx5_6_ungrouped_fee}, grouped = {tx5_6_grouped_fee}, using non-grouped']): with self.nodes[3].assert_debug_log([f'Fee non-grouped = {tx5_6_ungrouped_fee}, grouped = {tx5_6_grouped_fee}, using non-grouped']):
txid5 = self.nodes[3].sendtoaddress(self.nodes[0].getnewaddress(), 2.95) txid5 = self.nodes[3].sendtoaddress(self.nodes[0].getnewaddress(), 2.95, fee_rate=self.fee_rate)
tx5 = self.nodes[3].getrawtransaction(txid5, True) tx5 = self.nodes[3].getrawtransaction(txid5, True)
# tx5 should have 3 inputs (1.0, 1.0, 1.0) and 2 outputs # tx5 should have 3 inputs (1.0, 1.0, 1.0) and 2 outputs
assert_equal(3, len(tx5["vin"])) assert_equal(3, len(tx5["vin"]))
@@ -146,10 +145,10 @@ class WalletGroupTest(BitcoinTestFramework):
# 1 sat higher, crossing the threshold from non-grouped to grouped. # 1 sat higher, crossing the threshold from non-grouped to grouped.
self.log.info("Test wallet option maxapsfee threshold from non-grouped to grouped") self.log.info("Test wallet option maxapsfee threshold from non-grouped to grouped")
addr_aps3 = self.nodes[4].getnewaddress() addr_aps3 = self.nodes[4].getnewaddress()
[self.nodes[0].sendtoaddress(addr_aps3, 1.0) for _ in range(5)] [self.nodes[0].sendtoaddress(addr_aps3, 1.0, fee_rate=self.fee_rate) for _ in range(5)]
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
with self.nodes[4].assert_debug_log([f'Fee non-grouped = {tx5_6_ungrouped_fee}, grouped = {tx5_6_grouped_fee}, using grouped']): with self.nodes[4].assert_debug_log([f'Fee non-grouped = {tx5_6_ungrouped_fee}, grouped = {tx5_6_grouped_fee}, using grouped']):
txid6 = self.nodes[4].sendtoaddress(self.nodes[0].getnewaddress(), 2.95) txid6 = self.nodes[4].sendtoaddress(self.nodes[0].getnewaddress(), 2.95, fee_rate=self.fee_rate)
tx6 = self.nodes[4].getrawtransaction(txid6, True) tx6 = self.nodes[4].getrawtransaction(txid6, True)
# tx6 should have 5 inputs and 2 outputs # tx6 should have 5 inputs and 2 outputs
assert_equal(5, len(tx6["vin"])) assert_equal(5, len(tx6["vin"]))
@@ -166,7 +165,7 @@ class WalletGroupTest(BitcoinTestFramework):
tx = tx_from_hex(raw_tx) tx = tx_from_hex(raw_tx)
tx.vin = [] tx.vin = []
tx.vout = [tx.vout[0]] * 2000 tx.vout = [tx.vout[0]] * 2000
funded_tx = self.nodes[0].fundrawtransaction(tx.serialize().hex()) funded_tx = self.nodes[0].fundrawtransaction(tx.serialize().hex(), options={'fee_rate': self.fee_rate})
signed_tx = self.nodes[0].signrawtransactionwithwallet(funded_tx['hex']) signed_tx = self.nodes[0].signrawtransactionwithwallet(funded_tx['hex'])
self.nodes[0].sendrawtransaction(signed_tx['hex']) self.nodes[0].sendrawtransaction(signed_tx['hex'])
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
@@ -175,7 +174,7 @@ class WalletGroupTest(BitcoinTestFramework):
# utxos, without pulling in all outputs and creating a transaction that # utxos, without pulling in all outputs and creating a transaction that
# is way too big. # is way too big.
self.log.info("Test creating txn that only requires ~100 of our UTXOs without pulling in all outputs") self.log.info("Test creating txn that only requires ~100 of our UTXOs without pulling in all outputs")
assert self.nodes[2].sendtoaddress(address=addr2[0], amount=5) assert self.nodes[2].sendtoaddress(address=addr2[0], amount=5, fee_rate=self.fee_rate)
if __name__ == '__main__': if __name__ == '__main__':
+1 -9
View File
@@ -6,7 +6,6 @@
Verify that a bitcoind node can load multiple wallet files Verify that a bitcoind node can load multiple wallet files
""" """
from decimal import Decimal
from threading import Thread from threading import Thread
import os import os
import platform import platform
@@ -46,7 +45,7 @@ class MultiWalletTest(BitcoinTestFramework):
self.setup_clean_chain = True self.setup_clean_chain = True
self.num_nodes = 2 self.num_nodes = 2
self.rpc_timeout = 120 self.rpc_timeout = 120
self.extra_args = [["-nowallet", "-deprecatedrpc=settxfee"], []] self.extra_args = [["-nowallet"], []]
def skip_test_if_missing_module(self): def skip_test_if_missing_module(self):
self.skip_if_no_wallet() self.skip_if_no_wallet()
@@ -250,13 +249,6 @@ class MultiWalletTest(BitcoinTestFramework):
assert_equal(batch[0]["result"]["chain"], self.chain) assert_equal(batch[0]["result"]["chain"], self.chain)
assert_equal(batch[1]["result"]["walletname"], "w1") assert_equal(batch[1]["result"]["walletname"], "w1")
self.log.info('Check for per-wallet settxfee call')
assert_equal(w1.getwalletinfo()['paytxfee'], 0)
assert_equal(w2.getwalletinfo()['paytxfee'], 0)
w2.settxfee(0.001)
assert_equal(w1.getwalletinfo()['paytxfee'], 0)
assert_equal(w2.getwalletinfo()['paytxfee'], Decimal('0.00100000'))
self.log.info("Test dynamic wallet loading") self.log.info("Test dynamic wallet loading")
self.restart_node(0, ['-nowallet']) self.restart_node(0, ['-nowallet'])
+3 -6
View File
@@ -17,9 +17,8 @@ from test_framework.messages import (
class TxnMallTest(BitcoinTestFramework): class TxnMallTest(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.num_nodes = 3 self.num_nodes = 3
self.extra_args = [[ self.supports_cli = False
"-deprecatedrpc=settxfee" self.extra_args = [[] for i in range(self.num_nodes)]
] for i in range(self.num_nodes)]
def skip_test_if_missing_module(self): def skip_test_if_missing_module(self):
self.skip_if_no_wallet() self.skip_if_no_wallet()
@@ -38,7 +37,7 @@ class TxnMallTest(BitcoinTestFramework):
def spend_utxo(self, utxo, outputs): def spend_utxo(self, utxo, outputs):
inputs = [utxo] inputs = [utxo]
tx = self.nodes[0].createrawtransaction(inputs, outputs) tx = self.nodes[0].createrawtransaction(inputs, outputs)
tx = self.nodes[0].fundrawtransaction(tx) tx = self.nodes[0].fundrawtransaction(tx, fee_rate=100)
tx = self.nodes[0].signrawtransactionwithwallet(tx['hex']) tx = self.nodes[0].signrawtransactionwithwallet(tx['hex'])
return self.nodes[0].sendrawtransaction(tx['hex']) return self.nodes[0].sendrawtransaction(tx['hex'])
@@ -53,8 +52,6 @@ class TxnMallTest(BitcoinTestFramework):
for i in range(3): for i in range(3):
assert_equal(self.nodes[i].getbalance(), starting_balance) assert_equal(self.nodes[i].getbalance(), starting_balance)
self.nodes[0].settxfee(.001)
node0_address1 = self.nodes[0].getnewaddress(address_type=output_type) node0_address1 = self.nodes[0].getnewaddress(address_type=output_type)
node0_utxo1 = self.create_outpoints(self.nodes[0], outputs=[{node0_address1: 1219}])[0] node0_utxo1 = self.create_outpoints(self.nodes[0], outputs=[{node0_address1: 1219}])[0]
node0_tx1 = self.nodes[0].gettransaction(node0_utxo1['txid']) node0_tx1 = self.nodes[0].gettransaction(node0_utxo1['txid'])