URI: 
       tMerge pull request #6238 from SomberNight/202006_randomise_address_subscriptions - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit c887c910c6b8e63ec0fda305b997cd4099343f79
   DIR parent 5f2d347d81f9b8daeab3757eeed736c867cf12bd
  HTML Author: ghost43 <somber.night@protonmail.com>
       Date:   Thu, 18 Jun 2020 15:43:44 +0000
       
       Merge pull request #6238 from SomberNight/202006_randomise_address_subscriptions
       
       network: randomise the order of address subscriptions
       Diffstat:
         M electrum/lnwatcher.py               |       6 +++---
         M electrum/lnworker.py                |       6 +++---
         M electrum/synchronizer.py            |       4 ++--
         M electrum/util.py                    |      11 ++++++++++-
       
       4 files changed, 18 insertions(+), 9 deletions(-)
       ---
   DIR diff --git a/electrum/lnwatcher.py b/electrum/lnwatcher.py
       t@@ -11,7 +11,7 @@ from typing import NamedTuple, Dict
        from . import util
        from .sql_db import SqlDB, sql
        from .wallet_db import WalletDB
       -from .util import bh2u, bfh, log_exceptions, ignore_exceptions, TxMinedInfo
       +from .util import bh2u, bfh, log_exceptions, ignore_exceptions, TxMinedInfo, random_shuffled_copy
        from .address_synchronizer import AddressSynchronizer, TX_HEIGHT_LOCAL, TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_UNCONFIRMED
        from .transaction import Transaction, TxOutpoint
        
       t@@ -278,8 +278,8 @@ class WatchTower(LNWatcher):
        
            async def start_watching(self):
                # I need to watch the addresses from sweepstore
       -        l = await self.sweepstore.list_channels()
       -        for outpoint, address in l:
       +        lst = await self.sweepstore.list_channels()
       +        for outpoint, address in random_shuffled_copy(lst):
                    self.add_channel(outpoint, address)
        
            async def do_breach_remedy(self, funding_outpoint, closing_tx, spenders):
   DIR diff --git a/electrum/lnworker.py b/electrum/lnworker.py
       t@@ -35,7 +35,7 @@ from .crypto import sha256
        from .bip32 import BIP32Node
        from .util import bh2u, bfh, InvoiceError, resolve_dns_srv, is_ip_address, log_exceptions
        from .util import ignore_exceptions, make_aiohttp_session, SilentTaskGroup
       -from .util import timestamp_to_datetime
       +from .util import timestamp_to_datetime, random_shuffled_copy
        from .util import MyEncoder
        from .logging import Logger
        from .lntransport import LNTransport, LNResponderTransport
       t@@ -500,7 +500,7 @@ class LNWallet(LNWorker):
                # note: accessing channels (besides simple lookup) needs self.lock!
                self._channels = {}  # type: Dict[bytes, Channel]
                channels = self.db.get_dict("channels")
       -        for channel_id, c in channels.items():
       +        for channel_id, c in random_shuffled_copy(channels.items()):
                    self._channels[bfh(channel_id)] = Channel(c, sweep_address=self.sweep_address, lnworker=self)
        
                self.pending_payments = defaultdict(asyncio.Future)  # type: Dict[bytes, asyncio.Future[BarePaymentAttemptLog]]
       t@@ -1413,7 +1413,7 @@ class LNBackups(Logger):
                self.wallet = wallet
                self.db = wallet.db
                self.channel_backups = {}
       -        for channel_id, cb in self.db.get_dict("channel_backups").items():
       +        for channel_id, cb in random_shuffled_copy(self.db.get_dict("channel_backups").items()):
                    self.channel_backups[bfh(channel_id)] = ChannelBackup(cb, sweep_address=self.sweep_address, lnworker=self)
        
            @property
   DIR diff --git a/electrum/synchronizer.py b/electrum/synchronizer.py
       t@@ -32,7 +32,7 @@ from aiorpcx import TaskGroup, run_in_thread, RPCError
        
        from . import util
        from .transaction import Transaction, PartialTransaction
       -from .util import bh2u, make_aiohttp_session, NetworkJobOnDefaultServer
       +from .util import bh2u, make_aiohttp_session, NetworkJobOnDefaultServer, random_shuffled_copy
        from .bitcoin import address_to_scripthash, is_address
        from .network import UntrustedServerReturnedError
        from .logging import Logger
       t@@ -240,7 +240,7 @@ class Synchronizer(SynchronizerBase):
                    if history == ['*']: continue
                    await self._request_missing_txs(history, allow_server_not_finding_tx=True)
                # add addresses to bootstrap
       -        for addr in self.wallet.get_addresses():
       +        for addr in random_shuffled_copy(self.wallet.get_addresses()):
                    await self._add_address(addr)
                # main loop
                while True:
   DIR diff --git a/electrum/util.py b/electrum/util.py
       t@@ -24,7 +24,7 @@ import binascii
        import os, sys, re, json
        from collections import defaultdict, OrderedDict
        from typing import (NamedTuple, Union, TYPE_CHECKING, Tuple, Optional, Callable, Any,
       -                    Sequence, Dict, Generic, TypeVar)
       +                    Sequence, Dict, Generic, TypeVar, List, Iterable)
        from datetime import datetime
        import decimal
        from decimal import Decimal
       t@@ -1398,3 +1398,12 @@ class JsonRPCClient:
                async def coro(*args):
                    return await self.request(endpoint, *args)
                setattr(self, endpoint, coro)
       +
       +
       +T = TypeVar('T')
       +
       +def random_shuffled_copy(x: Iterable[T]) -> List[T]:
       +    """Returns a shuffled copy of the input."""
       +    x_copy = list(x)  # copy
       +    random.shuffle(x_copy)  # shuffle in-place
       +    return x_copy