network: randomise the order of address subscriptions
Before this, we were subscribing to our addresses in their bip32 order, leaking this information to servers. While this leak seems mostly harmless, it is trivial to fix.
This commit is contained in:
@@ -11,7 +11,7 @@ from typing import NamedTuple, Dict
|
|||||||
from . import util
|
from . import util
|
||||||
from .sql_db import SqlDB, sql
|
from .sql_db import SqlDB, sql
|
||||||
from .wallet_db import WalletDB
|
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 .address_synchronizer import AddressSynchronizer, TX_HEIGHT_LOCAL, TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_UNCONFIRMED
|
||||||
from .transaction import Transaction, TxOutpoint
|
from .transaction import Transaction, TxOutpoint
|
||||||
|
|
||||||
@@ -278,8 +278,8 @@ class WatchTower(LNWatcher):
|
|||||||
|
|
||||||
async def start_watching(self):
|
async def start_watching(self):
|
||||||
# I need to watch the addresses from sweepstore
|
# I need to watch the addresses from sweepstore
|
||||||
l = await self.sweepstore.list_channels()
|
lst = await self.sweepstore.list_channels()
|
||||||
for outpoint, address in l:
|
for outpoint, address in random_shuffled_copy(lst):
|
||||||
self.add_channel(outpoint, address)
|
self.add_channel(outpoint, address)
|
||||||
|
|
||||||
async def do_breach_remedy(self, funding_outpoint, closing_tx, spenders):
|
async def do_breach_remedy(self, funding_outpoint, closing_tx, spenders):
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ from .crypto import sha256
|
|||||||
from .bip32 import BIP32Node
|
from .bip32 import BIP32Node
|
||||||
from .util import bh2u, bfh, InvoiceError, resolve_dns_srv, is_ip_address, log_exceptions
|
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 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 .util import MyEncoder
|
||||||
from .logging import Logger
|
from .logging import Logger
|
||||||
from .lntransport import LNTransport, LNResponderTransport
|
from .lntransport import LNTransport, LNResponderTransport
|
||||||
@@ -499,7 +499,7 @@ class LNWallet(LNWorker):
|
|||||||
# note: accessing channels (besides simple lookup) needs self.lock!
|
# note: accessing channels (besides simple lookup) needs self.lock!
|
||||||
self._channels = {} # type: Dict[bytes, Channel]
|
self._channels = {} # type: Dict[bytes, Channel]
|
||||||
channels = self.db.get_dict("channels")
|
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._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]]
|
self.pending_payments = defaultdict(asyncio.Future) # type: Dict[bytes, asyncio.Future[BarePaymentAttemptLog]]
|
||||||
@@ -1397,7 +1397,7 @@ class LNBackups(Logger):
|
|||||||
self.wallet = wallet
|
self.wallet = wallet
|
||||||
self.db = wallet.db
|
self.db = wallet.db
|
||||||
self.channel_backups = {}
|
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)
|
self.channel_backups[bfh(channel_id)] = ChannelBackup(cb, sweep_address=self.sweep_address, lnworker=self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ from aiorpcx import TaskGroup, run_in_thread, RPCError
|
|||||||
|
|
||||||
from . import util
|
from . import util
|
||||||
from .transaction import Transaction, PartialTransaction
|
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 .bitcoin import address_to_scripthash, is_address
|
||||||
from .network import UntrustedServerReturnedError
|
from .network import UntrustedServerReturnedError
|
||||||
from .logging import Logger
|
from .logging import Logger
|
||||||
@@ -240,7 +240,7 @@ class Synchronizer(SynchronizerBase):
|
|||||||
if history == ['*']: continue
|
if history == ['*']: continue
|
||||||
await self._request_missing_txs(history, allow_server_not_finding_tx=True)
|
await self._request_missing_txs(history, allow_server_not_finding_tx=True)
|
||||||
# add addresses to bootstrap
|
# 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)
|
await self._add_address(addr)
|
||||||
# main loop
|
# main loop
|
||||||
while True:
|
while True:
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import binascii
|
|||||||
import os, sys, re, json
|
import os, sys, re, json
|
||||||
from collections import defaultdict, OrderedDict
|
from collections import defaultdict, OrderedDict
|
||||||
from typing import (NamedTuple, Union, TYPE_CHECKING, Tuple, Optional, Callable, Any,
|
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
|
from datetime import datetime
|
||||||
import decimal
|
import decimal
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
@@ -1398,3 +1398,12 @@ class JsonRPCClient:
|
|||||||
async def coro(*args):
|
async def coro(*args):
|
||||||
return await self.request(endpoint, *args)
|
return await self.request(endpoint, *args)
|
||||||
setattr(self, endpoint, coro)
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user