test: fix wallet_bumpfee.py

This commit is contained in:
Byron Hambly 2025-10-07 14:01:25 +02:00
parent 282d7bf9b6
commit 0865bc218a
No known key found for this signature in database
GPG key ID: DE8F6EA20A661697
5 changed files with 24 additions and 28 deletions

View file

@ -1188,7 +1188,7 @@ static RPCHelpMan decodepsbt()
result.pushKV("fallback_locktime", static_cast<uint64_t>(*psbtx.fallback_locktime));
}
result.pushKV("input_count", static_cast<uint64_t>(psbtx.inputs.size()));
result.pushKV("output_count", static_cast<uint64_t>(psbtx.inputs.size()));
result.pushKV("output_count", static_cast<uint64_t>(psbtx.outputs.size()));
if (psbtx.m_tx_modifiable != std::nullopt) {
result.pushKV("inputs_modifiable", psbtx.m_tx_modifiable->test(0));
result.pushKV("outputs_modifiable", psbtx.m_tx_modifiable->test(1));

View file

@ -309,6 +309,9 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
}
temp_mtx.vout = txouts;
temp_mtx.witness.vtxoutwit.clear(); // ELEMENTS
for (auto& inwit : temp_mtx.witness.vtxinwit) {
inwit.scriptWitness.SetNull();
}
const int64_t maxTxSize{CalculateMaximumSignedTxSize(CTransaction(temp_mtx), &wallet, &new_coin_control).vsize};
Result res = CheckFeeRate(wallet, temp_mtx, *new_coin_control.m_feerate, maxTxSize, old_fee, errors);
if (res != Result::OK) {

View file

@ -1869,6 +1869,7 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
}
// Error if this output is reduced to be below dust
txout.nValue = value;
if (IsDust(txout, wallet.chain().relayDustFee())) {
if (value < 0) {
return util::Error{_("The transaction amount is too small to pay the fee")};
@ -1876,8 +1877,6 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
return util::Error{_("The transaction amount is too small to send after the fee has been deducted")};
}
}
txout.nValue = value;
}
++i;
}

View file

