test: use MiniWallet for rpc_createmultisig.py

This test can now be run even with the Bitcoin Core wallet disabled.
This commit is contained in:
Ayush Sharma
2022-03-22 14:17:51 +05:30
parent 3617d22562
commit 2726b60a3a
3 changed files with 62 additions and 45 deletions

View File

@@ -18,15 +18,18 @@ from test_framework.util import (
assert_equal, assert_equal,
) )
from test_framework.wallet_util import bytes_to_wif from test_framework.wallet_util import bytes_to_wif
from test_framework.wallet import (
MiniWallet,
getnewdestination,
)
class RpcCreateMultiSigTest(BitcoinTestFramework): class RpcCreateMultiSigTest(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.setup_clean_chain = True self.setup_clean_chain = True
self.num_nodes = 3 self.num_nodes = 3
self.supports_cli = False self.supports_cli = False
if self.is_bdb_compiled():
def skip_test_if_missing_module(self): self.requires_wallet = True
self.skip_if_no_wallet()
def get_keys(self): def get_keys(self):
self.pub = [] self.pub = []
@@ -37,15 +40,20 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
k.generate() k.generate()
self.pub.append(k.get_pubkey().get_bytes().hex()) self.pub.append(k.get_pubkey().get_bytes().hex())
self.priv.append(bytes_to_wif(k.get_bytes(), k.is_compressed)) self.priv.append(bytes_to_wif(k.get_bytes(), k.is_compressed))
self.final = node2.getnewaddress() if self.is_bdb_compiled():
self.final = node2.getnewaddress()
else:
self.final = getnewdestination()[2]
def run_test(self): def run_test(self):
node0, node1, node2 = self.nodes node0, node1, node2 = self.nodes
self.wallet = MiniWallet(test_node=node0)
self.check_addmultisigaddress_errors() if self.is_bdb_compiled():
self.check_addmultisigaddress_errors()
self.log.info('Generating blocks ...') self.log.info('Generating blocks ...')
self.generate(node0, 149) self.generate(self.wallet, 149)
self.moved = 0 self.moved = 0
for self.nkeys in [3, 5]: for self.nkeys in [3, 5]:
@@ -53,14 +61,14 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
for self.output_type in ["bech32", "p2sh-segwit", "legacy"]: for self.output_type in ["bech32", "p2sh-segwit", "legacy"]:
self.get_keys() self.get_keys()
self.do_multisig() self.do_multisig()
if self.is_bdb_compiled():
self.checkbalances() self.checkbalances()
# Test mixed compressed and uncompressed pubkeys # Test mixed compressed and uncompressed pubkeys
self.log.info('Mixed compressed and uncompressed multisigs are not allowed') self.log.info('Mixed compressed and uncompressed multisigs are not allowed')
pk0 = node0.getaddressinfo(node0.getnewaddress())['pubkey'] pk0 = getnewdestination()[0].hex()
pk1 = node1.getaddressinfo(node1.getnewaddress())['pubkey'] pk1 = getnewdestination()[0].hex()
pk2 = node2.getaddressinfo(node2.getnewaddress())['pubkey'] pk2 = getnewdestination()[0].hex()
# decompress pk2 # decompress pk2
pk_obj = ECPubKey() pk_obj = ECPubKey()
@@ -68,26 +76,30 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
pk_obj.compressed = False pk_obj.compressed = False
pk2 = pk_obj.get_bytes().hex() pk2 = pk_obj.get_bytes().hex()
node0.createwallet(wallet_name='wmulti0', disable_private_keys=True) if self.is_bdb_compiled():
wmulti0 = node0.get_wallet_rpc('wmulti0') node0.createwallet(wallet_name='wmulti0', disable_private_keys=True)
wmulti0 = node0.get_wallet_rpc('wmulti0')
# Check all permutations of keys because order matters apparently # Check all permutations of keys because order matters apparently
for keys in itertools.permutations([pk0, pk1, pk2]): for keys in itertools.permutations([pk0, pk1, pk2]):
# Results should be the same as this legacy one # Results should be the same as this legacy one
legacy_addr = node0.createmultisig(2, keys, 'legacy')['address'] legacy_addr = node0.createmultisig(2, keys, 'legacy')['address']
result = wmulti0.addmultisigaddress(2, keys, '', 'legacy')
assert_equal(legacy_addr, result['address']) if self.is_bdb_compiled():
assert 'warnings' not in result result = wmulti0.addmultisigaddress(2, keys, '', 'legacy')
assert_equal(legacy_addr, result['address'])
assert 'warnings' not in result
# Generate addresses with the segwit types. These should all make legacy addresses # Generate addresses with the segwit types. These should all make legacy addresses
for addr_type in ['bech32', 'p2sh-segwit']: for addr_type in ['bech32', 'p2sh-segwit']:
result = wmulti0.createmultisig(2, keys, addr_type) result = self.nodes[0].createmultisig(2, keys, addr_type)
assert_equal(legacy_addr, result['address']) assert_equal(legacy_addr, result['address'])
assert_equal(result['warnings'], ["Unable to make chosen address type, please ensure no uncompressed public keys are present."]) assert_equal(result['warnings'], ["Unable to make chosen address type, please ensure no uncompressed public keys are present."])
result = wmulti0.addmultisigaddress(2, keys, '', addr_type) if self.is_bdb_compiled():
assert_equal(legacy_addr, result['address']) result = wmulti0.addmultisigaddress(2, keys, '', addr_type)
assert_equal(result['warnings'], ["Unable to make chosen address type, please ensure no uncompressed public keys are present."]) assert_equal(legacy_addr, result['address'])
assert_equal(result['warnings'], ["Unable to make chosen address type, please ensure no uncompressed public keys are present."])
self.log.info('Testing sortedmulti descriptors with BIP 67 test vectors') self.log.info('Testing sortedmulti descriptors with BIP 67 test vectors')
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/rpc_bip67.json'), encoding='utf-8') as f: with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/rpc_bip67.json'), encoding='utf-8') as f:
@@ -126,26 +138,29 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
bal0 = node0.getbalance() bal0 = node0.getbalance()
bal1 = node1.getbalance() bal1 = node1.getbalance()
bal2 = node2.getbalance() bal2 = node2.getbalance()
balw = self.wallet.get_balance()
height = node0.getblockchaininfo()["blocks"] height = node0.getblockchaininfo()["blocks"]
assert 150 < height < 350 assert 150 < height < 350
total = 149 * 50 + (height - 149 - 100) * 25 total = 149 * 50 + (height - 149 - 100) * 25
assert bal1 == 0 assert bal1 == 0
assert bal2 == self.moved assert bal2 == self.moved
assert bal0 + bal1 + bal2 == total assert_equal(bal0 + bal1 + bal2 + balw, total)
def do_multisig(self): def do_multisig(self):
node0, node1, node2 = self.nodes node0, node1, node2 = self.nodes
if 'wmulti' not in node1.listwallets():
try: if self.is_bdb_compiled():
node1.loadwallet('wmulti') if 'wmulti' not in node1.listwallets():
except JSONRPCException as e: try:
path = os.path.join(self.options.tmpdir, "node1", "regtest", "wallets", "wmulti") node1.loadwallet('wmulti')
if e.error['code'] == -18 and "Wallet file verification failed. Failed to load database path '{}'. Path does not exist.".format(path) in e.error['message']: except JSONRPCException as e:
node1.createwallet(wallet_name='wmulti', disable_private_keys=True) path = os.path.join(self.options.tmpdir, "node1", "regtest", "wallets", "wmulti")
else: if e.error['code'] == -18 and "Wallet file verification failed. Failed to load database path '{}'. Path does not exist.".format(path) in e.error['message']:
raise node1.createwallet(wallet_name='wmulti', disable_private_keys=True)
wmulti = node1.get_wallet_rpc('wmulti') else:
raise
wmulti = node1.get_wallet_rpc('wmulti')
# Construct the expected descriptor # Construct the expected descriptor
desc = 'multi({},{})'.format(self.nsigs, ','.join(self.pub)) desc = 'multi({},{})'.format(self.nsigs, ','.join(self.pub))
@@ -164,17 +179,19 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
if self.output_type == 'bech32': if self.output_type == 'bech32':
assert madd[0:4] == "bcrt" # actually a bech32 address assert madd[0:4] == "bcrt" # actually a bech32 address
# compare against addmultisigaddress if self.is_bdb_compiled():
msigw = wmulti.addmultisigaddress(self.nsigs, self.pub, None, self.output_type) # compare against addmultisigaddress
maddw = msigw["address"] msigw = wmulti.addmultisigaddress(self.nsigs, self.pub, None, self.output_type)
mredeemw = msigw["redeemScript"] maddw = msigw["address"]
assert_equal(desc, drop_origins(msigw['descriptor'])) mredeemw = msigw["redeemScript"]
# addmultisigiaddress and createmultisig work the same assert_equal(desc, drop_origins(msigw['descriptor']))
assert maddw == madd # addmultisigiaddress and createmultisig work the same
assert mredeemw == mredeem assert maddw == madd
assert mredeemw == mredeem
txid = node0.sendtoaddress(madd, 40) wmulti.unloadwallet()
spk = bytes.fromhex(node0.validateaddress(madd)["scriptPubKey"])
txid, _ = self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=spk, amount=1300)
tx = node0.getrawtransaction(txid, True) tx = node0.getrawtransaction(txid, True)
vout = [v["n"] for v in tx["vout"] if madd == v["scriptPubKey"]["address"]] vout = [v["n"] for v in tx["vout"] if madd == v["scriptPubKey"]["address"]]
assert len(vout) == 1 assert len(vout) == 1
@@ -225,8 +242,6 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
txinfo = node0.getrawtransaction(tx, True, blk) txinfo = node0.getrawtransaction(tx, True, blk)
self.log.info("n/m=%d/%d %s size=%d vsize=%d weight=%d" % (self.nsigs, self.nkeys, self.output_type, txinfo["size"], txinfo["vsize"], txinfo["weight"])) self.log.info("n/m=%d/%d %s size=%d vsize=%d weight=%d" % (self.nsigs, self.nkeys, self.output_type, txinfo["size"], txinfo["vsize"], txinfo["weight"]))
wmulti.unloadwallet()
if __name__ == '__main__': if __name__ == '__main__':
RpcCreateMultiSigTest().main() RpcCreateMultiSigTest().main()

