aboutsummaryrefslogtreecommitdiff
path: root/test/functional/test_framework/util.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/test_framework/util.py')
-rw-r--r--test/functional/test_framework/util.py118
1 files changed, 15 insertions, 103 deletions
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index d0aaeea7bc..123c48852c 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -8,11 +8,11 @@ from base64 import b64encode
from binascii import unhexlify
from decimal import Decimal, ROUND_DOWN
from subprocess import CalledProcessError
+import hashlib
import inspect
import json
import logging
import os
-import random
import re
import time
import unittest
@@ -226,14 +226,14 @@ def satoshi_round(amount):
return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
-def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf'), lock=None, timeout_factor=1.0):
+def wait_until_helper(predicate, *, attempts=float('inf'), timeout=float('inf'), lock=None, timeout_factor=1.0):
"""Sleep until the predicate resolves to be True.
Warning: Note that this method is not recommended to be used in tests as it is
- not aware of the context of the test framework. Using `wait_until()` counterpart
- from `BitcoinTestFramework` or `P2PInterface` class ensures an understandable
- amount of timeout and a common shared timeout_factor. Furthermore, `wait_until()`
- from `P2PInterface` class in `mininode.py` has a preset lock.
+ not aware of the context of the test framework. Using the `wait_until()` members
+ from `BitcoinTestFramework` or `P2PInterface` class ensures the timeout is
+ properly scaled. Furthermore, `wait_until()` from `P2PInterface` class in
+ `p2p.py` has a preset lock.
"""
if attempts == float('inf') and timeout == float('inf'):
timeout = 60
@@ -261,6 +261,14 @@ def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf'), lock=N
raise AssertionError("Predicate {} not true after {} seconds".format(predicate_source, timeout))
raise RuntimeError('Unreachable')
+def sha256sum_file(filename):
+ h = hashlib.sha256()
+ with open(filename, 'rb') as f:
+ d = f.read(4096)
+ while len(d) > 0:
+ h.update(d)
+ d = f.read(4096)
+ return h.digest()
# RPC/P2P connection constants and functions
############################################
@@ -363,6 +371,7 @@ def write_config(config_path, *, n, chain, extra_config=""):
f.write("listenonion=0\n")
f.write("printtoconsole=0\n")
f.write("upnp=0\n")
+ f.write("natpmp=0\n")
f.write("shrinkdebugfile=0\n")
f.write(extra_config)
@@ -419,47 +428,6 @@ def set_node_times(nodes, t):
node.setmocktime(t)
-def disconnect_nodes(from_connection, node_num):
- def get_peer_ids():
- result = []
- for peer in from_connection.getpeerinfo():
- if "testnode{}".format(node_num) in peer['subver']:
- result.append(peer['id'])
- return result
-
- peer_ids = get_peer_ids()
- if not peer_ids:
- logger.warning("disconnect_nodes: {} and {} were not connected".format(
- from_connection.index,
- node_num,
- ))
- return
- for peer_id in peer_ids:
- try:
- from_connection.disconnectnode(nodeid=peer_id)
- except JSONRPCException as e:
- # If this node is disconnected between calculating the peer id
- # and issuing the disconnect, don't worry about it.
- # This avoids a race condition if we're mass-disconnecting peers.
- if e.error['code'] != -29: # RPC_CLIENT_NODE_NOT_CONNECTED
- raise
-
- # wait to disconnect
- wait_until(lambda: not get_peer_ids(), timeout=5)
-
-
-def connect_nodes(from_connection, node_num):
- ip_port = "127.0.0.1:" + str(p2p_port(node_num))
- from_connection.addnode(ip_port, "onetry")
- # poll until version handshake complete to avoid race conditions
- # with transaction relaying
- # See comments in net_processing:
- # * Must have a version message before anything else
- # * Must have a verack message before anything else
- wait_until(lambda: all(peer['version'] != 0 for peer in from_connection.getpeerinfo()))
- wait_until(lambda: all(peer['bytesrecv_per_msg'].pop('verack', 0) == 24 for peer in from_connection.getpeerinfo()))
-
-
# Transaction/Block functions
#############################
@@ -476,62 +444,6 @@ def find_output(node, txid, amount, *, blockhash=None):
raise RuntimeError("find_output txid %s : %s not found" % (txid, str(amount)))
-def gather_inputs(from_node, amount_needed, confirmations_required=1):
- """
- Return a random set of unspent txouts that are enough to pay amount_needed
- """
- assert confirmations_required >= 0
- utxo = from_node.listunspent(confirmations_required)
- random.shuffle(utxo)
- inputs = []
- total_in = Decimal("0.00000000")
- while total_in < amount_needed and len(utxo) > 0:
- t = utxo.pop()
- total_in += t["amount"]
- inputs.append({"txid": t["txid"], "vout": t["vout"], "address": t["address"]})
- if total_in < amount_needed:
- raise RuntimeError("Insufficient funds: need %d, have %d" % (amount_needed, total_in))
- return (total_in, inputs)
-
-
-def make_change(from_node, amount_in, amount_out, fee):
- """
- Create change output(s), return them
- """
- outputs = {}
- amount = amount_out + fee
- change = amount_in - amount
- if change > amount * 2:
- # Create an extra change output to break up big inputs
- change_address = from_node.getnewaddress()
- # Split change in two, being careful of rounding:
- outputs[change_address] = Decimal(change / 2).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
- change = amount_in - amount - outputs[change_address]
- if change > 0:
- outputs[from_node.getnewaddress()] = change
- return outputs
-
-
-def random_transaction(nodes, amount, min_fee, fee_increment, fee_variants):
- """
- Create a random transaction.
- Returns (txid, hex-encoded-transaction-data, fee)
- """
- from_node = random.choice(nodes)
- to_node = random.choice(nodes)
- fee = min_fee + fee_increment * random.randint(0, fee_variants)
-
- (total_in, inputs) = gather_inputs(from_node, amount + fee)
- outputs = make_change(from_node, total_in, amount, fee)
- outputs[to_node.getnewaddress()] = float(amount)
-
- rawtx = from_node.createrawtransaction(inputs, outputs)
- signresult = from_node.signrawtransactionwithwallet(rawtx)
- txid = from_node.sendrawtransaction(signresult["hex"], 0)
-
- return (txid, signresult["hex"], fee)
-
-
# Helper to create at least "count" utxos
# Pass in a fee that is sufficient for relay and mining new transactions.
def create_confirmed_utxos(fee, node, count):