Skip to content

Commit

Permalink
Merge pull request bitcoin#333 from qtumproject/djaen/python-qa-refac…
Browse files Browse the repository at this point in the history
…toring-and-fixes

Test fixes for txfee, minimum gas price and refactoring/removal of duplicated code
  • Loading branch information
qtum-neil authored Sep 7, 2017
2 parents 0ba40e6 + 5d4237d commit d344a37
Show file tree
Hide file tree
Showing 30 changed files with 430 additions and 518 deletions.
30 changes: 21 additions & 9 deletions qa/pull-tester/rpc-tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,23 +160,35 @@
'p2p-leaktests.py',

#qtum
'qtum-8mb-block.py',
'qtum-dgp-gas-price-lingering-mempool-tx.py',
'qtum-opcreate.py',
'qtum-state-root.py',
'qtum-opcall.py',
'qtum-createcontract.py',
'qtum-sendtocontract.py',
'qtum-callcontract.py',
'qtum-condensing-txs.py',
'qtum-block-header.py',
'qtum-dgp.py',
'qtum-pos.py',
'qtum-callcontract.py',
'qtum-gas-limit.py',
'qtum-pos-segwit.py',
'qtum-combined-outputs-exceed-gas-limit.py',
'qtum-globals-state-changer.py',
'qtum-sendtocontract.py',
'qtum-condensing-txs.py',
'qtum-identical-refunds.py',
'qtum-8mb-block.py',
'qtum-null-sender.py',
'qtum-soft-block-gas-limits.py',
'qtum-createcontract.py',
'qtum-many-value-refunds-from-same-tx.py',
'qtum-spend-op-call.py',
'qtum-create-eth-op-code.py',
'qtum-no-exec-call-disabled.py',
'qtum-state-root.py',
'qtum-dgp-block-size-restart.py',
'qtum-null-sender.py',
'qtum-transaction-prioritization.py',
'qtum-dgp-block-size-sync.py',
'qtum-dgp-gas-price-lingering-mempool-tx.py'
'qtum-opcall.py'
]


if ENABLE_ZMQ:
testScripts.append('zmq_test.py')

Expand Down
4 changes: 2 additions & 2 deletions qa/rpc-tests/abandonconflict.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def run_test(self):

sync_blocks(self.nodes)
newbalance = self.nodes[0].getbalance()
assert(balance - newbalance < Decimal("0.001")) #no more than fees lost
assert(balance - newbalance < Decimal("0.01")) #no more than fees lost
balance = newbalance

url = urllib.parse.urlparse(self.nodes[1].url)
Expand Down Expand Up @@ -132,7 +132,7 @@ def run_test(self):
inputs =[]
inputs.append({"txid":txA, "vout":nA})
outputs = {}
outputs[self.nodes[1].getnewaddress()] = Decimal("9.9999")
outputs[self.nodes[1].getnewaddress()] = Decimal("9.99")
tx = self.nodes[0].createrawtransaction(inputs, outputs)
signed = self.nodes[0].signrawtransaction(tx)
self.nodes[1].sendrawtransaction(signed["hex"])
Expand Down
78 changes: 40 additions & 38 deletions qa/rpc-tests/bumpfee.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ def run_test(self):
peer_node.generate(COINBASE_MATURITY + 10)
self.sync_all()
for i in range(25):
peer_node.sendtoaddress(rbf_node_address, 0.001)
peer_node.sendtoaddress(rbf_node_address, 0.01)
self.sync_all()
peer_node.generate(1)
self.sync_all()
assert_equal(rbf_node.getbalance(), Decimal("0.025"))
assert_equal(rbf_node.getbalance(), Decimal("0.25"))

print("Running tests")
dest_address = peer_node.getnewaddress()
Expand All @@ -74,7 +74,7 @@ def run_test(self):


def test_simple_bumpfee_succeeds(rbf_node, peer_node, dest_address):
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00900000})
rbftx = rbf_node.gettransaction(rbfid)
sync_mempools((rbf_node, peer_node))
assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
Expand All @@ -98,7 +98,7 @@ def test_segwit_bumpfee_succeeds(rbf_node, dest_address):
# Create a transaction with segwit output, then create an RBF transaction
# which spends it, and make sure bumpfee can be called on it.

