MWEB: Functional tests

This commit is contained in:
David Burkett 2022-01-29 22:23:05 -05:00 committed by Loshan T
parent fbb7fa3dc6
commit 0e1f4e1671
23 changed files with 389 additions and 34 deletions

View File

@ -33,8 +33,12 @@ class BIP68Test(BitcoinTestFramework):
[
"-acceptnonstdtxn=1",
"-peertimeout=9999", # bump because mocktime might cause a disconnect otherwise
"-vbparams=mweb:-2:0",
],
[
"-acceptnonstdtxn=0",
"-vbparams=mweb:-2:0",
],
["-acceptnonstdtxn=0"],
]
def skip_test_if_missing_module(self):

View File

@ -58,6 +58,7 @@ class BIP65Test(BitcoinTestFramework):
'-whitelist=noban@127.0.0.1',
'-par=1', # Use only one script thread to get the exact reject reason for testing
'-acceptnonstdtxn=1', # cltv_invalidate is nonstandard
'-vbparams=mweb:-2:0',
]]
self.setup_clean_chain = True
self.rpc_timeout = 480

View File

@ -43,6 +43,7 @@ class BIP66Test(BitcoinTestFramework):
self.extra_args = [[
'-whitelist=noban@127.0.0.1',
'-par=1', # Use only one script thread to get the exact log msg for testing
'-vbparams=mweb:-2:0',
]]
self.setup_clean_chain = True
self.rpc_timeout = 240

View File

@ -36,7 +36,7 @@ class MaxUploadTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 1
self.extra_args = [[
"-maxuploadtarget=800",
"-maxuploadtarget=3200",
"-acceptnonstdtxn=1",
"-peertimeout=9999", # bump because mocktime might cause a disconnect otherwise
]]
@ -90,8 +90,8 @@ class MaxUploadTest(BitcoinTestFramework):
getdata_request = msg_getdata()
getdata_request.inv.append(CInv(MSG_BLOCK, big_old_block))
max_bytes_per_day = 800*1024*1024
daily_buffer = 144 * 4000000
max_bytes_per_day = 3200*1024*1024
daily_buffer = 144 * 4000000 * 4 # MWEB uses a buffer 4x the max serialized segwit block
max_bytes_available = max_bytes_per_day - daily_buffer
success_count = max_bytes_available // old_block_size

View File

@ -46,6 +46,7 @@ class NULLDUMMYTest(BitcoinTestFramework):
self.extra_args = [[
'-segwitheight=432',
'-addresstype=legacy',
'-vbparams=mweb:-2:0',
]] * 2
def skip_test_if_missing_module(self):

View File

@ -57,17 +57,20 @@ class SegWitTest(BitcoinTestFramework):
"-rpcserialversion=0",
"-segwitheight=432",
"-addresstype=legacy",
"-vbparams=mweb:-2:0",
],
[
"-acceptnonstdtxn=1",
"-rpcserialversion=1",
"-segwitheight=432",
"-addresstype=legacy",
"-vbparams=mweb:-2:0",
],
[
"-acceptnonstdtxn=1",
"-segwitheight=432",
"-addresstype=legacy",
"-vbparams=mweb:-2:0",
],
]
self.rpc_timeout = 120

View File

