commit ca5b93f07db2191acda93b4b674d71667dd83363
parent 772199a7668f08eb1c142104a9f7e01cfdc76b6b
Author: SomberNight <somber.night@protonmail.com>
Date: Fri, 9 Oct 2020 16:52:45 +0200
wallet: cpfp to send to a change address instead of receive address
Diffstat:
2 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/electrum/tests/test_wallet_vertical.py b/electrum/tests/test_wallet_vertical.py
@@ -979,10 +979,10 @@ class TestWalletSending(TestCaseForTestnet):
self.assertEqual(tx.txid(), tx_copy.txid())
self.assertEqual(tx.wtxid(), tx_copy.wtxid())
- self.assertEqual('010000000168368aeb2fba618b62c8b64d03513b6185f58623433439b649a3af1889bf7399000000006a473044022076523e03cdb6a563e10481150a10f1221b71bd5f9696b9ee8e68f3fad33431b602203d698e0d23caa9a7249d3cf0d093f9db3ded4f5d822b79762023f6a6af8171a0012102a7536f0bfbc60c5a8e86e2b9df26431fc062f9f454016dbc26f2467e0bc98b3ffdffffff01f0874b00000000001976a91472e34cebab371967b038ce41d0e8fa1fb983795e88acbe391400',
+ self.assertEqual('010000000168368aeb2fba618b62c8b64d03513b6185f58623433439b649a3af1889bf7399000000006a473044022014139c4c8dd4148851c1306c4901b759799e87a22885a3c23f6a6472a3c580dd02205df8037a19261a80157143ee61d24b64b8f60c3cb196e36e758920669f88eb56012102a7536f0bfbc60c5a8e86e2b9df26431fc062f9f454016dbc26f2467e0bc98b3ffdffffff01f0874b00000000001976a914aab9af3fbee0ab4e5c00d53e92f66d4bcb44f1bd88acbe391400',
str(tx_copy))
- self.assertEqual('3227e795a1fb569eb8387a541ef4ae66ceebe7b8bb0b08b54594a79b19c5274d', tx_copy.txid())
- self.assertEqual('3227e795a1fb569eb8387a541ef4ae66ceebe7b8bb0b08b54594a79b19c5274d', tx_copy.wtxid())
+ self.assertEqual('c064c0dd89077de615f0ff8a626d4a62092c02649ed8266ed4c54302918e87d5', tx_copy.txid())
+ self.assertEqual('c064c0dd89077de615f0ff8a626d4a62092c02649ed8266ed4c54302918e87d5', tx_copy.wtxid())
wallet.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
self.assertEqual((0, funding_output_value - 50000, 0), wallet.get_balance())
@@ -1385,10 +1385,10 @@ class TestWalletSending(TestCaseForTestnet):
self.assertEqual(tx.txid(), tx_copy.txid())
self.assertEqual(tx.wtxid(), tx_copy.wtxid())
- self.assertEqual('010000000001014a5d2593658f7feb9fadcf70dced3bc18db8c90bf77495e608f14dd51c6e6ac30100000000fdffffff01f0874b0000000000160014d4ca56fcbad98fb4dcafdc573a75d6a6fffb09b70247304402200a0855f38f3f5015e78c5d2161c1d881e16ea8169b375ef423feb0233ed0402d0220238c48d56eb846e3d71945b856554f2665ff55dfb7d52249fca6de0b7cecb338012102a6ff1ffc189b4776b78e20edca969cc45da3e610cc0cc79925604be43fee469fbd391400',
+ self.assertEqual('010000000001014a5d2593658f7feb9fadcf70dced3bc18db8c90bf77495e608f14dd51c6e6ac30100000000fdffffff01f0874b0000000000160014f0fe5c1867a174a12e70165e728a072619455ed502473044022029314c8fb5e05dcd6e94d26f7d96bd9824290977bdc0602b2ef1faf8aa7da53c022003c0477a2b45f05ec4e06e4669a9c3a9e8d9ad0ab78ed85a37b93064c5358e9a012102a6ff1ffc189b4776b78e20edca969cc45da3e610cc0cc79925604be43fee469fbd391400',
str(tx_copy))
- self.assertEqual('92fe0029019e8f7476fbee38a684c40c2d726bc769ea064e9cb044d09e715be1', tx_copy.txid())
- self.assertEqual('5ab92fa14ffecc3c510a77f994bdf6bb5aa810e74ddf41b8a03da088d5a96326', tx_copy.wtxid())
+ self.assertEqual('6bb0490b29b65c7292f6bb1715982fe4474417b4fbdcf8a4675a0994ce12d156', tx_copy.txid())
+ self.assertEqual('ce94905afcb396d7bc6de28e4d102dcefc85224abae7df16399b2789f5596db8', tx_copy.wtxid())
wallet.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
self.assertEqual((0, funding_output_value - 50000, 0), wallet.get_balance())
diff --git a/electrum/wallet.py b/electrum/wallet.py
@@ -1089,7 +1089,9 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
return tx
return candidate
- def get_change_addresses_for_new_transaction(self, preferred_change_addr=None) -> List[str]:
+ def get_change_addresses_for_new_transaction(
+ self, preferred_change_addr=None, *, allow_reuse: bool = True,
+ ) -> List[str]:
change_addrs = []
if preferred_change_addr:
if isinstance(preferred_change_addr, (list, tuple)):
@@ -1106,6 +1108,8 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
change_addrs = addrs
else:
# if there are none, take one randomly from the last few
+ if not allow_reuse:
+ return []
addrs = self.get_change_addresses(slice_start=-self.gap_limit_for_change)
change_addrs = [random.choice(addrs)] if addrs else []
for addr in change_addrs:
@@ -1116,6 +1120,17 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
max_change = self.max_change_outputs if self.multiple_change else 1
return change_addrs[:max_change]
+ def get_single_change_address_for_new_transaction(
+ self, preferred_change_addr=None, *, allow_reuse: bool = True,
+ ) -> Optional[str]:
+ addrs = self.get_change_addresses_for_new_transaction(
+ preferred_change_addr=preferred_change_addr,
+ allow_reuse=allow_reuse,
+ )
+ if addrs:
+ return addrs[0]
+ return None
+
@check_returned_address_for_corruption
def get_new_sweep_address_for_channel(self) -> str:
# Recalc and get unused change addresses
@@ -1447,7 +1462,9 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
if not item:
return
inputs = [item]
- out_address = self.get_unused_address() or address
+ out_address = (self.get_single_change_address_for_new_transaction(allow_reuse=False)
+ or self.get_unused_address()
+ or address)
outputs = [PartialTxOutput.from_address_and_value(out_address, value - fee)]
locktime = get_locktime_for_new_transaction(self.network)
tx_new = PartialTransaction.from_io(inputs, outputs, locktime=locktime)