@ -1789,13 +1789,18 @@ bool FillInputToWeight(CMutableTransaction& mtx, size_t nIn, int64_t target_weig
bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, const CCoinControl* coin_control) const
{
// Fill in dummy signatures for fee calculation.
int nIn = 0;
size_t nIn = 0;
const bool can_grind_r = CanGrindR();
for (const auto& txout : txouts)
{
CTxIn& txin = txNew.vin[nIn];
// If weight was provided, fill the input to that weight
if (coin_control && coin_control->HasInputWeight(txin.prevout)) {
// ELEMENTS: ensure input witness is large enough for rare case in bumpfee
if (txNew.witness.vtxinwit.size() <= nIn) {
txNew.witness.vtxinwit.resize(nIn + 1);
}
assert(txNew.witness.vtxinwit.size() > nIn);
if (!FillInputToWeight(txNew, nIn, coin_control->GetInputWeight(txin.prevout))) {
return false;
}

View file

@ -284,18 +284,10 @@ class BumpFeeTest(BitcoinTestFramework):
self.generate(self.nodes[0], 1)
utxos = wallet.listunspent()
# ELEMENTS FIXME: use createrawtransaction until sendall is fixed
# tx = wallet.sendall(recipients=[wallet.getnewaddress()], fee_rate=2, options={"inputs": [utxos[0]]})
fee = Decimal("0.00001000")
tx = wallet.createrawtransaction([{"txid": utxos[0]["txid"], "vout": utxos[0]["vout"]}], [{wallet.getnewaddress(): utxos[0]["amount"] - fee}, {"fee": fee}])
signed = wallet.signrawtransactionwithwallet(tx)
assert signed["complete"]
txid = wallet.sendrawtransaction(signed["hex"])
tx = {"txid": txid}
tx = wallet.sendall(recipients=[wallet.getnewaddress()], fee_rate=2, options={"inputs": [utxos[0]]})
# Set the only output with a crazy high feerate as change, should fail as the output would be dust
# ELEMENTS FIXME
# assert_raises_rpc_error(-4, "The transaction amount is too small to pay the fee", wallet.bumpfee, txid=tx["txid"], options={"fee_rate": 1100, "original_change_index": 0})
assert_raises_rpc_error(-4, "The transaction amount is too small to pay the fee", wallet.bumpfee, txid=tx["txid"], options={"fee_rate": 1100, "original_change_index": 0})
# Specify single output as change successfully
bumped = wallet.bumpfee(txid=tx["txid"], options={"fee_rate": 11, "original_change_index": 0}) # ELEMENTS
@ -353,7 +345,7 @@ def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address):
# if this is a new_outputs test, check that outputs were indeed replaced
if mode == "new_outputs":
assert len(bumpedwtx["details"]) == 1
# assert bumpedwtx["details"][0]["address"] == new_address # ELEMENTS FIXME: address differs
assert bumpedwtx["details"][0]["address"] == new_address
self.clear_mempool()
@ -410,7 +402,6 @@ def test_notmine_bumpfee(self, rbf_node, peer_node, dest_address):
entry = rbf_node.getmempoolentry(rbfid)
old_fee = entry["fees"]["base"]
old_feerate = int(old_fee / entry["vsize"] * Decimal(1e8))
print(old_feerate) # ELEMENTS FIXME lint
assert_raises_rpc_error(-4, "Transaction contains inputs that don't belong to this wallet",
rbf_node.bumpfee, rbfid)
@ -421,13 +412,12 @@ def test_notmine_bumpfee(self, rbf_node, peer_node, dest_address):
assert res[0]["allowed"]
assert_greater_than(res[0]["fees"]["base"], old_fee)
# ELEMENTS FIXME: insufficient funds
# self.log.info("Test that psbtbumpfee works for non-owned inputs")
# psbt = rbf_node.psbtbumpfee(txid=rbfid)
# finish_psbtbumpfee(psbt["psbt"])
self.log.info("Test that psbtbumpfee works for non-owned inputs")
psbt = rbf_node.psbtbumpfee(txid=rbfid)
finish_psbtbumpfee(psbt["psbt"])
# psbt = rbf_node.psbtbumpfee(txid=rbfid, fee_rate=old_feerate + 10)
# finish_psbtbumpfee(psbt["psbt"])
psbt = rbf_node.psbtbumpfee(txid=rbfid, fee_rate=old_feerate + 10)
finish_psbtbumpfee(psbt["psbt"])
self.clear_mempool()
@ -507,7 +497,7 @@ def test_small_output_with_feerate_succeeds(self, rbf_node, dest_address):
tx_fee = rbfid_new_details["fee"]
# Total value from input not going to destination
if tx_fee > Decimal('0.00040000'): # ELEMENTS FIXME: this was 0.00050000 in bitcoin (since spend_one_input leaves 0.0005 for the fee)
if tx_fee > Decimal('0.00050000'):
break
# input(s) have been added
@ -837,20 +827,19 @@ def test_feerate_checks_replaced_outputs(self, rbf_node, peer_node):
# Calculate the minimum feerate required for the bump to work.
# Since the bumped tx will replace all of the outputs with a single output, we can estimate that its size will 31 * (len(outputs) - 1) bytes smaller
tx_size = tx_details["decoded"]["vsize"]
est_bumped_size = tx_size - (len(tx_details["decoded"]["vout"]) - 1) * 31
est_bumped_size = tx_size - (len(tx_details["decoded"]["vout"]) - 1) * 66 # ELEMENTS: our outputs are larger
inc_fee_rate = max(rbf_node.getmempoolinfo()["incrementalrelayfee"], Decimal(0.00005000)) # Wallet has a fixed incremental relay fee of 5 sat/vb
# RPC gives us fee as negative
min_fee = (-tx_details["fee"]["bitcoin"] + get_fee(est_bumped_size, inc_fee_rate)) * Decimal(1e8)
min_fee_rate = (min_fee / est_bumped_size).quantize(Decimal("1.000"))
print(min_fee_rate) # ELEMENTS FIXME: lint
# Attempt to bumpfee and replace all outputs with a single one using a feerate slightly less than the minimum
new_outputs = [{rbf_node.getnewaddress(address_type="bech32"): 49}]
print(len(new_outputs)) # ELEMENTS FIXME: lint
# assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, tx_res["txid"], {"fee_rate": min_fee_rate - 1, "outputs": new_outputs}) # ELEMENTS FIXME
assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, tx_res["txid"], {"fee_rate": min_fee_rate - 1, "outputs": new_outputs})
# Bumpfee and replace all outputs with a single one using the minimum feerate
# rbf_node.bumpfee(tx_res["txid"], {"fee_rate": min_fee_rate, "outputs": new_outputs}) # ELEMENTS FIXME
min_fee_rate += 4 # ELEMENTS: additional offset
rbf_node.bumpfee(tx_res["txid"], {"fee_rate": min_fee_rate, "outputs": new_outputs})
self.clear_mempool()