#!/usr/bin/env python3 # Copyright (c) 2020 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """A limited-functionality wallet, which may replace a real wallet in tests""" from decimal import Decimal from test_framework.address import ADDRESS_BCRT1_P2WSH_OP_TRUE from test_framework.messages import ( COIN, COutPoint, CTransaction, CTxIn, CTxInWitness, CTxOut, ) from test_framework.script import ( CScript, OP_TRUE, ) from test_framework.util import ( assert_equal, hex_str_to_bytes, satoshi_round, ) class MiniWallet: def __init__(self, test_node): self._test_node = test_node self._utxos = [] self._address = ADDRESS_BCRT1_P2WSH_OP_TRUE self._scriptPubKey = hex_str_to_bytes(self._test_node.validateaddress(self._address)['scriptPubKey']) def generate(self, num_blocks): """Generate blocks with coinbase outputs to the internal address, and append the outputs to the internal list""" blocks = self._test_node.generatetoaddress(num_blocks, self._address) for b in blocks: cb_tx = self._test_node.getblock(blockhash=b, verbosity=2)['tx'][0] self._utxos.append({'txid': cb_tx['txid'], 'vout': 0, 'value': cb_tx['vout'][0]['value']}) return blocks def send_self_transfer(self, *, fee_rate, from_node): """Create and send a tx with the specified fee_rate. Fee may be exact or at most one satoshi higher than needed.""" self._utxos = sorted(self._utxos, key=lambda k: -k['value']) largest_utxo = self._utxos.pop() # Pick the largest utxo and hope it covers the fee vsize = Decimal(96) send_value = satoshi_round(largest_utxo['value'] - fee_rate * (vsize / 1000)) fee = largest_utxo['value'] - send_value assert (send_value > 0) tx = CTransaction() tx.vin = [CTxIn(COutPoint(int(largest_utxo['txid'], 16), largest_utxo['vout']))] tx.vout = [CTxOut(int(send_value * COIN), self._scriptPubKey)] tx.wit.vtxinwit = [CTxInWitness()] tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])] tx_hex = tx.serialize().hex() txid = from_node.sendrawtransaction(tx_hex) self._utxos.append({'txid': txid, 'vout': 0, 'value': send_value}) tx_info = from_node.getmempoolentry(txid) assert_equal(tx_info['vsize'], vsize) assert_equal(tx_info['fee'], fee) return {'txid': txid, 'wtxid': tx_info['wtxid'], 'hex': tx_hex}