Changeset View
Changeset View
Standalone View
Standalone View
test/functional/wallet_keypool.py
Show All 17 Lines | def skip_test_if_missing_module(self): | ||||
self.skip_if_no_wallet() | self.skip_if_no_wallet() | ||||
def run_test(self): | def run_test(self): | ||||
nodes = self.nodes | nodes = self.nodes | ||||
addr_before_encrypting = nodes[0].getnewaddress() | addr_before_encrypting = nodes[0].getnewaddress() | ||||
addr_before_encrypting_data = nodes[ | addr_before_encrypting_data = nodes[ | ||||
0].getaddressinfo(addr_before_encrypting) | 0].getaddressinfo(addr_before_encrypting) | ||||
wallet_info_old = nodes[0].getwalletinfo() | wallet_info_old = nodes[0].getwalletinfo() | ||||
assert addr_before_encrypting_data[ | if not self.options.descriptors: | ||||
'hdseedid'] == wallet_info_old['hdseedid'] | assert addr_before_encrypting_data['hdseedid'] == \ | ||||
wallet_info_old['hdseedid'] | |||||
# Encrypt wallet and wait to terminate | # Encrypt wallet and wait to terminate | ||||
nodes[0].encryptwallet('test') | nodes[0].encryptwallet('test') | ||||
if self.options.descriptors: | |||||
# Import hardened derivation only descriptors | |||||
nodes[0].walletpassphrase('test', 10) | |||||
nodes[0].importdescriptors([ | |||||
{ | |||||
"desc": "pkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/*h)#dfe4u060", | |||||
"timestamp": "now", | |||||
"range": [0, 0], | |||||
"active": True | |||||
}, | |||||
{ | |||||
"desc": "pkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/2h/*h)#y9d74xe5", | |||||
"timestamp": "now", | |||||
"range": [0, 0], | |||||
"active": True, | |||||
"internal": True | |||||
}, | |||||
]) | |||||
nodes[0].walletlock() | |||||
# Keep creating keys | # Keep creating keys | ||||
addr = nodes[0].getnewaddress() | addr = nodes[0].getnewaddress() | ||||
addr_data = nodes[0].getaddressinfo(addr) | addr_data = nodes[0].getaddressinfo(addr) | ||||
wallet_info = nodes[0].getwalletinfo() | wallet_info = nodes[0].getwalletinfo() | ||||
assert addr_before_encrypting_data[ | assert addr_before_encrypting_data['hdmasterfingerprint'] != \ | ||||
'hdseedid'] != wallet_info['hdseedid'] | addr_data['hdmasterfingerprint'] | ||||
if not self.options.descriptors: | |||||
assert addr_data['hdseedid'] == wallet_info['hdseedid'] | assert addr_data['hdseedid'] == wallet_info['hdseedid'] | ||||
assert_raises_rpc_error( | assert_raises_rpc_error( | ||||
-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress) | -12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress) | ||||
# put six (plus 2) new keys in the keypool (100% external-, +100% | # put six (plus 2) new keys in the keypool (100% external-, +100% | ||||
# internal-keys, 1 in min) | # internal-keys, 1 in min) | ||||
nodes[0].walletpassphrase('test', 12000) | nodes[0].walletpassphrase('test', 12000) | ||||
nodes[0].keypoolrefill(6) | nodes[0].keypoolrefill(6) | ||||
nodes[0].walletlock() | nodes[0].walletlock() | ||||
wi = nodes[0].getwalletinfo() | wi = nodes[0].getwalletinfo() | ||||
# This would be 18 for Core if using --descriptors. But we don't have | |||||
# the BECH32 and P2SH_SEGWIT keypools. | |||||
assert_equal(wi['keypoolsize_hd_internal'], 6) | assert_equal(wi['keypoolsize_hd_internal'], 6) | ||||
assert_equal(wi['keypoolsize'], 6) | assert_equal(wi['keypoolsize'], 6) | ||||
# drain the internal keys | # drain the internal keys | ||||
nodes[0].getrawchangeaddress() | nodes[0].getrawchangeaddress() | ||||
nodes[0].getrawchangeaddress() | nodes[0].getrawchangeaddress() | ||||
nodes[0].getrawchangeaddress() | nodes[0].getrawchangeaddress() | ||||
nodes[0].getrawchangeaddress() | nodes[0].getrawchangeaddress() | ||||
Show All 27 Lines | def run_test(self): | ||||
# drain the keypool | # drain the keypool | ||||
for _ in range(3): | for _ in range(3): | ||||
nodes[0].getnewaddress() | nodes[0].getnewaddress() | ||||
assert_raises_rpc_error(-12, "Keypool ran out", nodes[0].getnewaddress) | assert_raises_rpc_error(-12, "Keypool ran out", nodes[0].getnewaddress) | ||||
nodes[0].walletpassphrase('test', 100) | nodes[0].walletpassphrase('test', 100) | ||||
nodes[0].keypoolrefill(100) | nodes[0].keypoolrefill(100) | ||||
wi = nodes[0].getwalletinfo() | wi = nodes[0].getwalletinfo() | ||||
# This would be 300 for Core if using --descriptors. But we don't have | |||||
# the BECH32 and P2SH_SEGWIT keypools. | |||||
assert_equal(wi['keypoolsize_hd_internal'], 100) | assert_equal(wi['keypoolsize_hd_internal'], 100) | ||||
assert_equal(wi['keypoolsize'], 100) | assert_equal(wi['keypoolsize'], 100) | ||||
# create a blank wallet | # create a blank wallet | ||||
nodes[0].createwallet(wallet_name='w2', blank=True) | nodes[0].createwallet(wallet_name='w2', blank=True, | ||||
disable_private_keys=True) | |||||
w2 = nodes[0].get_wallet_rpc('w2') | w2 = nodes[0].get_wallet_rpc('w2') | ||||
# refer to initial wallet as w1 | # refer to initial wallet as w1 | ||||
w1 = nodes[0].get_wallet_rpc('') | w1 = nodes[0].get_wallet_rpc('') | ||||
# import private key and fund it | # import private key and fund it | ||||
address = addr.pop() | address = addr.pop() | ||||
privkey = w1.dumpprivkey(address) | desc = w1.getaddressinfo(address)['desc'] | ||||
res = w2.importmulti( | if self.options.descriptors: | ||||
[{'scriptPubKey': {'address': address}, 'keys': [privkey], 'timestamp': 'now'}]) | res = w2.importdescriptors([{'desc': desc, 'timestamp': 'now'}]) | ||||
else: | |||||
res = w2.importmulti([{'desc': desc, 'timestamp': 'now'}]) | |||||
assert_equal(res[0]['success'], True) | assert_equal(res[0]['success'], True) | ||||
w1.walletpassphrase('test', 100) | w1.walletpassphrase('test', 100) | ||||
res = w1.sendtoaddress(address=address, amount=100.00) | res = w1.sendtoaddress(address=address, amount=100.00) | ||||
nodes[0].generate(1) | nodes[0].generate(1) | ||||
destination = addr.pop() | destination = addr.pop() | ||||
# Using a fee rate (10 sat / byte) well above the minimum relay rate | # Using a fee rate (10 sat / byte) well above the minimum relay rate | ||||
Show All 34 Lines | def run_test(self): | ||||
options={"feeRate": 100}) | options={"feeRate": 100}) | ||||
assert_equal("psbt" in res, True) | assert_equal("psbt" in res, True) | ||||
# create a transaction without change at the maximum fee rate, such | # create a transaction without change at the maximum fee rate, such | ||||
# that the output is still spendable: | # that the output is still spendable: | ||||
res = w2.walletcreatefundedpsbt( | res = w2.walletcreatefundedpsbt( | ||||
inputs=[], | inputs=[], | ||||
outputs=[{destination: 100.00}], | outputs=[{destination: 100.00}], | ||||
options={"subtractFeeFromOutputs": [0], "feeRate": 494.90}) | options={"subtractFeeFromOutputs": [0], "feeRate": 492.39}) | ||||
assert_equal("psbt" in res, True) | assert_equal("psbt" in res, True) | ||||
assert_equal(res["fee"], Decimal("94.53")) | assert_equal(res["fee"], Decimal("94.54")) | ||||
# creating a 10,000 sat transaction with a manual change address should | # creating a 10,000 sat transaction with a manual change address should | ||||
# be possible | # be possible | ||||
res = w2.walletcreatefundedpsbt(inputs=[], | res = w2.walletcreatefundedpsbt(inputs=[], | ||||
outputs=[{destination: 100.00}], | outputs=[{destination: 100.00}], | ||||
options={"subtractFeeFromOutputs": [0], | options={"subtractFeeFromOutputs": [0], | ||||
"feeRate": 100, | "feeRate": 100, | ||||
"changeAddress": addr.pop()}) | "changeAddress": addr.pop()}) | ||||
assert_equal("psbt" in res, True) | assert_equal("psbt" in res, True) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
KeyPoolTest().main() | KeyPoolTest().main() |