Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_framework/avatools.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2021 The Bitcoin ABC developers | # Copyright (c) 2021 The Bitcoin ABC developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
"""Utilities for avalanche tests.""" | """Utilities for avalanche tests.""" | ||||
from typing import Any, Optional, List, Dict | from typing import Any, Optional, List, Dict | ||||
from .messages import ( | |||||
CTransaction, | |||||
FromHex, | |||||
ToHex | |||||
) | |||||
from .test_node import TestNode | from .test_node import TestNode | ||||
from .util import satoshi_round | |||||
def get_stakes(node: TestNode, | def get_coinbase_stakes(node: TestNode, | ||||
blockhashes: List[str], | blockhashes: List[str], | ||||
priv_key: str, | priv_key: str, | ||||
amount: Optional[str] = None) -> List[Dict[str, Any]]: | amount: Optional[str] = None) -> List[Dict[str, Any]]: | ||||
"""Returns a list of dictionaries representing stakes, in a format | """Returns a list of dictionaries representing stakes, in a format | ||||
compatible with the buildavalancheproof RPC. | compatible with the buildavalancheproof RPC, using only coinbase | ||||
transactions. | |||||
:param node: Test node used to get the block and coinbase data. | :param node: Test node used to get the block and coinbase data. | ||||
:param blockhashes: List of block hashes, whose coinbase tx will be used | :param blockhashes: List of block hashes, whose coinbase tx will be used | ||||
as a stake. | as a stake. | ||||
:param priv_key: Private key controlling the coinbase UTXO | :param priv_key: Private key controlling the coinbase UTXO | ||||
:param amount: If specified, this overwrites the amount information | :param amount: If specified, this overwrites the amount information | ||||
in the coinbase dicts. | in the coinbase dicts. | ||||
""" | """ | ||||
Show All 10 Lines | def get_coinbase_stakes(node: TestNode, | ||||
return [{ | return [{ | ||||
'txid': coinbase['txid'], | 'txid': coinbase['txid'], | ||||
'vout': coinbase['n'], | 'vout': coinbase['n'], | ||||
'amount': amount or coinbase['value'], | 'amount': amount or coinbase['value'], | ||||
'height': coinbase['height'], | 'height': coinbase['height'], | ||||
'iscoinbase': True, | 'iscoinbase': True, | ||||
'privatekey': priv_key, | 'privatekey': priv_key, | ||||
} for coinbase in coinbases] | } for coinbase in coinbases] | ||||
def get_stakes(node: TestNode, count: int) -> List[Dict[str, Any]]: | |||||
""" | |||||
Generate and return a list of stakes by mining enough blocks and splitting | |||||
each coinbase transaction into 10 coins. | |||||
This function can generate more valid stakes than `get_coinbase_stakes` | |||||
does, because on the regtest chain halving happens every 150 blocks so | |||||
the coinbase amount is below the dust threshold after only 900 blocks. | |||||
:param node: Test node used to generate blocks and send transactions | |||||
:param count: Number of stakes to generate. | |||||
""" | |||||
node.generate(int(0.1 * count) + 101) | |||||
utxos = node.listunspent() | |||||
addresses = [node.getnewaddress() for _ in range(10)] | |||||
for i in range(count // 10 + 1): | |||||
u = utxos.pop() | |||||
inputs = [{"txid": u["txid"], "vout": u["vout"]}] | |||||
outputs = { | |||||
addr: satoshi_round(u['amount'] / 10) for addr in addresses} | |||||
raw_tx = node.createrawtransaction(inputs, outputs) | |||||
ctx = FromHex(CTransaction(), raw_tx) | |||||
ctx.vout[0].nValue -= node.calculate_fee(ctx) | |||||
signed_tx = node.signrawtransactionwithwallet(ToHex(ctx))["hex"] | |||||
node.sendrawtransaction(signed_tx) | |||||
while node.getmempoolinfo()['size'] > 0: | |||||
node.generate(1) | |||||
utxos = node.listunspent() | |||||
stakes = [] | |||||
for utxo in utxos: | |||||
blockhash = node.gettransaction(utxo["txid"])["blockhash"] | |||||
stakes.append({ | |||||
'txid': utxo['txid'], | |||||
'vout': utxo['vout'], | |||||
'amount': utxo['amount'], | |||||
'iscoinbase': utxo['label'] == "coinbase", | |||||
'height': node.getblock(blockhash, 1)["height"], | |||||
'privatekey': node.dumpprivkey(utxo["address"]), | |||||
}) | |||||
return stakes[:count] |