Browse Source

wallet: (regression) fix get_spendable_coins when "domain" arg is given

`get_spendable_coins` was ignoring the "domain" param, and returning utxos for the whole wallet
patch-4
SomberNight 3 years ago
parent
commit
2c73e7f854
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 35
      electrum/tests/test_wallet_vertical.py
  2. 28
      electrum/wallet.py

35
electrum/tests/test_wallet_vertical.py

@ -2412,6 +2412,41 @@ class TestWalletSending(TestCaseForTestnet):
self.assertEqual('02000000000101ce010c0cab95cde544f713771916613a1a84c8787bbc95321854410b212aed9b0100000000fdffffff02cac00000000000001600147a65e09bb1da80abfc65d545388a2e61aab7c721eec100000000000016001405424089c64d39d9a498b6e1c8e646327431b240024730440220526eac6c56cba19842b67f6c9e45af113b1a2d44fb229335bdeaf08cb2cc164e0220087fba65619016fd3f62f6c8717070e48f94b45743b86d8e0517698d2b9c3afc012102d67eaa10463f5c786271feb9ae3456c27d35c3cf6c7d881617e915d1f32cb875c4951e00',
str(tx_copy))
@mock.patch.object(wallet.Abstract_Wallet, 'save_db')
def test_get_spendable_coins(self, mock_save_db):
wallet = self.create_standard_wallet_from_seed('frost repair depend effort salon ring foam oak cancel receive save usage',
config=self.config)
# bootstrap wallet (incoming funding_tx1)
funding_tx1 = Transaction('01000000000102acd6459dec7c3c51048eb112630da756f5d4cb4752b8d39aa325407ae0885cba020000001716001455c7f5e0631d8e6f5f05dddb9f676cec48845532fdffffffd146691ef6a207b682b13da5f2388b1f0d2a2022c8cfb8dc27b65434ec9ec8f701000000171600147b3be8a7ceaf15f57d7df2a3d216bc3c259e3225fdffffff02a9875b000000000017a914ea5a99f83e71d1c1dfc5d0370e9755567fe4a141878096980000000000160014d4ca56fcbad98fb4dcafdc573a75d6a6fffb09b702483045022100dde1ba0c9a2862a65791b8d91295a6603207fb79635935a67890506c214dd96d022046c6616642ef5971103c1db07ac014e63fa3b0e15c5729eacdd3e77fcb7d2086012103a72410f185401bb5b10aaa30989c272b554dc6d53bda6da85a76f662723421af024730440220033d0be8f74e782fbcec2b396647c7715d2356076b442423f23552b617062312022063c95cafdc6d52ccf55c8ee0f9ceb0f57afb41ea9076eb74fe633f59c50c6377012103b96a4954d834fbcfb2bbf8cf7de7dc2b28bc3d661c1557d1fd1db1bfc123a94abb391400')
funding_txid1 = funding_tx1.txid()
self.assertEqual('52e669a20a26c8b3df5b41e5e6309b18bcde8e1ad7ea17a18f63b6dc6c8becc0', funding_txid1)
wallet.adb.receive_tx_callback(funding_txid1, funding_tx1, TX_HEIGHT_UNCONFIRMED)
# another incoming transaction (funding_tx2)
funding_tx2 = Transaction('01000000000101c0ec8b6cdcb6638fa117ead71a8edebc189b30e6e5415bdfb3c8260aa269e6520000000017160014ba9ca815474a674ff1efb3fc82cf0f3460de8c57fdffffff0230390f000000000017a9148b59abaca8215c0d4b18cbbf715550aa2b50c85b87404b4c000000000016001483c3bc7234f17a209cc5dcce14903b54ee4dab9002473044022038a05f7d38bcf810dfebb39f1feda5cc187da4cf5d6e56986957ddcccedc75d302203ab67ccf15431b4e2aeeab1582b9a5a7821e7ac4be8ebf512505dbfdc7e094fd0121032168234e0ba465b8cedc10173ea9391725c0f6d9fa517641af87926626a5144abd391400')
funding_txid2 = funding_tx2.txid()
self.assertEqual('c36a6e1cd54df108e69574f70bc9b88dc13beddc70cfad9feb7f8f6593255d4a', funding_txid2)
wallet.adb.receive_tx_callback(funding_txid2, funding_tx2, TX_HEIGHT_UNCONFIRMED)
self.assertEqual((0, 15_000_000, 0), wallet.get_balance())
self.assertEqual(
{'c36a6e1cd54df108e69574f70bc9b88dc13beddc70cfad9feb7f8f6593255d4a:1',
'52e669a20a26c8b3df5b41e5e6309b18bcde8e1ad7ea17a18f63b6dc6c8becc0:1'},
{txi.prevout.to_str() for txi in wallet.get_spendable_coins()})
self.assertEqual(
{'52e669a20a26c8b3df5b41e5e6309b18bcde8e1ad7ea17a18f63b6dc6c8becc0:1'},
{txi.prevout.to_str() for txi in wallet.get_spendable_coins(["tb1q6n99dl96mx8mfh90m3tn5awk5mllkzdh25dw7z"])})
# test freezing an address
wallet.set_frozen_state_of_addresses(["tb1q6n99dl96mx8mfh90m3tn5awk5mllkzdh25dw7z"], freeze=True)
self.assertEqual(
{'c36a6e1cd54df108e69574f70bc9b88dc13beddc70cfad9feb7f8f6593255d4a:1'},
{txi.prevout.to_str() for txi in wallet.get_spendable_coins()})
wallet.set_frozen_state_of_addresses(["tb1q6n99dl96mx8mfh90m3tn5awk5mllkzdh25dw7z"], freeze=False)
self.assertEqual(
{'c36a6e1cd54df108e69574f70bc9b88dc13beddc70cfad9feb7f8f6593255d4a:1',
'52e669a20a26c8b3df5b41e5e6309b18bcde8e1ad7ea17a18f63b6dc6c8becc0:1'},
{txi.prevout.to_str() for txi in wallet.get_spendable_coins()})
class TestWalletOfflineSigning(TestCaseForTestnet):