@ -0,0 +1,109 @@
#!/usr/bin/env python3
# Copyright (c) 2021 The Litecoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Basic MWEB test"""
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
class MWEBBasicTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
def run_test(self):
self.log.info("Create all pre-MWEB blocks")
self.nodes[0].generate(431)
self.log.info("Pegin some coins")
addr0 = self.nodes[0].getnewaddress(address_type='mweb')
self.nodes[0].sendtoaddress(addr0, 10)
self.log.info("Create some blocks - activate MWEB")
self.nodes[0].generate(10)
self.sync_all()
self.log.info("Check for MWEB UTXOs")
utxos = [x for x in self.nodes[0].listunspent() if x['address'].startswith('tmweb')]
assert_equal(len(utxos), 2)
utxos.sort(key=lambda x: x['amount'])
utxo0 = utxos[0]
utxo1 = utxos[1]
if utxos[0]['address'] != addr0:
utxo0 = utxos[1]
utxo1 = utxos[0]
assert utxo0['amount'] == 10 and utxo0['address'] == addr0
assert 2 < utxo1['amount'] < 2.5 # change from single 12.5 LTC coinbase being spent
self.log.info("Send MWEB coins to node 1")
addr1 = self.nodes[1].getnewaddress(address_type='mweb')
tx1_hash = self.nodes[0].sendtoaddress(addr1, 5)
tx1 = self.nodes[0].getmempoolentry(tx1_hash)
self.log.info("tx1: {}".format(tx1))
self.nodes[0].generate(1)
self.sync_all()
self.log.info("Check MWEB coins are spent on node 0")
utxos = [x for x in self.nodes[0].listunspent() if x['address'].startswith('tmweb')]
assert_equal(len(utxos), 2)
assert sum(x['amount'] for x in utxos) < 45
self.log.info("Check for MWEB UTXO on node 1")
utxos = [x for x in self.nodes[1].listunspent() if x['address'].startswith('tmweb')]
assert_equal(len(utxos), 1)
assert utxos[0]['amount'] == 5 and utxos[0]['address'] == addr1
self.log.info("Send MWEB coins to node 0")
self.nodes[1].sendtoaddress(addr0, 2)
self.sync_all()
self.nodes[0].generate(1)
self.sync_all()
self.log.info("Check MWEB coins are spent on node 1")
utxos = [x for x in self.nodes[1].listunspent() if x['address'].startswith('tmweb')]
assert_equal(len(utxos), 1)
assert sum(x['amount'] for x in utxos) < 3
self.log.info("UTXO amount: {}".format(utxos[0]['amount']))
self.log.info("Check for MWEB UTXO on node 0")
utxos = self.nodes[0].listunspent(addresses=[addr0])
assert_equal(len(utxos), 1)
assert utxos[0]['amount'] == 2 and utxos[0]['address'] == addr0
self.log.info("Pegout coins on node 1")
addr2 = self.nodes[1].getnewaddress()
self.nodes[1].sendtoaddress(addr2, 2)
self.sync_all()
self.nodes[1].generate(1)
self.sync_all()
self.log.info("Check MWEB coins are spent on node 1")
utxos = [x for x in self.nodes[1].listunspent() if x['address'].startswith('tmweb')]
assert_equal(len(utxos), 1)
assert sum(x['amount'] for x in utxos) < 1
self.log.info("Mine 5 blocks. Peg-out maturity is 6 blocks, so coins shouldn't be available yet.")
self.nodes[1].generate(5)
self.sync_all()
self.log.info("Check for UTXO on node 1")
utxos = self.nodes[1].listunspent(addresses=[addr2])
assert_equal(len(utxos), 0)
self.log.info("Mine 1 more block. Peg-out coins should mature.")
self.nodes[1].generate(1)
self.sync_all()
self.log.info("Check for UTXO on node 1")
utxos = self.nodes[1].listunspent(addresses=[addr2])
assert_equal(len(utxos), 1)
assert utxos[0]['amount'] == 2 and utxos[0]['address'] == addr2
if __name__ == '__main__':
MWEBBasicTest().main()

View File

@ -0,0 +1,39 @@
#!/usr/bin/env python3
# Copyright (c) 2021 The Litecoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Verify that we can pegout all coins in the MWEB"""
from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
from test_framework.ltc_util import get_hog_addr_txout, setup_mweb_chain
class MWEBPegoutAllTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
def run_test(self):
self.log.info("Setup MWEB chain")
setup_mweb_chain(self.nodes[0])
total_balance = self.nodes[0].getbalance()
pegout_txid = self.nodes[0].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=total_balance, subtractfeefromamount=True)
pegout_tx = self.nodes[0].gettransaction(txid=pegout_txid, verbose=True)
assert_equal(len(self.nodes[0].getrawmempool()), 1)
self.nodes[0].generate(1)
assert_equal(len(self.nodes[0].getrawmempool()), 0)
self.log.info("Check that pegged in amount is 0")
hog_addr_txout = get_hog_addr_txout(self.nodes[0])
assert_equal(hog_addr_txout.nValue, 0.0)
self.log.info("Ensure we can mine the next block")
self.nodes[0].generate(1)
if __name__ == '__main__':
MWEBPegoutAllTest().main()

