Skip to content

Commit f033a98

Browse files
committed
Merge bitcoin/bitcoin#28139: test: create wallet specific for test_locked_wallet case
c648bdb test: create wallet specific for test_locked_wallet case (furszy) Pull request description: Coming from bitcoin/bitcoin#28089 (comment). Several test cases are relying on the node1 default wallet, which thanks to 'test_locked_wallet' is encrypted. And can be only accessed within a specific timeframe (100ms), a duration internally set by the same test. This situation introduces a potential race condition, where other tests must complete their operations within the specified 100ms window to pass (otherwise the wallet gets re-locked and they fail). This can be seen running the test in valgrind (bitcoin/bitcoin#28089), where other test cases fail due the wallet re-locking itself after the 100ms. ACKs for top commit: MarcoFalke: lgtm ACK c648bdb ishaanam: utACK c648bdb Tree-SHA512: 01cde5a4a0cb3405adb9ea3c1f73841f3fa237d1162268ed06f0d49ca38541006b423a029e0b5e5955e1aa7e018c4600d894e555a68cf17ff60a4b8be58f4aa9
2 parents c2ff87e + c648bdb commit f033a98

File tree

1 file changed

+39
-22
lines changed

1 file changed

+39
-22
lines changed

test/functional/wallet_fundrawtransaction.py

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -581,11 +581,20 @@ def test_spend_2of2(self):
581581
def test_locked_wallet(self):
582582
self.log.info("Test fundrawtxn with locked wallet and hardened derivation")
583583

584-
self.nodes[1].encryptwallet("test")
584+
df_wallet = self.nodes[1].get_wallet_rpc(self.default_wallet_name)
585+
self.nodes[1].createwallet(wallet_name="locked_wallet", descriptors=self.options.descriptors)
586+
wallet = self.nodes[1].get_wallet_rpc("locked_wallet")
587+
588+
# Add some balance to the wallet (this will be reverted at the end of the test)
589+
df_wallet.sendall(recipients=[wallet.getnewaddress()])
590+
self.generate(self.nodes[1], 1)
591+
592+
# Encrypt wallet and import descriptors
593+
wallet.encryptwallet("test")
585594

586595
if self.options.descriptors:
587-
self.nodes[1].walletpassphrase('test', 10)
588-
self.nodes[1].importdescriptors([{
596+
wallet.walletpassphrase('test', 10)
597+
wallet.importdescriptors([{
589598
'desc': descsum_create('wpkh(tprv8ZgxMBicQKsPdYeeZbPSKd2KYLmeVKtcFA7kqCxDvDR13MQ6us8HopUR2wLcS2ZKPhLyKsqpDL2FtL73LMHcgoCL7DXsciA8eX8nbjCR2eG/0h/*h)'),
590599
'timestamp': 'now',
591600
'active': True
@@ -596,49 +605,57 @@ def test_locked_wallet(self):
596605
'active': True,
597606
'internal': True
598607
}])
599-
self.nodes[1].walletlock()
608+
wallet.walletlock()
600609

601610
# Drain the keypool.
602-
self.nodes[1].getnewaddress()
603-
self.nodes[1].getrawchangeaddress()
611+
wallet.getnewaddress()
612+
wallet.getrawchangeaddress()
604613

605-
# Choose 2 inputs
606-
inputs = self.nodes[1].listunspent()[0:2]
607-
value = sum(inp["amount"] for inp in inputs) - Decimal("0.00000500") # Pay a 500 sat fee
614+
# Choose input
615+
inputs = wallet.listunspent()
616+
# Deduce fee to produce a changeless transaction
617+
value = inputs[0]["amount"] - Decimal("0.00002200")
608618
outputs = {self.nodes[0].getnewaddress():value}
609-
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
619+
rawtx = wallet.createrawtransaction(inputs, outputs)
610620
# fund a transaction that does not require a new key for the change output
611-
self.nodes[1].fundrawtransaction(rawtx)
621+
funded_tx = wallet.fundrawtransaction(rawtx)
622+
assert_equal(funded_tx["changepos"], -1)
612623

613624
# fund a transaction that requires a new key for the change output
614625
# creating the key must be impossible because the wallet is locked
615626
outputs = {self.nodes[0].getnewaddress():value - Decimal("0.1")}
616-
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
617-
assert_raises_rpc_error(-4, "Transaction needs a change address, but we can't generate it.", self.nodes[1].fundrawtransaction, rawtx)
627+
rawtx = wallet.createrawtransaction(inputs, outputs)
628+
assert_raises_rpc_error(-4, "Transaction needs a change address, but we can't generate it.", wallet.fundrawtransaction, rawtx)
618629

619630
# Refill the keypool.
620-
self.nodes[1].walletpassphrase("test", 100)
621-
self.nodes[1].keypoolrefill(8) #need to refill the keypool to get an internal change address
622-
self.nodes[1].walletlock()
631+
wallet.walletpassphrase("test", 100)
632+
wallet.keypoolrefill(8) #need to refill the keypool to get an internal change address
633+
wallet.walletlock()
623634

624-
assert_raises_rpc_error(-13, "walletpassphrase", self.nodes[1].sendtoaddress, self.nodes[0].getnewaddress(), 1.2)
635+
assert_raises_rpc_error(-13, "walletpassphrase", wallet.sendtoaddress, self.nodes[0].getnewaddress(), 1.2)
625636

626637
oldBalance = self.nodes[0].getbalance()
627638

628639
inputs = []
629640
outputs = {self.nodes[0].getnewaddress():1.1}
630-
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
631-
fundedTx = self.nodes[1].fundrawtransaction(rawtx)
641+
rawtx = wallet.createrawtransaction(inputs, outputs)
642+
fundedTx = wallet.fundrawtransaction(rawtx)
643+
assert fundedTx["changepos"] != -1
632644

633645
# Now we need to unlock.
634-
self.nodes[1].walletpassphrase("test", 600)
635-
signedTx = self.nodes[1].signrawtransactionwithwallet(fundedTx['hex'])
636-
self.nodes[1].sendrawtransaction(signedTx['hex'])
646+
wallet.walletpassphrase("test", 600)
647+
signedTx = wallet.signrawtransactionwithwallet(fundedTx['hex'])
648+
wallet.sendrawtransaction(signedTx['hex'])
637649
self.generate(self.nodes[1], 1)
638650

639651
# Make sure funds are received at node1.
640652
assert_equal(oldBalance+Decimal('51.10000000'), self.nodes[0].getbalance())
641653

654+
# Restore pre-test wallet state
655+
wallet.sendall(recipients=[df_wallet.getnewaddress(), df_wallet.getnewaddress(), df_wallet.getnewaddress()])
656+
wallet.unloadwallet()
657+
self.generate(self.nodes[1], 1)
658+
642659
def test_many_inputs_fee(self):
643660
"""Multiple (~19) inputs tx test | Compare fee."""
644661
self.log.info("Test fundrawtxn fee with many inputs")

0 commit comments

Comments
 (0)