Skip to content

Commit 80c8a02

Browse files
author
MarcoFalke
committed
Merge #20159: test: mining_getblocktemplate_longpoll.py improvements (use MiniWallet, add logging)
b128b56 test: add logging for mining_getblocktemplate_longpoll.py (Sebastian Falbesoner) 8ee3536 test: remove unused helpers random_transaction(), make_change() and gather_inputs() (Sebastian Falbesoner) fddce7e test: use MiniWallet for mining_getblocktemplate_longpoll.py (Sebastian Falbesoner) Pull request description: This PR enables one more of the non-wallet functional tests (mining_getblocktemplate_longpoll.py) to be run even with the Bitcoin Core wallet disabled by using the new MiniWallet instead, as proposed in #20078. Also adds missing log messages for the subtests. This was the only functional test that used the `random_transaction` helper in `test_framework/util.py`, hence it is removed, together with other helpers (`make_change` and `gather_inputs`) that were again only used by `random_transaction`. ACKs for top commit: MarcoFalke: ACK b128b56 Tree-SHA512: 09a5fa7b0f5976a47040f7027236d7ec0426d5a4829a082221c4b5fae294470230e89ae3df0bca0eea26833162c03980517f5cc88761ad251c3df4c4a49bca46
2 parents 5d64477 + b128b56 commit 80c8a02

File tree

2 files changed

+19
-71
lines changed

2 files changed

+19
-71
lines changed

test/functional/mining_getblocktemplate_longpoll.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
"""Test longpolling with getblocktemplate."""
66

77
from decimal import Decimal
8+
import random
9+
import threading
810

911
from test_framework.test_framework import BitcoinTestFramework
10-
from test_framework.util import get_rpc_proxy, random_transaction
12+
from test_framework.util import get_rpc_proxy
13+
from test_framework.wallet import MiniWallet
1114

12-
import threading
1315

1416
class LongpollThread(threading.Thread):
1517
def __init__(self, node):
@@ -29,45 +31,48 @@ def set_test_params(self):
2931
self.num_nodes = 2
3032
self.supports_cli = False
3133

32-
def skip_test_if_missing_module(self):
33-
self.skip_if_no_wallet()
34-
3534
def run_test(self):
3635
self.log.info("Warning: this test will take about 70 seconds in the best case. Be patient.")
36+
self.log.info("Test that longpollid doesn't change between successive getblocktemplate() invocations if nothing else happens")
3737
self.nodes[0].generate(10)
3838
template = self.nodes[0].getblocktemplate({'rules': ['segwit']})
3939
longpollid = template['longpollid']
40-
# longpollid should not change between successive invocations if nothing else happens
4140
template2 = self.nodes[0].getblocktemplate({'rules': ['segwit']})
4241
assert template2['longpollid'] == longpollid
4342

44-
# Test 1: test that the longpolling wait if we do nothing
43+
self.log.info("Test that longpoll waits if we do nothing")
4544
thr = LongpollThread(self.nodes[0])
4645
thr.start()
4746
# check that thread still lives
4847
thr.join(5) # wait 5 seconds or until thread exits
4948
assert thr.is_alive()
5049

51-
# Test 2: test that longpoll will terminate if another node generates a block
52-
self.nodes[1].generate(1) # generate a block on another node
50+
miniwallets = [ MiniWallet(node) for node in self.nodes ]
51+
self.log.info("Test that longpoll will terminate if another node generates a block")
52+
miniwallets[1].generate(1) # generate a block on another node
5353
# check that thread will exit now that new transaction entered mempool
5454
thr.join(5) # wait 5 seconds or until thread exits
5555
assert not thr.is_alive()
5656

57-
# Test 3: test that longpoll will terminate if we generate a block ourselves
57+
self.log.info("Test that longpoll will terminate if we generate a block ourselves")
5858
thr = LongpollThread(self.nodes[0])
5959
thr.start()
60-
self.nodes[0].generate(1) # generate a block on another node
60+
miniwallets[0].generate(1) # generate a block on own node
6161
thr.join(5) # wait 5 seconds or until thread exits
6262
assert not thr.is_alive()
6363

64-
# Test 4: test that introducing a new transaction into the mempool will terminate the longpoll
64+
# Add enough mature utxos to the wallets, so that all txs spend confirmed coins
65+
self.nodes[0].generate(100)
66+
self.sync_blocks()
67+
68+
self.log.info("Test that introducing a new transaction into the mempool will terminate the longpoll")
6569
thr = LongpollThread(self.nodes[0])
6670
thr.start()
6771
# generate a random transaction and submit it
6872
min_relay_fee = self.nodes[0].getnetworkinfo()["relayfee"]
69-
# min_relay_fee is fee per 1000 bytes, which should be more than enough.
70-
(txid, txhex, fee) = random_transaction(self.nodes, Decimal("1.1"), min_relay_fee, Decimal("0.001"), 20)
73+
fee_rate = min_relay_fee + Decimal('0.00000010') * random.randint(0,20)
74+
miniwallets[0].send_self_transfer(from_node=random.choice(self.nodes),
75+
fee_rate=fee_rate)
7176
# after one minute, every 10 seconds the mempool is probed, so in 80 seconds it should have returned
7277
thr.join(60 + 20)
7378
assert not thr.is_alive()

test/functional/test_framework/util.py

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import json
1313
import logging
1414
import os
15-
import random
1615
import re
1716
import time
1817
import unittest
@@ -469,62 +468,6 @@ def find_output(node, txid, amount, *, blockhash=None):
469468
raise RuntimeError("find_output txid %s : %s not found" % (txid, str(amount)))
470469

471470

472-
def gather_inputs(from_node, amount_needed, confirmations_required=1):
473-
"""
474-
Return a random set of unspent txouts that are enough to pay amount_needed
475-
"""
476-
assert confirmations_required >= 0
477-
utxo = from_node.listunspent(confirmations_required)
478-
random.shuffle(utxo)
479-
inputs = []
480-
total_in = Decimal("0.00000000")
481-
while total_in < amount_needed and len(utxo) > 0:
482-
t = utxo.pop()
483-
total_in += t["amount"]
484-
inputs.append({"txid": t["txid"], "vout": t["vout"], "address": t["address"]})
485-
if total_in < amount_needed:
486-
raise RuntimeError("Insufficient funds: need %d, have %d" % (amount_needed, total_in))
487-
return (total_in, inputs)
488-
489-
490-
def make_change(from_node, amount_in, amount_out, fee):
491-
"""
492-
Create change output(s), return them
493-
"""
494-
outputs = {}
495-
amount = amount_out + fee
496-
change = amount_in - amount
497-
if change > amount * 2:
498-
# Create an extra change output to break up big inputs
499-
change_address = from_node.getnewaddress()
500-
# Split change in two, being careful of rounding:
501-
outputs[change_address] = Decimal(change / 2).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
502-
change = amount_in - amount - outputs[change_address]
503-
if change > 0:
504-
outputs[from_node.getnewaddress()] = change
505-
return outputs
506-
507-
508-
def random_transaction(nodes, amount, min_fee, fee_increment, fee_variants):
509-
"""
510-
Create a random transaction.
511-
Returns (txid, hex-encoded-transaction-data, fee)
512-
"""
513-
from_node = random.choice(nodes)
514-
to_node = random.choice(nodes)
515-
fee = min_fee + fee_increment * random.randint(0, fee_variants)
516-
517-
(total_in, inputs) = gather_inputs(from_node, amount + fee)
518-
outputs = make_change(from_node, total_in, amount, fee)
519-
outputs[to_node.getnewaddress()] = float(amount)
520-
521-
rawtx = from_node.createrawtransaction(inputs, outputs)
522-
signresult = from_node.signrawtransactionwithwallet(rawtx)
523-
txid = from_node.sendrawtransaction(signresult["hex"], 0)
524-
525-
return (txid, signresult["hex"], fee)
526-
527-
528471
# Helper to create at least "count" utxos
529472
# Pass in a fee that is sufficient for relay and mining new transactions.
530473
def create_confirmed_utxos(fee, node, count):

0 commit comments

Comments
 (0)