View File

@ -0,0 +1,65 @@
#!/usr/bin/env python3
# Copyright (c) 2014-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.
"""Test mempool re-org scenarios for MWEB transactions
Test re-org scenarios with a mempool that contains transactions
that create or spend (directly or indirectly) MWEB outputs.
"""
import json
from test_framework.blocktools import create_raw_transaction
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error
from test_framework.ltc_util import setup_mweb_chain
class MWEBReorgTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
self.extra_args = [
[
'-whitelist=noban@127.0.0.1', # immediate tx relay
],
[]
]
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
def run_test(self):
self.basic_reorg_test()
def basic_reorg_test(self):
self.log.info("Create all pre-MWEB blocks")
setup_mweb_chain(self.nodes[0])
self.log.info("Pegin some coins in pegin_tx1. pegin_tx1 should be in the mempool")
node0_mweb_addr = self.nodes[0].getnewaddress(address_type='mweb')
pegin_tx1_id = self.nodes[0].sendtoaddress(node0_mweb_addr, 100)
self.sync_all()
assert_equal(set(self.nodes[1].getrawmempool()), {pegin_tx1_id})
self.log.info("Mine pegin_tx1 in block0a, and mine a few blocks on top. mempool should be empty")
block0a = self.nodes[0].generate(4)[0]
self.sync_all()
assert_equal(len(self.nodes[1].getrawmempool()), 0)
self.log.info("Invalidate block0a. pegin_tx1 should be back in the mempool")
self.nodes[1].invalidateblock(block0a)
assert_equal(set(self.nodes[1].getrawmempool()), {pegin_tx1_id})
self.log.info("Generate block0b. pegin_tx1 should be included in the block")
block0b_hash = self.nodes[1].generate(1)[0]
block0b_txs = self.nodes[1].getblock(block0b_hash, 2)['tx']
assert_equal(len(block0b_txs), 3)
assert_equal(block0b_txs[1]['txid'], pegin_tx1_id)
if __name__ == '__main__':
MWEBReorgTest().main()

View File

@ -0,0 +1,80 @@
#!/usr/bin/env python3
# Copyright (c) 2021 The Litecoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""MWEB block weight test"""
from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
class MWEBWeightTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.rpc_timeout = 120
self.num_nodes = 3
self.extra_args = [["-spendzeroconfchange=0"]] * self.num_nodes
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
def run_test(self):
self.log.info("Create some blocks")
self.nodes[0].generate(101)
self.log.info("Pegin some coins - activate MWEB")
addr = self.nodes[0].getnewaddress(address_type='mweb')
self.nodes[0].sendtoaddress(addr, 1)
self.sync_all()
self.nodes[1].generate(700)
self.sync_all()
# Workaround for syncing issue
self.nodes[2].generate(1)
self.sync_all()
self.nodes[2].generate(700)
self.sync_all()
# Max number of MWEB transactions in a block (21000/39)
tx_limit = 538
self.log.info("Create transactions up to the max block weight")
addr = self.nodes[0].getnewaddress(address_type='mweb')
for x in range(0, tx_limit):
self.nodes[1].sendtoaddress(addr, 1)
assert_equal(len(self.nodes[1].getrawmempool()), tx_limit)
self.log.info("Create a block")
self.nodes[1].generate(1)
self.sync_all()
self.log.info("Check mempool is empty")
assert_equal(len(self.nodes[1].getrawmempool()), 0)
self.log.info("Check UTXOs have matured")
utxos = self.nodes[0].listunspent(addresses=[addr])
assert_equal(len(utxos), tx_limit)
assert all(x['amount'] == 1 and x['spendable'] for x in utxos)
self.log.info("Create transactions exceeding the max block weight")
addr = self.nodes[0].getnewaddress(address_type='mweb')
for x in range(0, tx_limit + 1):
self.nodes[2].sendtoaddress(addr, 0.01)
assert_equal(len(self.nodes[2].getrawmempool()), tx_limit + 1)
self.log.info("Create a block")
self.nodes[2].generate(1)
self.sync_all()
self.log.info("Check mempool is not empty")
assert_equal(len(self.nodes[2].getrawmempool()), 1)
self.log.info("Check UTXOs have matured")
utxos = self.nodes[0].listunspent(addresses=[addr])
assert_equal(len(utxos), tx_limit)
assert all(x['amount'] == Decimal('0.01') and x['spendable'] for x in utxos)
if __name__ == '__main__':
MWEBWeightTest().main()