segwit_in = next(u for u in rbf_node.listunspent() if u["amount"] == Decimal("0.001"))
segwit_in = next(u for u in rbf_node.listunspent() if u["amount"] == Decimal("0.01"))
segwit_out = rbf_node.validateaddress(rbf_node.getnewaddress())
rbf_node.addwitnessaddress(segwit_out["address"])
segwitid = send_to_witness(
Expand All @@ -107,15 +107,15 @@ def test_segwit_bumpfee_succeeds(rbf_node, dest_address):
utxo=segwit_in,
pubkey=segwit_out["pubkey"],
encode_p2sh=False,
amount=Decimal("0.0009"),
amount=Decimal("0.009"),
sign=True)

rbfraw = rbf_node.createrawtransaction([{
'txid': segwitid,
'vout': 0,
"sequence": BIP125_SEQUENCE_NUMBER
}], {dest_address: Decimal("0.0005"),
get_change_address(rbf_node): Decimal("0.0003")})
}], {dest_address: Decimal("0.005"),
get_change_address(rbf_node): Decimal("0.003")})
rbfsigned = rbf_node.signrawtransaction(rbfraw)
rbfid = rbf_node.sendrawtransaction(rbfsigned["hex"])
assert rbfid in rbf_node.getrawmempool()
Expand All @@ -127,7 +127,7 @@ def test_segwit_bumpfee_succeeds(rbf_node, dest_address):

def test_nonrbf_bumpfee_fails(peer_node, dest_address):
# cannot replace a non RBF transaction (from node which did not enable RBF)
not_rbfid = create_fund_sign_send(peer_node, {dest_address: 0.00090000})
not_rbfid = create_fund_sign_send(peer_node, {dest_address: 0.00900000})
assert_raises_message(JSONRPCException, "not BIP 125 replaceable", peer_node.bumpfee, not_rbfid)


Expand Down Expand Up @@ -155,8 +155,8 @@ def test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address):
def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address):
# cannot bump fee if the transaction has a descendant
# parent is send-to-self, so we don't have to check which output is change when creating the child tx
parent_id = create_fund_sign_send(rbf_node, {rbf_node_address: 0.00050000})
tx = rbf_node.createrawtransaction([{"txid": parent_id, "vout": 0}], {dest_address: 0.00020000})
parent_id = create_fund_sign_send(rbf_node, {rbf_node_address: 0.0050000})
tx = rbf_node.createrawtransaction([{"txid": parent_id, "vout": 0}], {dest_address: 0.0020000})
tx = rbf_node.signrawtransaction(tx)
txid = rbf_node.sendrawtransaction(tx["hex"])
assert_raises_message(JSONRPCException, "Transaction has descendants in the wallet", rbf_node.bumpfee, parent_id)
Expand All @@ -165,65 +165,66 @@ def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address)
def test_small_output_fails(rbf_node, dest_address):
# cannot bump fee with a too-small output
rbfid = spend_one_input(rbf_node,
Decimal("0.00100000"),
{dest_address: 0.00080000,
get_change_address(rbf_node): Decimal("0.00010000")})
rbf_node.bumpfee(rbfid, {"totalFee": 20000})
Decimal("0.01000000"),
{dest_address: 0.00800000,
get_change_address(rbf_node): Decimal("0.00100000")})
rbf_node.bumpfee(rbfid, {"totalFee": 200000})

rbfid = spend_one_input(rbf_node,
Decimal("0.00100000"),
{dest_address: 0.00080000,
get_change_address(rbf_node): Decimal("0.00010000")})
assert_raises_message(JSONRPCException, "Change output is too small", rbf_node.bumpfee, rbfid, {"totalFee": 20001})
Decimal("0.0100000"),
{dest_address: 0.0080000,
get_change_address(rbf_node): Decimal("0.0010000")})
assert_raises_message(JSONRPCException, "Change output is too small", rbf_node.bumpfee, rbfid, {"totalFee": 200001})


