diff --git a/contrib/build-wine/prepare-wine.sh b/contrib/build-wine/prepare-wine.sh index 24196d22..e80259f5 100755 --- a/contrib/build-wine/prepare-wine.sh +++ b/contrib/build-wine/prepare-wine.sh @@ -112,8 +112,6 @@ done # upgrade pip $PYTHON -m pip install pip --upgrade -# install PySocks -$PYTHON -m pip install win_inet_pton==1.0.1 $PYTHON -m pip install -r $here/../deterministic-build/requirements-binaries.txt diff --git a/contrib/deterministic-build/requirements.txt b/contrib/deterministic-build/requirements.txt index c271e34c..56c4b094 100644 --- a/contrib/deterministic-build/requirements.txt +++ b/contrib/deterministic-build/requirements.txt @@ -134,6 +134,4 @@ yarl==1.3.0 \ --hash=sha256:e060906c0c585565c718d1c3841747b61c5439af2211e185f6739a9412dfbde1 colorama==0.4.1 \ --hash=sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d \ - --hash=sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48 -passlib==1.7.1 \ - --hash=sha256:43526aea08fa32c6b6dbbbe9963c4c767285b78147b7437597f992812f69d280 + --hash=sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48 \ No newline at end of file diff --git a/electrum/blockchain.py b/electrum/blockchain.py index 4a6857db..45b20da3 100644 --- a/electrum/blockchain.py +++ b/electrum/blockchain.py @@ -30,7 +30,6 @@ from .crypto import sha256d from . import constants from .util import bfh, bh2u from .simple_config import SimpleConfig - try: import hashlib getPoWHash = lambda x: hashlib.scrypt(password=x, salt=x, n=1024, r=1, p=1, dklen=32) @@ -272,14 +271,24 @@ class Blockchain(util.PrintError): raise Exception("prev hash mismatch: %s vs %s" % (prev_hash, header.get('prev_block_hash'))) if constants.net.TESTNET: return +#<<<<<<< HEAD # bits = self.target_to_bits(target) + #bits = target + #if bits != header.get('bits'): + # raise Exception("bits mismatch: %s vs %s" % (bits, header.get('bits'))) + #block_hash = int('0x' + _hash, 16) + #target_val = self.bits_to_target(bits) + #if int('0x' + _powhash, 16) > target_val: + # raise Exception("insufficient proof of work: %s vs target %s" % (int('0x' + _hash, 16), target_val)) +#======= + #bits = cls.target_to_bits(target) bits = target if bits != header.get('bits'): raise Exception("bits mismatch: %s vs %s" % (bits, header.get('bits'))) - block_hash = int('0x' + _hash, 16) - target_val = self.bits_to_target(bits) - #if int('0x' + _powhash, 16) > target_val: - # raise Exception("insufficient proof of work: %s vs target %s" % (int('0x' + _hash, 16), target_val)) + block_hash_as_num = int.from_bytes(bfh(_hash), byteorder='big') + if block_hash_as_num > target: + raise Exception(f"insufficient proof of work: {block_hash_as_num} vs target {target}") +#>>>>>>> upstream/master def verify_chunk(self, index: int, data: bytes) -> None: num = len(data) // HEADER_SIZE @@ -550,12 +559,12 @@ class Blockchain(util.PrintError): return bnNew @classmethod - def bits_to_target(self, bits: int) -> int: + def bits_to_target(cls, bits: int) -> int: bitsN = (bits >> 24) & 0xff - if not (bitsN >= 0x03 and bitsN <= 0x1e): - raise BaseException("First part of bits should be in [0x03, 0x1e]") + if not (0x03 <= bitsN <= 0x1d): + raise Exception("First part of bits should be in [0x03, 0x1d]") bitsBase = bits & 0xffffff - if not (bitsBase >= 0x8000 and bitsBase <= 0x7fffff): + if not (0x8000 <= bitsBase <= 0x7fffff): raise Exception("Second part of bits should be in [0x8000, 0x7fffff]") return bitsBase << (8 * (bitsN - 3)) diff --git a/electrum/gui/qt/history_list.py b/electrum/gui/qt/history_list.py index 316b6241..da2e4b89 100644 --- a/electrum/gui/qt/history_list.py +++ b/electrum/gui/qt/history_list.py @@ -634,7 +634,7 @@ class HistoryList(MyTreeView, AcceptFileDragDrop): self.parent.show_message(_("Your wallet history has been successfully exported.")) def do_export_history(self, file_name, is_csv): - hist = self.wallet.get_full_history(domain=self.get_domain(), + hist = self.wallet.get_full_history(domain=self.hm.get_domain(), from_timestamp=None, to_timestamp=None, fx=self.parent.fx, diff --git a/electrum/interface.py b/electrum/interface.py index fc6ddfc0..53ce4fde 100644 --- a/electrum/interface.py +++ b/electrum/interface.py @@ -52,6 +52,17 @@ if TYPE_CHECKING: ca_path = certifi.where() +class NetworkTimeout: + # seconds + class Generic: + NORMAL = 30 + RELAXED = 45 + MOST_RELAXED = 180 + class Urgent(Generic): + NORMAL = 10 + RELAXED = 20 + MOST_RELAXED = 60 + class NotificationSession(RPCSession): def __init__(self, *args, **kwargs): @@ -59,6 +70,7 @@ class NotificationSession(RPCSession): self.subscriptions = defaultdict(list) self.cache = {} self.in_flight_requests_semaphore = asyncio.Semaphore(100) + self.default_timeout = NetworkTimeout.Generic.NORMAL async def handle_request(self, request): # note: if server sends malformed request and we raise, the superclass @@ -76,7 +88,7 @@ class NotificationSession(RPCSession): async def send_request(self, *args, timeout=None, **kwargs): # note: the timeout starts after the request touches the wire! if timeout is None: - timeout = 30 + timeout = self.default_timeout # note: the semaphore implementation guarantees no starvation async with self.in_flight_requests_semaphore: try: @@ -327,9 +339,9 @@ class Interface(PrintError): return None async def get_block_header(self, height, assert_mode): - # use lower timeout as we usually have network.bhi_lock here self.print_error('requesting block header {} in mode {}'.format(height, assert_mode)) - timeout = 5 if not self.proxy else 10 + # use lower timeout as we usually have network.bhi_lock here + timeout = self.network.get_network_timeout_seconds(NetworkTimeout.Urgent) res = await self.session.send_request('blockchain.block.header', [height], timeout=timeout) return blockchain.deserialize_header(bytes.fromhex(res), height) @@ -358,6 +370,7 @@ class Interface(PrintError): host=self.host, port=self.port, ssl=sslc, proxy=self.proxy) as session: self.session = session # type: NotificationSession + self.session.default_timeout = self.network.get_network_timeout_seconds(NetworkTimeout.Generic) try: ver = await session.send_request('server.version', [ELECTRUM_VERSION, PROTOCOL_VERSION]) except aiorpcx.jsonrpc.RPCError as e: diff --git a/electrum/network.py b/electrum/network.py index e089c8e6..1704e038 100644 --- a/electrum/network.py +++ b/electrum/network.py @@ -49,7 +49,8 @@ from . import constants from . import blockchain from . import bitcoin from .blockchain import Blockchain, HEADER_SIZE -from .interface import Interface, serialize_server, deserialize_server, RequestTimedOut +from .interface import (Interface, serialize_server, deserialize_server, + RequestTimedOut, NetworkTimeout) from .version import PROTOCOL_VERSION from .simple_config import SimpleConfig @@ -649,11 +650,18 @@ class Network(PrintError): await self._close_interface(interface) self.trigger_callback('network_updated') + def get_network_timeout_seconds(self, request_type=NetworkTimeout.Generic) -> int: + if self.oneserver and not self.auto_connect: + return request_type.MOST_RELAXED + if self.proxy: + return request_type.RELAXED + return request_type.NORMAL + @ignore_exceptions # do not kill main_taskgroup @log_exceptions async def _run_new_interface(self, server): interface = Interface(self, server, self.proxy) - timeout = 10 if not self.proxy else 20 + timeout = self.get_network_timeout_seconds(NetworkTimeout.Urgent) try: await asyncio.wait_for(interface.ready, timeout) except BaseException as e: @@ -724,7 +732,9 @@ class Network(PrintError): return await self.interface.session.send_request('blockchain.transaction.get_merkle', [tx_hash, tx_height]) @best_effort_reliable - async def broadcast_transaction(self, tx, *, timeout=10): + async def broadcast_transaction(self, tx, *, timeout=None): + if timeout is None: + timeout = self.get_network_timeout_seconds(NetworkTimeout.Urgent) out = await self.interface.session.send_request('blockchain.transaction.broadcast', [str(tx)], timeout=timeout) if out != tx.txid(): raise Exception(out) diff --git a/electrum/transaction.py b/electrum/transaction.py index c57da908..78df13bf 100644 --- a/electrum/transaction.py +++ b/electrum/transaction.py @@ -68,12 +68,10 @@ class TxOutput(NamedTuple): address: str value: Union[int, str] # str when the output is set to max: '!' - class TxOutputForUI(NamedTuple): address: str value: int - class TxOutputHwInfo(NamedTuple): address_index: Tuple sorted_xpubs: Iterable[str] diff --git a/electrum/util.py b/electrum/util.py index 8de9fbfe..415cb05c 100644 --- a/electrum/util.py +++ b/electrum/util.py @@ -32,7 +32,6 @@ import urllib import threading import hmac import stat -import inspect from locale import localeconv import asyncio import urllib.request, urllib.parse, urllib.error @@ -61,7 +60,6 @@ def inv_dict(d): ca_path = certifi.where() - base_units = {'FLO':8, 'mFLO':5, 'bits':2, 'sat':0} base_units_inverse = inv_dict(base_units) base_units_list = ['FLO', 'mFLO', 'bits', 'sat'] # list(dict) does not guarantee order @@ -157,6 +155,12 @@ class Satoshis(object): def __ne__(self, other): return not (self == other) + def __eq__(self, other): + return self.value == other.value + + def __ne__(self, other): + return not (self == other) + # note: this is not a NamedTuple as then its json encoding cannot be customized class Fiat(object): @@ -358,18 +362,8 @@ def constant_time_compare(val1, val2): # decorator that prints execution time def profiler(func): - def get_func_name(args): - arg_names_from_sig = inspect.getfullargspec(func).args - # prepend class name if there is one (and if we can find it) - if len(arg_names_from_sig) > 0 and len(args) > 0 \ - and arg_names_from_sig[0] in ('self', 'cls', 'klass'): - classname = args[0].__class__.__name__ - else: - classname = '' - name = '{}.{}'.format(classname, func.__name__) if classname else func.__name__ - return name def do_profile(args, kw_args): - name = get_func_name(args) + name = func.__qualname__ t0 = time.time() o = func(*args, **kw_args) t = time.time() - t0 diff --git a/electrum/wallet.py b/electrum/wallet.py index ad829bea..31a6a13a 100644 --- a/electrum/wallet.py +++ b/electrum/wallet.py @@ -602,8 +602,7 @@ class Abstract_Wallet(AddressSynchronizer): return tx return candidate - def make_unsigned_transaction(self, coins, outputs, config, fixed_fee=None, - change_addr=None, is_sweep=False, flodata=None): + def make_unsigned_transaction(self, coins, outputs, config, fixed_fee=None, change_addr=None, is_sweep=False, flodata=None): # check outputs i_max = None for i, o in enumerate(outputs):