add functional tests for feerate bumpfee with adding inputs

This commit is contained in:
Gregory Sanders 2019-03-08 11:30:53 -05:00
parent 0ea47ba7b3
commit d08becff85

View file

@ -73,6 +73,9 @@ class BumpFeeTest(BitcoinTestFramework):
test_unconfirmed_not_spendable(rbf_node, rbf_node_address) test_unconfirmed_not_spendable(rbf_node, rbf_node_address)
test_bumpfee_metadata(rbf_node, dest_address) test_bumpfee_metadata(rbf_node, dest_address)
test_locked_wallet_fails(rbf_node, dest_address) test_locked_wallet_fails(rbf_node, dest_address)
# These tests wipe out a number of utxos that are expected in other tests
test_small_output_with_feerate_succeeds(rbf_node, dest_address)
test_no_more_inputs_fails(rbf_node, dest_address)
self.log.info("Success") self.log.info("Success")
@ -173,6 +176,40 @@ def test_small_output_fails(rbf_node, dest_address):
rbfid = spend_one_input(rbf_node, dest_address) rbfid = spend_one_input(rbf_node, dest_address)
assert_raises_rpc_error(-4, "Change output is too small", rbf_node.bumpfee, rbfid, {"totalFee": 50001}) assert_raises_rpc_error(-4, "Change output is too small", rbf_node.bumpfee, rbfid, {"totalFee": 50001})
def test_small_output_with_feerate_succeeds(rbf_node, dest_address):
# Make sure additional inputs exist
rbf_node.generatetoaddress(101, rbf_node.getnewaddress())
rbfid = spend_one_input(rbf_node, dest_address)
original_input_list = rbf_node.getrawtransaction(rbfid, 1)["vin"]
assert_equal(len(original_input_list), 1)
original_txin = original_input_list[0]
# Keep bumping until we out-spend change output
tx_fee = 0
while tx_fee < Decimal("0.0005"):
new_input_list = rbf_node.getrawtransaction(rbfid, 1)["vin"]
new_item = list(new_input_list)[0]
assert_equal(len(original_input_list), 1)
assert_equal(original_txin["txid"], new_item["txid"])
assert_equal(original_txin["vout"], new_item["vout"])
rbfid_new_details = rbf_node.bumpfee(rbfid)
rbfid_new = rbfid_new_details["txid"]
raw_pool = rbf_node.getrawmempool()
assert rbfid not in raw_pool
assert rbfid_new in raw_pool
rbfid = rbfid_new
tx_fee = rbfid_new_details["origfee"]
# input(s) have been added
final_input_list = rbf_node.getrawtransaction(rbfid, 1)["vin"]
assert_greater_than(len(final_input_list), 1)
# Original input is in final set
assert [txin for txin in final_input_list
if txin["txid"] == original_txin["txid"]
and txin["vout"] == original_txin["vout"]]
rbf_node.generatetoaddress(1, rbf_node.getnewaddress())
assert_equal(rbf_node.gettransaction(rbfid)["confirmations"], 1)
def test_dust_to_fee(rbf_node, dest_address): def test_dust_to_fee(rbf_node, dest_address):
# check that if output is reduced to dust, it will be converted to fee # check that if output is reduced to dust, it will be converted to fee
@ -272,19 +309,20 @@ def test_locked_wallet_fails(rbf_node, dest_address):
rbf_node.walletlock() rbf_node.walletlock()
assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first.", assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first.",
rbf_node.bumpfee, rbfid) rbf_node.bumpfee, rbfid)
rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
def spend_one_input(node, dest_address): def spend_one_input(node, dest_address, change_size=Decimal("0.00049000")):
tx_input = dict( tx_input = dict(
sequence=BIP125_SEQUENCE_NUMBER, **next(u for u in node.listunspent() if u["amount"] == Decimal("0.00100000"))) sequence=BIP125_SEQUENCE_NUMBER, **next(u for u in node.listunspent() if u["amount"] == Decimal("0.00100000")))
rawtx = node.createrawtransaction( destinations = {dest_address: Decimal("0.00050000")}
[tx_input], {dest_address: Decimal("0.00050000"), if change_size > 0:
node.getrawchangeaddress(): Decimal("0.00049000")}) destinations[node.getrawchangeaddress()] = change_size
rawtx = node.createrawtransaction([tx_input], destinations)
signedtx = node.signrawtransactionwithwallet(rawtx) signedtx = node.signrawtransactionwithwallet(rawtx)
txid = node.sendrawtransaction(signedtx["hex"]) txid = node.sendrawtransaction(signedtx["hex"])
return txid return txid
def submit_block_with_tx(node, tx): def submit_block_with_tx(node, tx):
ctx = CTransaction() ctx = CTransaction()
ctx.deserialize(io.BytesIO(hex_str_to_bytes(tx))) ctx.deserialize(io.BytesIO(hex_str_to_bytes(tx)))
@ -301,6 +339,12 @@ def submit_block_with_tx(node, tx):
node.submitblock(block.serialize(True).hex()) node.submitblock(block.serialize(True).hex())
return block return block
def test_no_more_inputs_fails(rbf_node, dest_address):
# feerate rbf requires confirmed outputs when change output doesn't exist or is insufficient
rbf_node.generatetoaddress(1, dest_address)
# spend all funds, no change output
rbfid = rbf_node.sendtoaddress(rbf_node.getnewaddress(), rbf_node.getbalance(), "", "", True)
assert_raises_rpc_error(-4, "Unable to create transaction: Insufficient funds", rbf_node.bumpfee, rbfid)
if __name__ == "__main__": if __name__ == "__main__":
BumpFeeTest().main() BumpFeeTest().main()