def test_dust_to_fee(rbf_node, dest_address):
# check that if output is reduced to dust, it will be converted to fee
# the bumped tx sets fee=9900, but it converts to 10,000
rbfid = spend_one_input(rbf_node,
Decimal("0.00100000"),
{dest_address: 0.00080000,
get_change_address(rbf_node): Decimal("0.00010000")})
Decimal("0.0100000"),
{dest_address: 0.0080000,
get_change_address(rbf_node): Decimal("0.0010000")})
fulltx = rbf_node.getrawtransaction(rbfid, 1)
bumped_tx = rbf_node.bumpfee(rbfid, {"totalFee": 19900})
bumped_tx = rbf_node.bumpfee(rbfid, {"totalFee": 199000})
full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1)
assert_equal(bumped_tx["fee"], Decimal("0.00020000"))
assert_equal(bumped_tx["fee"], Decimal("0.00200000"))
assert_equal(len(fulltx["vout"]), 2)
assert_equal(len(full_bumped_tx["vout"]), 1) #change output is eliminated


def test_settxfee(rbf_node, dest_address):
# check that bumpfee reacts correctly to the use of settxfee (paytxfee)
# increase feerate by 2.5x, test that fee increased at least 2x
rbf_node.settxfee(Decimal("0.00001000"))
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
rbf_node.settxfee(Decimal("0.00100000"))
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.09000000})
rbftx = rbf_node.gettransaction(rbfid)
rbf_node.settxfee(Decimal("0.00002500"))
rbf_node.settxfee(Decimal("0.01000000"))
bumped_tx = rbf_node.bumpfee(rbfid)
print(bumped_tx["fee"], " > ", 2 * abs(rbftx["fee"]))
assert bumped_tx["fee"] > 2 * abs(rbftx["fee"])
rbf_node.settxfee(Decimal("0.00000000")) # unset paytxfee


def test_rebumping(rbf_node, dest_address):
# check that re-bumping the original tx fails, but bumping the bumper succeeds
rbf_node.settxfee(Decimal("0.00001000"))
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
bumped = rbf_node.bumpfee(rbfid, {"totalFee": 1000})
assert_raises_message(JSONRPCException, "already bumped", rbf_node.bumpfee, rbfid, {"totalFee": 2000})
rbf_node.bumpfee(bumped["txid"], {"totalFee": 2000})
rbf_node.settxfee(Decimal("0.0001000"))
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.0090000})
bumped = rbf_node.bumpfee(rbfid, {"totalFee": 155000})
assert_raises_message(JSONRPCException, "already bumped", rbf_node.bumpfee, rbfid, {"totalFee": 200000})
rbf_node.bumpfee(bumped["txid"], {"totalFee": 200000})


def test_rebumping_not_replaceable(rbf_node, dest_address):
# check that re-bumping a non-replaceable bump tx fails
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
bumped = rbf_node.bumpfee(rbfid, {"totalFee": 10000, "replaceable": False})
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.0090000})
bumped = rbf_node.bumpfee(rbfid, {"totalFee": 155000, "replaceable": False})
assert_raises_message(JSONRPCException, "Transaction is not BIP 125 replaceable", rbf_node.bumpfee, bumped["txid"],
{"totalFee": 20000})
{"totalFee": 200000})


def test_unconfirmed_not_spendable(rbf_node, rbf_node_address):
# check that unconfirmed outputs from bumped transactions are not spendable
rbfid = create_fund_sign_send(rbf_node, {rbf_node_address: 0.00090000})
rbfid = create_fund_sign_send(rbf_node, {rbf_node_address: 0.00500000})
rbftx = rbf_node.gettransaction(rbfid)["hex"]
assert rbfid in rbf_node.getrawmempool()
bumpid = rbf_node.bumpfee(rbfid)["txid"]
Expand Down Expand Up @@ -258,15 +259,15 @@ def test_unconfirmed_not_spendable(rbf_node, rbf_node_address):


def test_bumpfee_metadata(rbf_node, dest_address):
rbfid = rbf_node.sendtoaddress(dest_address, 0.00090000, "comment value", "to value")
rbfid = rbf_node.sendtoaddress(dest_address, 0.00900000, "comment value", "to value")
bumped_tx = rbf_node.bumpfee(rbfid)
bumped_wtx = rbf_node.gettransaction(bumped_tx["txid"])
assert_equal(bumped_wtx["comment"], "comment value")
assert_equal(bumped_wtx["to"], "to value")