View File

@ -45,8 +45,8 @@ class CompactFiltersTest(BitcoinTestFramework):
self.rpc_timeout = 480
self.num_nodes = 2
self.extra_args = [
["-blockfilterindex", "-peerblockfilters"],
["-blockfilterindex"],
["-blockfilterindex", "-peerblockfilters", "-vbparams=mweb:-2:0"],
["-blockfilterindex", "-vbparams=mweb:-2:0"],
]
def run_test(self):

View File

@ -99,6 +99,7 @@ class CompactBlocksTest(BitcoinTestFramework):
self.num_nodes = 1
self.extra_args = [[
"-acceptnonstdtxn=1",
"-vbparams=mweb:-2:0",
]]
self.utxos = []

View File

@ -4,11 +4,11 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Tests NODE_NETWORK_LIMITED.
Tests that a node configured with -prune=550 signals NODE_NETWORK_LIMITED correctly
Tests that a node configured with -prune=2200 signals NODE_NETWORK_LIMITED correctly
and that it responds to getdata requests for blocks correctly:
- send a block within 288 + 2 of the tip
- disconnect peers who request blocks older than that."""
from test_framework.messages import CInv, MSG_BLOCK, msg_getdata, msg_verack, NODE_NETWORK_LIMITED, NODE_WITNESS
from test_framework.messages import CInv, MSG_BLOCK, msg_getdata, msg_verack, NODE_NETWORK_LIMITED, NODE_WITNESS, NODE_MWEB
from test_framework.p2p import P2PInterface
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@ -35,7 +35,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 3
self.extra_args = [['-prune=550', '-addrmantest'], [], []]
self.extra_args = [['-prune=2200', '-addrmantest'], [], []]
def disconnect_all(self):
self.disconnect_nodes(0, 1)
@ -49,7 +49,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
def run_test(self):
node = self.nodes[0].add_p2p_connection(P2PIgnoreInv())
expected_services = NODE_WITNESS | NODE_NETWORK_LIMITED
expected_services = NODE_WITNESS | NODE_MWEB | NODE_NETWORK_LIMITED
self.log.info("Check that node has signalled expected services.")
assert_equal(node.nServices, expected_services)

View File

@ -56,6 +56,7 @@ from test_framework.script import (
OP_0,
OP_1,
OP_2,
OP_8,
OP_16,
OP_2DROP,
OP_CHECKMULTISIG,
@ -220,9 +221,9 @@ class SegWitTest(BitcoinTestFramework):
self.num_nodes = 3
# This test tests SegWit both pre and post-activation, so use the normal BIP9 activation.
self.extra_args = [
["-acceptnonstdtxn=1", "-segwitheight={}".format(SEGWIT_HEIGHT), "-whitelist=noban@127.0.0.1", "-mempoolreplacement=1"],
["-acceptnonstdtxn=0", "-segwitheight={}".format(SEGWIT_HEIGHT), "-mempoolreplacement=1"],
["-acceptnonstdtxn=1", "-segwitheight=-1", "-mempoolreplacement=1"],
["-acceptnonstdtxn=1", "-segwitheight={}".format(SEGWIT_HEIGHT), "-whitelist=noban@127.0.0.1", "-mempoolreplacement=1", "-vbparams=mweb:0:0"],
["-acceptnonstdtxn=0", "-segwitheight={}".format(SEGWIT_HEIGHT), "-mempoolreplacement=1", "-vbparams=mweb:0:0"],
["-acceptnonstdtxn=1", "-segwitheight=-1", "-mempoolreplacement=1", "-vbparams=mweb:0:0"],
]
self.supports_cli = False
@ -1400,6 +1401,10 @@ class SegWitTest(BitcoinTestFramework):
witness_hash = sha256(witness_program)
assert_equal(len(self.nodes[1].getrawmempool()), 0)
for version in list(range(OP_1, OP_16 + 1)) + [OP_0]:
# MWEB: We no longer allow version byte of 8 for segwit outputs except for first output (HogAddr) of HogEx txs.
#if version == OP_8:
# continue
# First try to spend to a future version segwit script_pubkey.
if version == OP_1:
# Don't use 32-byte v1 witness (used by Taproot; see BIP 341)

View File

@ -50,10 +50,11 @@ class BlockchainTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 1
self.supports_cli = False
self.extra_args=[['-vbparams=mweb:-2:0']]
def run_test(self):
self.mine_chain()
self.restart_node(0, extra_args=['-stopatheight=207', '-prune=1']) # Set extra args with pruning after rescan is complete
self.restart_node(0, extra_args=['-stopatheight=207', '-prune=1', '-vbparams=mweb:-2:0']) # Set extra args with pruning after rescan is complete
self._test_getblockchaininfo()
self._test_getchaintxstats()
@ -112,16 +113,16 @@ class BlockchainTest(BitcoinTestFramework):
# should have exact keys
assert_equal(sorted(res.keys()), keys)
self.restart_node(0, ['-stopatheight=207', '-prune=550'])
self.restart_node(0, ['-stopatheight=207', '-prune=2200', '-vbparams=mweb:-2:0'])
res = self.nodes[0].getblockchaininfo()
# result should have these additional pruning keys if prune=550
# result should have these additional pruning keys if prune=2200
assert_equal(sorted(res.keys()), sorted(['pruneheight', 'automatic_pruning', 'prune_target_size'] + keys))
# check related fields
assert res['pruned']
assert_equal(res['pruneheight'], 0)
assert res['automatic_pruning']
assert_equal(res['prune_target_size'], 576716800)
assert_equal(res['prune_target_size'], 2306867200)
assert_greater_than(res['size_on_disk'], 0)
assert_equal(res['softforks'], {

View File

@ -31,7 +31,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.setup_clean_chain = True
# This test isn't testing tx relay. Set whitelist on the peers for
# instant tx relay.
self.extra_args = [['-whitelist=noban@127.0.0.1']] * self.num_nodes
self.extra_args = [['-whitelist=noban@127.0.0.1', '-vbparams=mweb:-2:0']] * self.num_nodes
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@ -533,6 +533,12 @@ class RawTransactionsTest(BitcoinTestFramework):
}])
self.nodes[1].walletlock()
# MWEB: We don't update hd seed when encrypting wallet, so new keypool was not generated.
# We need to refill keypool manually.
self.nodes[1].walletpassphrase('test', 10)
self.nodes[1].keypoolrefill(1)
self.nodes[1].walletlock()
# Drain the keypool.
self.nodes[1].getnewaddress()
self.nodes[1].getrawchangeaddress()

View File

@ -20,6 +20,7 @@ class SignRawTransactionsTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
self.extra_args=[['-vbparams=mweb:-2:0'],['-vbparams=mweb:-2:0']]
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()

View File

@ -52,4 +52,22 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=DUMMY_P2WPKH_SCRIPT):
assert new_size < mempool_size
mempool_size = new_size
return COutPoint(int(txid, 16), 0)
return COutPoint(int(txid, 16), 0)
def setup_mweb_chain(node):
# Create all pre-MWEB blocks
node.generate(431)
# Pegin some coins
node.sendtoaddress(node.getnewaddress(address_type='mweb'), 1)
# Create some blocks - activate MWEB
node.generate(1)
def get_hog_addr_txout(node):
best_block = node.getblock(node.getbestblockhash(), 2)
hogex_tx = best_block['tx'][-1] # TODO: Should validate that the tx is marked as a hogex tx
hog_addr = hogex_tx['vout'][0]
return CTxOut(hog_addr['value'], hog_addr['scriptPubKey'])

View File

@ -57,6 +57,7 @@ NODE_BLOOM = (1 << 2)
NODE_WITNESS = (1 << 3)
NODE_COMPACT_FILTERS = (1 << 6)
NODE_NETWORK_LIMITED = (1 << 10)
NODE_MWEB = (1 << 24)
MSG_TX = 1
MSG_BLOCK = 2

View File

@ -79,6 +79,7 @@ TEST_FRAMEWORK_MODULES = [
EXTENDED_SCRIPTS = [
# These tests are not run by default.
# Longest test should go first, to favor running tests in parallel
'mweb_weight.py',
'feature_pruning.py',
'feature_dbcrash.py',
]
@ -244,6 +245,9 @@ BASE_SCRIPTS = [
'wallet_scriptaddress2.py',
'feature_dersig.py',
'feature_cltv.py',
'mweb_basic.py',
'mweb_reorg.py',
'mweb_pegout_all.py'
'rpc_uptime.py',
'wallet_resendwallettransactions.py',
'wallet_resendwallettransactions.py --descriptors',
@ -683,7 +687,7 @@ class TestResult():
def check_script_prefixes():
"""Check that test scripts start with one of the allowed name prefixes."""
good_prefixes_re = re.compile("^(example|feature|interface|mempool|mining|p2p|rpc|wallet|tool|ltc)_")
good_prefixes_re = re.compile("(example|feature|interface|mempool|mining|p2p|rpc|wallet|tool|ltc|mweb)_")
bad_script_names = [script for script in ALL_SCRIPTS if good_prefixes_re.match(script) is None]
if bad_script_names:

View File

@ -123,7 +123,7 @@ class ToolWalletTest(BitcoinTestFramework):
HD (hd seed available): yes
Keypool Size: 2
Transactions: 0
Address Book: 3
Address Book: 4
''')
self.assert_tool_output(out, '-wallet=' + self.default_wallet_name, 'info')
timestamp_after = self.wallet_timestamp()
@ -180,7 +180,7 @@ class ToolWalletTest(BitcoinTestFramework):
HD (hd seed available): yes
Keypool Size: 2
Transactions: 1
Address Book: 3
Address Book: 4
''')
self.assert_tool_output(out, '-wallet=' + self.default_wallet_name, 'info')
shasum_after = self.wallet_shasum()

View File

@ -25,6 +25,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
found_p2sh_segwit_addr = 0
found_bech32_addr = 0
found_script_addr = 0
found_mweb_addr = 0
found_addr_chg = 0
found_addr_rsv = 0
hd_master_addr_ret = None
@ -55,8 +56,9 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
# ensure the old master is still available
assert hd_master_addr_old == addr
elif keytype == "hdseed=1":
# ensure we have generated a new hd master key
assert hd_master_addr_old != addr
if hd_master_addr_old != None:
# MWEB: No new seed is generated when encrypting, so assert hd master key is unchanged
assert hd_master_addr_old == addr
hd_master_addr_ret = addr
elif keytype == "script=1":
# scripts don't have keypaths
@ -75,6 +77,8 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
found_p2sh_segwit_addr += 1
elif addr.startswith('rltc1'):
found_bech32_addr += 1
elif addr.startswith('tmweb'):
found_mweb_addr += 1
break
elif keytype == "change=1":
found_addr_chg += 1
@ -89,7 +93,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
found_script_addr += 1
break
return found_comments, found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret
return found_comments, found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_mweb_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret
class WalletDumpTest(BitcoinTestFramework):
@ -111,13 +115,14 @@ class WalletDumpTest(BitcoinTestFramework):
wallet_unenc_dump = os.path.join(self.nodes[0].datadir, "wallet.unencrypted.dump")
wallet_enc_dump = os.path.join(self.nodes[0].datadir, "wallet.encrypted.dump")
# generate 30 addresses to compare against the dump
# generate 40 addresses to compare against the dump
# - 10 legacy P2PKH
# - 10 P2SH-segwit
# - 10 bech32
# - 10 mweb
test_addr_count = 10
addrs = []
for address_type in ['legacy', 'p2sh-segwit', 'bech32']:
for address_type in ['legacy', 'p2sh-segwit', 'bech32', 'mweb']:
for _ in range(test_addr_count):
addr = self.nodes[0].getnewaddress(address_type=address_type)
vaddr = self.nodes[0].getaddressinfo(addr) # required to get hd keypath
@ -155,7 +160,7 @@ class WalletDumpTest(BitcoinTestFramework):
result = self.nodes[0].dumpwallet(wallet_unenc_dump)
assert_equal(result['filename'], wallet_unenc_dump)
found_comments, found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \
found_comments, found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_mweb_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \
read_dump(wallet_unenc_dump, addrs, [multisig_addr], None)
assert '# End of dump' in found_comments # Check that file is not corrupt
assert_equal(dump_time_str, next(c for c in found_comments if c.startswith('# * Created on')))
@ -165,8 +170,9 @@ class WalletDumpTest(BitcoinTestFramework):
assert_equal(found_p2sh_segwit_addr, test_addr_count) # all keys must be in the dump
assert_equal(found_bech32_addr, test_addr_count) # all keys must be in the dump
assert_equal(found_script_addr, 1) # all scripts must be in the dump
assert_equal(found_addr_chg, 0) # 0 blocks where mined
assert_equal(found_addr_rsv, 90 * 2) # 90 keys plus 100% internal keys
assert_equal(found_mweb_addr, test_addr_count)
assert_equal(found_addr_chg, 0 + 2) # 0 blocks were mined plus 2 initial MWEB keys (CHANGE and PEG-IN)
assert_equal(found_addr_rsv, 90 * 3) # 90 keys plus 100% internal keys and 100% MWEB keys
# encrypt wallet, restart, unlock and dump
self.nodes[0].encryptwallet('test')
@ -175,7 +181,7 @@ class WalletDumpTest(BitcoinTestFramework):
self.nodes[0].keypoolrefill()
self.nodes[0].dumpwallet(wallet_enc_dump)
found_comments, found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_addr_chg, found_addr_rsv, _ = \
found_comments, found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_mweb_addr, found_addr_chg, found_addr_rsv, _ = \
read_dump(wallet_enc_dump, addrs, [multisig_addr], hd_master_addr_unenc)
assert '# End of dump' in found_comments # Check that file is not corrupt
assert_equal(dump_time_str, next(c for c in found_comments if c.startswith('# * Created on')))
@ -185,8 +191,9 @@ class WalletDumpTest(BitcoinTestFramework):
assert_equal(found_p2sh_segwit_addr, test_addr_count) # all keys must be in the dump
assert_equal(found_bech32_addr, test_addr_count) # all keys must be in the dump
assert_equal(found_script_addr, 1)
assert_equal(found_addr_chg, 90 * 2) # old reserve keys are marked as change now
assert_equal(found_addr_rsv, 90 * 2)
assert_equal(found_mweb_addr, test_addr_count)
assert_equal(found_addr_chg, 0 + 2) # 0 blocks were mined plus 2 initial MWEB keys (CHANGE and PEG-IN)
assert_equal(found_addr_rsv, 90 * 3)
# Overwriting should fail
assert_raises_rpc_error(-8, "already exists", lambda: self.nodes[0].dumpwallet(wallet_enc_dump))

View File

@ -72,11 +72,19 @@ class KeyPoolTest(BitcoinTestFramework):
}
])
nodes[0].walletlock()
# MWEB: We don't update hd seed when encrypting wallet, so new keypool was not generated.
# We need to refill keypool manually.
self.nodes[0].walletpassphrase('test', 10)
self.nodes[0].keypoolrefill(1)
self.nodes[0].walletlock()
# Keep creating keys
addr = nodes[0].getnewaddress()
addr_data = nodes[0].getaddressinfo(addr)
wallet_info = nodes[0].getwalletinfo()
assert addr_before_encrypting_data['hdmasterfingerprint'] != addr_data['hdmasterfingerprint']
# MWEB: We don't update hd seed when encrypting wallet, so fingerprint shouldn't change
assert addr_before_encrypting_data['hdmasterfingerprint'] == addr_data['hdmasterfingerprint']
if not self.options.descriptors:
assert addr_data['hdseedid'] == wallet_info['hdseedid']
assert_raises_rpc_error(-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress)