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.py101
1 files changed, 30 insertions, 71 deletions
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index b043d1a70d..bfc835f272 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -12,6 +12,7 @@ import inspect
import json
import logging
import os
+import random
import re
import time
import unittest
@@ -28,6 +29,10 @@ logger = logging.getLogger("TestFramework.utils")
def assert_approx(v, vexp, vspan=0.00001):
"""Assert that `v` is within `vspan` of `vexp`"""
+ if isinstance(v, Decimal) or isinstance(vexp, Decimal):
+ v=Decimal(v)
+ vexp=Decimal(vexp)
+ vspan=Decimal(vspan)
if v < vexp - vspan:
raise AssertionError("%s < [%s..%s]" % (str(v), str(vexp - vspan), str(vexp + vspan)))
if v > vexp + vspan:
@@ -286,6 +291,13 @@ def sha256sum_file(filename):
d = f.read(4096)
return h.digest()
+
+# TODO: Remove and use random.randbytes(n) instead, available in Python 3.9
+def random_bytes(n):
+ """Return a random bytes object of length n."""
+ return bytes(random.getrandbits(8) for i in range(n))
+
+
# RPC/P2P connection constants and functions
############################################
@@ -476,39 +488,6 @@ def find_output(node, txid, amount, *, blockhash=None):
raise RuntimeError("find_output txid %s : %s not found" % (txid, str(amount)))
-# Helper to create at least "count" utxos
-# Pass in a fee that is sufficient for relay and mining new transactions.
-def create_confirmed_utxos(test_framework, fee, node, count, **kwargs):
- to_generate = int(0.5 * count) + 101
- while to_generate > 0:
- test_framework.generate(node, min(25, to_generate), **kwargs)
- to_generate -= 25
- utxos = node.listunspent()
- iterations = count - len(utxos)
- addr1 = node.getnewaddress()
- addr2 = node.getnewaddress()
- if iterations <= 0:
- return utxos
- for _ in range(iterations):
- t = utxos.pop()
- inputs = []
- inputs.append({"txid": t["txid"], "vout": t["vout"]})
- outputs = {}
- send_value = t['amount'] - fee
- outputs[addr1] = satoshi_round(send_value / 2)
- outputs[addr2] = satoshi_round(send_value / 2)
- raw_tx = node.createrawtransaction(inputs, outputs)
- signed_tx = node.signrawtransactionwithwallet(raw_tx)["hex"]
- node.sendrawtransaction(signed_tx)
-
- while (node.getmempoolinfo()['size'] > 0):
- test_framework.generate(node, 1, **kwargs)
-
- utxos = node.listunspent()
- assert len(utxos) >= count
- return utxos
-
-
def chain_transaction(node, parent_txids, vouts, value, fee, num_outputs):
"""Build and send a transaction that spends the given inputs (specified
by lists of parent_txid:vout each), with the desired total value and fee,
@@ -532,45 +511,30 @@ def chain_transaction(node, parent_txids, vouts, value, fee, num_outputs):
# Create large OP_RETURN txouts that can be appended to a transaction
-# to make it large (helper for constructing large transactions).
+# to make it large (helper for constructing large transactions). The
+# total serialized size of the txouts is about 66k vbytes.
def gen_return_txouts():
- # Some pre-processing to create a bunch of OP_RETURN txouts to insert into transactions we create
- # So we have big transactions (and therefore can't fit very many into each block)
- # create one script_pubkey
- script_pubkey = "6a4d0200" # OP_RETURN OP_PUSH2 512 bytes
- for _ in range(512):
- script_pubkey = script_pubkey + "01"
- # concatenate 128 txouts of above script_pubkey which we'll insert before the txout for change
- txouts = []
from .messages import CTxOut
- txout = CTxOut()
- txout.nValue = 0
- txout.scriptPubKey = bytes.fromhex(script_pubkey)
- for _ in range(128):
- txouts.append(txout)
+ from .script import CScript, OP_RETURN
+ txouts = [CTxOut(nValue=0, scriptPubKey=CScript([OP_RETURN, b'\x01'*67437]))]
+ assert_equal(sum([len(txout.serialize()) for txout in txouts]), 67456)
return txouts
# Create a spend of each passed-in utxo, splicing in "txouts" to each raw
# transaction to make it large. See gen_return_txouts() above.
-def create_lots_of_big_transactions(node, txouts, utxos, num, fee):
- addr = node.getnewaddress()
+def create_lots_of_big_transactions(mini_wallet, node, fee, tx_batch_size, txouts, utxos=None):
txids = []
- from .messages import tx_from_hex
- for _ in range(num):
- t = utxos.pop()
- inputs = [{"txid": t["txid"], "vout": t["vout"]}]
- outputs = {}
- change = t['amount'] - fee
- outputs[addr] = satoshi_round(change)
- rawtx = node.createrawtransaction(inputs, outputs)
- tx = tx_from_hex(rawtx)
- for txout in txouts:
- tx.vout.append(txout)
- newtx = tx.serialize().hex()
- signresult = node.signrawtransactionwithwallet(newtx, None, "NONE")
- txid = node.sendrawtransaction(signresult["hex"], 0)
- txids.append(txid)
+ use_internal_utxos = utxos is None
+ for _ in range(tx_batch_size):
+ tx = mini_wallet.create_self_transfer(
+ utxo_to_spend=None if use_internal_utxos else utxos.pop(),
+ fee=fee,
+ )["tx"]
+ tx.vout.extend(txouts)
+ res = node.testmempoolaccept([tx.serialize().hex()])[0]
+ assert_equal(res['fees']['base'], fee)
+ txids.append(node.sendrawtransaction(tx.serialize().hex()))
return txids
@@ -578,13 +542,8 @@ def mine_large_block(test_framework, mini_wallet, node):
# generate a 66k transaction,
# and 14 of them is close to the 1MB block limit
txouts = gen_return_txouts()
- from .messages import COIN
- fee = 100 * int(node.getnetworkinfo()["relayfee"] * COIN)
- for _ in range(14):
- tx = mini_wallet.create_self_transfer(from_node=node, fee_rate=0, mempool_valid=False)['tx']
- tx.vout[0].nValue -= fee
- tx.vout.extend(txouts)
- mini_wallet.sendrawtransaction(from_node=node, tx_hex=tx.serialize().hex())
+ fee = 100 * node.getnetworkinfo()["relayfee"]
+ create_lots_of_big_transactions(mini_wallet, node, fee, 14, txouts)
test_framework.generate(node, 1)