mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-29 07:18:58 +01:00
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:
@@ -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()
|
||||||
|
|||||||
@@ -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 = []
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
Reference in New Issue
Block a user