mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-12-04 17:52:25 +01:00
wallet/rpc: add maxfeerate parameter to sendrawtransaction
This commit is contained in:
@@ -46,7 +46,7 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
|
||||
|
||||
signed_tx = node.signrawtransactionwithwallet(txToHex(tx2))
|
||||
|
||||
txid = node.sendrawtransaction(signed_tx['hex'], True)
|
||||
txid = node.sendrawtransaction(signed_tx['hex'], 0)
|
||||
|
||||
# If requested, ensure txouts are confirmed.
|
||||
if confirmed:
|
||||
@@ -136,7 +136,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||
tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
|
||||
tx1a_hex = txToHex(tx1a)
|
||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0)
|
||||
|
||||
self.sync_all()
|
||||
|
||||
@@ -147,9 +147,9 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx1b_hex = txToHex(tx1b)
|
||||
|
||||
# This will raise an exception due to insufficient fee
|
||||
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True)
|
||||
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, 0)
|
||||
# This will raise an exception due to transaction replacement being disabled
|
||||
assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[1].sendrawtransaction, tx1b_hex, True)
|
||||
assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[1].sendrawtransaction, tx1b_hex, 0)
|
||||
|
||||
# Extra 0.1 BTC fee
|
||||
tx1b = CTransaction()
|
||||
@@ -157,9 +157,9 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx1b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b' * 35]))]
|
||||
tx1b_hex = txToHex(tx1b)
|
||||
# Replacement still disabled even with "enough fee"
|
||||
assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[1].sendrawtransaction, tx1b_hex, True)
|
||||
assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[1].sendrawtransaction, tx1b_hex, 0)
|
||||
# Works when enabled
|
||||
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
|
||||
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, 0)
|
||||
|
||||
mempool = self.nodes[0].getrawmempool()
|
||||
|
||||
@@ -188,7 +188,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx.vin = [CTxIn(prevout, nSequence=0)]
|
||||
tx.vout = [CTxOut(remaining_value, CScript([1, OP_DROP] * 15 + [1]))]
|
||||
tx_hex = txToHex(tx)
|
||||
txid = self.nodes[0].sendrawtransaction(tx_hex, True)
|
||||
txid = self.nodes[0].sendrawtransaction(tx_hex, 0)
|
||||
chain_txids.append(txid)
|
||||
prevout = COutPoint(int(txid, 16), 0)
|
||||
|
||||
@@ -200,14 +200,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
dbl_tx_hex = txToHex(dbl_tx)
|
||||
|
||||
# This will raise an exception due to insufficient fee
|
||||
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, True)
|
||||
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, 0)
|
||||
|
||||
# Accepted with sufficient fee
|
||||
dbl_tx = CTransaction()
|
||||
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||
dbl_tx.vout = [CTxOut(1 * COIN, CScript([1] * 35))]
|
||||
dbl_tx_hex = txToHex(dbl_tx)
|
||||
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
|
||||
self.nodes[0].sendrawtransaction(dbl_tx_hex, 0)
|
||||
|
||||
mempool = self.nodes[0].getrawmempool()
|
||||
for doublespent_txid in chain_txids:
|
||||
@@ -237,7 +237,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx_hex = txToHex(tx)
|
||||
|
||||
assert len(tx.serialize()) < 100000
|
||||
txid = self.nodes[0].sendrawtransaction(tx_hex, True)
|
||||
txid = self.nodes[0].sendrawtransaction(tx_hex, 0)
|
||||
yield tx
|
||||
_total_txs[0] += 1
|
||||
|
||||
@@ -261,14 +261,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
dbl_tx.vout = [CTxOut(initial_nValue - fee * n, CScript([1] * 35))]
|
||||
dbl_tx_hex = txToHex(dbl_tx)
|
||||
# This will raise an exception due to insufficient fee
|
||||
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, True)
|
||||
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, 0)
|
||||
|
||||
# 1 BTC fee is enough
|
||||
dbl_tx = CTransaction()
|
||||
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||
dbl_tx.vout = [CTxOut(initial_nValue - fee * n - 1 * COIN, CScript([1] * 35))]
|
||||
dbl_tx_hex = txToHex(dbl_tx)
|
||||
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
|
||||
self.nodes[0].sendrawtransaction(dbl_tx_hex, 0)
|
||||
|
||||
mempool = self.nodes[0].getrawmempool()
|
||||
|
||||
@@ -289,7 +289,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
dbl_tx.vout = [CTxOut(initial_nValue - 2 * fee * n, CScript([1] * 35))]
|
||||
dbl_tx_hex = txToHex(dbl_tx)
|
||||
# This will raise an exception
|
||||
assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, dbl_tx_hex, True)
|
||||
assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, dbl_tx_hex, 0)
|
||||
|
||||
for tx in tree_txs:
|
||||
tx.rehash()
|
||||
@@ -303,7 +303,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||
tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
|
||||
tx1a_hex = txToHex(tx1a)
|
||||
self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
||||
self.nodes[0].sendrawtransaction(tx1a_hex, 0)
|
||||
|
||||
# Higher fee, but the fee per KB is much lower, so the replacement is
|
||||
# rejected.
|
||||
@@ -313,7 +313,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx1b_hex = txToHex(tx1b)
|
||||
|
||||
# This will raise an exception due to insufficient fee
|
||||
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True)
|
||||
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, 0)
|
||||
|
||||
def test_spends_of_conflicting_outputs(self):
|
||||
"""Replacements that spend conflicting tx outputs are rejected"""
|
||||
@@ -324,7 +324,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx1a.vin = [CTxIn(utxo1, nSequence=0)]
|
||||
tx1a.vout = [CTxOut(int(1.1 * COIN), CScript([b'a' * 35]))]
|
||||
tx1a_hex = txToHex(tx1a)
|
||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0)
|
||||
|
||||
tx1a_txid = int(tx1a_txid, 16)
|
||||
|
||||
@@ -336,14 +336,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx2_hex = txToHex(tx2)
|
||||
|
||||
# This will raise an exception
|
||||
assert_raises_rpc_error(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, tx2_hex, True)
|
||||
assert_raises_rpc_error(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, tx2_hex, 0)
|
||||
|
||||
# Spend tx1a's output to test the indirect case.
|
||||
tx1b = CTransaction()
|
||||
tx1b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
|
||||
tx1b.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
|
||||
tx1b_hex = txToHex(tx1b)
|
||||
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
|
||||
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, 0)
|
||||
tx1b_txid = int(tx1b_txid, 16)
|
||||
|
||||
tx2 = CTransaction()
|
||||
@@ -353,7 +353,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx2_hex = txToHex(tx2)
|
||||
|
||||
# This will raise an exception
|
||||
assert_raises_rpc_error(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, tx2_hex, True)
|
||||
assert_raises_rpc_error(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, tx2_hex, 0)
|
||||
|
||||
def test_new_unconfirmed_inputs(self):
|
||||
"""Replacements that add new unconfirmed inputs are rejected"""
|
||||
@@ -364,7 +364,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx1.vin = [CTxIn(confirmed_utxo)]
|
||||
tx1.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
|
||||
tx1_hex = txToHex(tx1)
|
||||
self.nodes[0].sendrawtransaction(tx1_hex, True)
|
||||
self.nodes[0].sendrawtransaction(tx1_hex, 0)
|
||||
|
||||
tx2 = CTransaction()
|
||||
tx2.vin = [CTxIn(confirmed_utxo), CTxIn(unconfirmed_utxo)]
|
||||
@@ -372,7 +372,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx2_hex = txToHex(tx2)
|
||||
|
||||
# This will raise an exception
|
||||
assert_raises_rpc_error(-26, "replacement-adds-unconfirmed", self.nodes[0].sendrawtransaction, tx2_hex, True)
|
||||
assert_raises_rpc_error(-26, "replacement-adds-unconfirmed", self.nodes[0].sendrawtransaction, tx2_hex, 0)
|
||||
|
||||
def test_too_many_replacements(self):
|
||||
"""Replacements that evict too many transactions are rejected"""
|
||||
@@ -394,7 +394,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
splitting_tx.vout = outputs
|
||||
splitting_tx_hex = txToHex(splitting_tx)
|
||||
|
||||
txid = self.nodes[0].sendrawtransaction(splitting_tx_hex, True)
|
||||
txid = self.nodes[0].sendrawtransaction(splitting_tx_hex, 0)
|
||||
txid = int(txid, 16)
|
||||
|
||||
# Now spend each of those outputs individually
|
||||
@@ -403,7 +403,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx_i.vin = [CTxIn(COutPoint(txid, i), nSequence=0)]
|
||||
tx_i.vout = [CTxOut(split_value - fee, CScript([b'a' * 35]))]
|
||||
tx_i_hex = txToHex(tx_i)
|
||||
self.nodes[0].sendrawtransaction(tx_i_hex, True)
|
||||
self.nodes[0].sendrawtransaction(tx_i_hex, 0)
|
||||
|
||||
# Now create doublespend of the whole lot; should fail.
|
||||
# Need a big enough fee to cover all spending transactions and have
|
||||
@@ -418,14 +418,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
double_tx_hex = txToHex(double_tx)
|
||||
|
||||
# This will raise an exception
|
||||
assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, double_tx_hex, True)
|
||||
assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, double_tx_hex, 0)
|
||||
|
||||
# If we remove an input, it should pass
|
||||
double_tx = CTransaction()
|
||||
double_tx.vin = inputs[0:-1]
|
||||
double_tx.vout = [CTxOut(double_spend_value, CScript([b'a']))]
|
||||
double_tx_hex = txToHex(double_tx)
|
||||
self.nodes[0].sendrawtransaction(double_tx_hex, True)
|
||||
self.nodes[0].sendrawtransaction(double_tx_hex, 0)
|
||||
|
||||
def test_opt_in(self):
|
||||
"""Replacing should only work if orig tx opted in"""
|
||||
@@ -436,7 +436,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0xffffffff)]
|
||||
tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
|
||||
tx1a_hex = txToHex(tx1a)
|
||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0)
|
||||
|
||||
# This transaction isn't shown as replaceable
|
||||
assert_equal(self.nodes[0].getmempoolentry(tx1a_txid)['bip125-replaceable'], False)
|
||||
@@ -448,7 +448,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx1b_hex = txToHex(tx1b)
|
||||
|
||||
# This will raise an exception
|
||||
assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx1b_hex, True)
|
||||
assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx1b_hex, 0)
|
||||
|
||||
tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
|
||||
|
||||
@@ -457,7 +457,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0xfffffffe)]
|
||||
tx2a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
|
||||
tx2a_hex = txToHex(tx2a)
|
||||
tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
|
||||
tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, 0)
|
||||
|
||||
# Still shouldn't be able to double-spend
|
||||
tx2b = CTransaction()
|
||||
@@ -466,7 +466,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx2b_hex = txToHex(tx2b)
|
||||
|
||||
# This will raise an exception
|
||||
assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx2b_hex, True)
|
||||
assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx2b_hex, 0)
|
||||
|
||||
# Now create a new transaction that spends from tx1a and tx2a
|
||||
# opt-in on one of the inputs
|
||||
@@ -481,7 +481,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx3a.vout = [CTxOut(int(0.9*COIN), CScript([b'c'])), CTxOut(int(0.9*COIN), CScript([b'd']))]
|
||||
tx3a_hex = txToHex(tx3a)
|
||||
|
||||
tx3a_txid = self.nodes[0].sendrawtransaction(tx3a_hex, True)
|
||||
tx3a_txid = self.nodes[0].sendrawtransaction(tx3a_hex, 0)
|
||||
|
||||
# This transaction is shown as replaceable
|
||||
assert_equal(self.nodes[0].getmempoolentry(tx3a_txid)['bip125-replaceable'], True)
|
||||
@@ -496,10 +496,10 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx3c.vout = [CTxOut(int(0.5 * COIN), CScript([b'f' * 35]))]
|
||||
tx3c_hex = txToHex(tx3c)
|
||||
|
||||
self.nodes[0].sendrawtransaction(tx3b_hex, True)
|
||||
self.nodes[0].sendrawtransaction(tx3b_hex, 0)
|
||||
# If tx3b was accepted, tx3c won't look like a replacement,
|
||||
# but make sure it is accepted anyway
|
||||
self.nodes[0].sendrawtransaction(tx3c_hex, True)
|
||||
self.nodes[0].sendrawtransaction(tx3c_hex, 0)
|
||||
|
||||
def test_prioritised_transactions(self):
|
||||
# Ensure that fee deltas used via prioritisetransaction are
|
||||
@@ -512,7 +512,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||
tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
|
||||
tx1a_hex = txToHex(tx1a)
|
||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0)
|
||||
|
||||
# Higher fee, but the actual fee per KB is much lower.
|
||||
tx1b = CTransaction()
|
||||
@@ -521,13 +521,13 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx1b_hex = txToHex(tx1b)
|
||||
|
||||
# Verify tx1b cannot replace tx1a.
|
||||
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True)
|
||||
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, 0)
|
||||
|
||||
# Use prioritisetransaction to set tx1a's fee to 0.
|
||||
self.nodes[0].prioritisetransaction(txid=tx1a_txid, fee_delta=int(-0.1*COIN))
|
||||
|
||||
# Now tx1b should be able to replace tx1a
|
||||
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
|
||||
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, 0)
|
||||
|
||||
assert tx1b_txid in self.nodes[0].getrawmempool()
|
||||
|
||||
@@ -538,7 +538,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)]
|
||||
tx2a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
|
||||
tx2a_hex = txToHex(tx2a)
|
||||
self.nodes[0].sendrawtransaction(tx2a_hex, True)
|
||||
self.nodes[0].sendrawtransaction(tx2a_hex, 0)
|
||||
|
||||
# Lower fee, but we'll prioritise it
|
||||
tx2b = CTransaction()
|
||||
@@ -548,13 +548,13 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
tx2b_hex = txToHex(tx2b)
|
||||
|
||||
# Verify tx2b cannot replace tx2a.
|
||||
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx2b_hex, True)
|
||||
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx2b_hex, 0)
|
||||
|
||||
# Now prioritise tx2b to have a higher modified fee
|
||||
self.nodes[0].prioritisetransaction(txid=tx2b.hash, fee_delta=int(0.1*COIN))
|
||||
|
||||
# tx2b should now be accepted
|
||||
tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True)
|
||||
tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, 0)
|
||||
|
||||
assert tx2b_txid in self.nodes[0].getrawmempool()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user