View File

@@ -93,6 +93,9 @@ class MiniWallet:
self._address, self._internal_key = create_deterministic_address_bcrt1_p2tr_op_true() self._address, self._internal_key = create_deterministic_address_bcrt1_p2tr_op_true()
self._scriptPubKey = bytes.fromhex(self._test_node.validateaddress(self._address)['scriptPubKey']) self._scriptPubKey = bytes.fromhex(self._test_node.validateaddress(self._address)['scriptPubKey'])
def get_balance(self):
return sum(u['value'] for u in self._utxos)
def rescan_utxos(self): def rescan_utxos(self):
"""Drop all utxos and rescan the utxo set""" """Drop all utxos and rescan the utxo set"""
self._utxos = [] self._utxos = []

View File

@@ -225,8 +225,7 @@ BASE_SCRIPTS = [
'feature_rbf.py --descriptors', 'feature_rbf.py --descriptors',
'mempool_packages.py', 'mempool_packages.py',
'mempool_package_onemore.py', 'mempool_package_onemore.py',
'rpc_createmultisig.py --legacy-wallet', 'rpc_createmultisig.py',
'rpc_createmultisig.py --descriptors',
'rpc_packages.py', 'rpc_packages.py',
'mempool_package_limits.py', 'mempool_package_limits.py',
'feature_versionbits_warning.py', 'feature_versionbits_warning.py',