def test_locked_wallet_fails(rbf_node, dest_address):
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00900000})
rbf_node.walletlock()
assert_raises_message(JSONRPCException, "Please enter the wallet passphrase with walletpassphrase first.",
rbf_node.bumpfee, rbfid)
Expand Down Expand Up @@ -295,10 +296,11 @@ def get_change_address(node):
dummy transaction, calls fundrawtransaction to give add an input and change
output, then returns the change address."""
dest_address = node.getnewaddress()
dest_amount = Decimal("0.00012345")
dest_amount = Decimal("0.01234500")
rawtx = node.createrawtransaction([], {dest_address: dest_amount})
fundtx = node.fundrawtransaction(rawtx)
info = node.decoderawtransaction(fundtx["hex"])

return next(address for out in info["vout"]
if out["value"] != dest_amount for address in out["scriptPubKey"]["addresses"])

Expand Down
5 changes: 3 additions & 2 deletions qa/rpc-tests/fundrawtransaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def run_test(self):
print("Mining blocks...")

min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee']
print(min_relay_tx_fee)
# 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
for node in self.nodes:
Expand Down Expand Up @@ -539,7 +540,7 @@ def run_test(self):
self.sync_all()

for i in range(0,20):
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
self.nodes[0].generate(1)
self.sync_all()

Expand Down Expand Up @@ -569,7 +570,7 @@ def run_test(self):
self.sync_all()

for i in range(0,20):
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
self.nodes[0].generate(1)
self.sync_all()

Expand Down
2 changes: 1 addition & 1 deletion qa/rpc-tests/mempool_limit.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def run_test(self):
#create a mempool tx that will be evicted
us0 = utxos.pop()
inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}]
outputs = {self.nodes[0].getnewaddress() : 0.0001}
outputs = {self.nodes[0].getnewaddress() : 0.01}
tx = self.nodes[0].createrawtransaction(inputs, outputs)
self.nodes[0].settxfee(self.relayfee) # specifically fund this tx with low fee
txF = self.nodes[0].fundrawtransaction(tx)
Expand Down
2 changes: 1 addition & 1 deletion qa/rpc-tests/mempool_reorg.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def setup_network(self):
def run_test(self):
for node in self.nodes:
node.generate(25)
self.sync_all()
self.sync_all()
self.nodes[0].generate(COINBASE_MATURITY)
self.sync_all()

Expand Down
4 changes: 2 additions & 2 deletions qa/rpc-tests/p2p-compactblocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ def setup_network(self):

# Start up node0 to be a version 1, pre-segwit node.
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
[["-debug", "-logtimemicros=1", "-bip9params=segwit:0:0"],
["-debug", "-logtimemicros", "-txindex"]])
[["-debug", "-logtimemicros=1", "-bip9params=segwit:0:0", "-minrelaytxfee=0.000001"],
["-debug", "-logtimemicros", "-txindex", "-minrelaytxfee=0.000001"]])
connect_nodes(self.nodes[0], 1)

def build_block_on_tip(self, node, segwit=False):
Expand Down
4 changes: 2 additions & 2 deletions qa/rpc-tests/qtum-block-header.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def rejected(reject = None):
function() payable {}
}
"""
tx_hex = node.createcontract("60606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a72305820693c4900c412f72a51f8c01a36d38d9038d822d953faf5a5b28e40ec6e1a25020029", 1000000, 0.00000001, spendable_addresses.pop(-1), False)['raw transaction']
tx_hex = node.createcontract("60606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a72305820693c4900c412f72a51f8c01a36d38d9038d822d953faf5a5b28e40ec6e1a25020029", 1000000, QTUM_MIN_GAS_PRICE/COIN, spendable_addresses.pop(-1), False)['raw transaction']
f = io.BytesIO(hex_str_to_bytes(tx_hex))
tx = CTransaction()
tx.deserialize(f)
Expand Down Expand Up @@ -124,7 +124,7 @@ def rejected(reject = None):


# A block with a tx, but without updated state hashes
tx_hex = node.sendtocontract(contract_address, "00", 1, 100000, 0.00000001, spendable_addresses.pop(-1), False)['raw transaction']
tx_hex = node.sendtocontract(contract_address, "00", 1, 100000, QTUM_MIN_GAS_PRICE/COIN, spendable_addresses.pop(-1), False)['raw transaction']
f = io.BytesIO(hex_str_to_bytes(tx_hex))
tx = CTransaction()
tx.deserialize(f)
Expand Down
Loading

0 comments on commit d344a37

Please sign in to comment.