28
electrum/wallet.py

@ -40,7 +40,7 @@ from functools import partial
from collections import defaultdict
from numbers import Number
from decimal import Decimal
from typing import TYPE_CHECKING, List, Optional, Tuple, Union, NamedTuple, Sequence, Dict, Any, Set
from typing import TYPE_CHECKING, List, Optional, Tuple, Union, NamedTuple, Sequence, Dict, Any, Set, Iterable
from abc import ABC, abstractmethod
import itertools
import threading
@ -830,19 +830,31 @@ class Abstract_Wallet(ABC, Logger, EventListener):
def get_addr_balance(self, address):
return self.adb.get_balance([address])
def get_utxos(self, **kwargs):
domain = self.get_addresses()
def get_utxos(
self,
domain: Optional[Iterable[str]] = None,
**kwargs,
):
if domain is None:
domain = self.get_addresses()
return self.adb.get_utxos(domain=domain, **kwargs)
def get_spendable_coins(self, domain, *, nonlocal_only=False) -> Sequence[PartialTxInput]:
def get_spendable_coins(
self,
domain: Optional[Iterable[str]] = None,
*,
nonlocal_only: bool = False,
) -> Sequence[PartialTxInput]:
confirmed_only = self.config.get('confirmed_only', False)
with self._freeze_lock:
frozen_addresses = self._frozen_addresses.copy()
utxos = self.get_utxos(
excluded_addresses=frozen_addresses,
mature_only=True,
confirmed_funding_only=confirmed_only,
nonlocal_only=nonlocal_only)
domain=domain,
excluded_addresses=frozen_addresses,
mature_only=True,
confirmed_funding_only=confirmed_only,
nonlocal_only=nonlocal_only,
)
utxos = [utxo for utxo in utxos if not self.is_frozen_coin(utxo)]
return utxos

Loading…
Cancel
Save