URI: 
       tdigitalbitbox, trustedcoin: proxied http client - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit e1f4865844ce1bbdbd91a76b8ba245ae04b6300e
   DIR parent 0169ec880ca69efe78bc23b40dfcbef82edc0155
  HTML Author: Janus <ysangkok@gmail.com>
       Date:   Fri,  7 Dec 2018 19:19:40 +0100
       
       digitalbitbox, trustedcoin: proxied http client
       
       use common cross-thread HTTP method, which is put in network.py,
       since that is where the proxy is. TrustedCoin tested successfully,
       but DigitalBitbox can't be tested completely due to #4903
       
       before this commit, digitalbitbox would not use any proxying
       
       Diffstat:
         M electrum/network.py                 |      36 ++++++++++++++++++++++++++++++-
         M electrum/plugins/digitalbitbox/dig… |      60 ++++++++++++++++---------------
         M electrum/plugins/trustedcoin/trust… |      35 +++++++++++++-------------------
       
       3 files changed, 80 insertions(+), 51 deletions(-)
       ---
   DIR diff --git a/electrum/network.py b/electrum/network.py
       t@@ -38,9 +38,12 @@ import traceback
        import dns
        import dns.resolver
        from aiorpcx import TaskGroup
       +from aiohttp import ClientResponse
        
        from . import util
       -from .util import PrintError, print_error, log_exceptions, ignore_exceptions, bfh, SilentTaskGroup
       +from .util import (PrintError, print_error, log_exceptions, ignore_exceptions,
       +                   bfh, SilentTaskGroup, make_aiohttp_session)
       +
        from .bitcoin import COIN
        from . import constants
        from . import blockchain
       t@@ -903,3 +906,34 @@ class Network(PrintError):
                            await self.interface.group.spawn(self._request_fee_estimates, self.interface)
        
                    await asyncio.sleep(0.1)
       +
       +
       +    async def _send_http_on_proxy(self, method: str, url: str, params: str = None, body: bytes = None, json: dict = None, headers=None, on_finish=None):
       +        async def default_on_finish(resp: ClientResponse):
       +            resp.raise_for_status()
       +            return await resp.text()
       +        if headers is None:
       +            headers = {}
       +        if on_finish is None:
       +            on_finish = default_on_finish
       +        async with make_aiohttp_session(self.proxy) as session:
       +            if method == 'get':
       +                async with session.get(url, params=params, headers=headers) as resp:
       +                    return await on_finish(resp)
       +            elif method == 'post':
       +                assert body is not None or json is not None, 'body or json must be supplied if method is post'
       +                if body is not None:
       +                    async with session.post(url, data=body, headers=headers) as resp:
       +                        return await on_finish(resp)
       +                elif json is not None:
       +                    async with session.post(url, json=json, headers=headers) as resp:
       +                        return await on_finish(resp)
       +            else:
       +                assert False
       +
       +    @staticmethod
       +    def send_http_on_proxy(method, url, **kwargs):
       +        network = Network.get_instance()
       +        assert network._loop_thread is not threading.currentThread()
       +        coro = asyncio.run_coroutine_threadsafe(network._send_http_on_proxy(method, url, **kwargs), network.asyncio_loop)
       +        return coro.result(5)
   DIR diff --git a/electrum/plugins/digitalbitbox/digitalbitbox.py b/electrum/plugins/digitalbitbox/digitalbitbox.py
       t@@ -3,35 +3,36 @@
        # digitalbitbox.com
        #
        
       +import base64
       +import binascii
       +import hashlib
       +import hmac
       +import json
       +import math
       +import os
       +import re
       +import struct
       +import sys
       +import time
       +
       +from electrum.crypto import sha256d, EncodeAES_base64, EncodeAES_bytes, DecodeAES_bytes, hmac_oneshot
       +from electrum.bitcoin import (TYPE_ADDRESS, push_script, var_int, public_key_to_p2pkh,
       +                              is_address)
       +from electrum.bip32 import serialize_xpub, deserialize_xpub
       +from electrum import ecc
       +from electrum.ecc import msg_magic
       +from electrum.wallet import Standard_Wallet
       +from electrum import constants
       +from electrum.transaction import Transaction
       +from electrum.i18n import _
       +from electrum.keystore import Hardware_KeyStore
       +from ..hw_wallet import HW_PluginBase
       +from electrum.util import print_error, to_string, UserCancelled, UserFacingException
       +from electrum.base_wizard import ScriptTypeNotSupported, HWD_SETUP_NEW_WALLET
       +from electrum.network import Network
       +
        try:
       -    from electrum.crypto import sha256d, EncodeAES_base64, EncodeAES_bytes, DecodeAES_bytes, hmac_oneshot
       -    from electrum.bitcoin import (TYPE_ADDRESS, push_script, var_int, public_key_to_p2pkh,
       -                                  is_address)
       -    from electrum.bip32 import serialize_xpub, deserialize_xpub
       -    from electrum import ecc
       -    from electrum.ecc import msg_magic
       -    from electrum.wallet import Standard_Wallet
       -    from electrum import constants
       -    from electrum.transaction import Transaction
       -    from electrum.i18n import _
       -    from electrum.keystore import Hardware_KeyStore
       -    from ..hw_wallet import HW_PluginBase
       -    from electrum.util import print_error, to_string, UserCancelled, UserFacingException
       -    from electrum.base_wizard import ScriptTypeNotSupported, HWD_SETUP_NEW_WALLET
       -
       -    import time
            import hid
       -    import json
       -    import math
       -    import binascii
       -    import struct
       -    import hashlib
       -    import requests
       -    import base64
       -    import os
       -    import sys
       -    import re
       -    import hmac
            DIGIBOX = True
        except ImportError as e:
            DIGIBOX = False
       t@@ -744,9 +745,10 @@ class DigitalBitboxPlugin(HW_PluginBase):
                    EncodeAES_base64(key_s, json.dumps(payload).encode('ascii')).decode('ascii'),
                )
                try:
       -            requests.post(url, args)
       +            text = Network.send_http_on_proxy('post', url, body=args.encode('ascii'), headers={'content-type': 'application/x-www-form-urlencoded'})
       +            print_error('digitalbitbox reply from server', text)
                except Exception as e:
       -            self.handler.show_error(str(e))
       +            self.handler.show_error(repr(e)) # repr because str(Exception()) == ''
        
        
            def get_xpub(self, device_id, derivation, xtype, wizard):
   DIR diff --git a/electrum/plugins/trustedcoin/trustedcoin.py b/electrum/plugins/trustedcoin/trustedcoin.py
       t@@ -31,6 +31,7 @@ import hashlib
        
        from urllib.parse import urljoin
        from urllib.parse import quote
       +from aiohttp import ClientResponse
        
        from electrum import ecc, constants, keystore, version, bip32
        from electrum.bitcoin import TYPE_ADDRESS, is_new_seed, public_key_to_p2pkh
       t@@ -42,7 +43,7 @@ from electrum.mnemonic import Mnemonic
        from electrum.wallet import Multisig_Wallet, Deterministic_Wallet
        from electrum.i18n import _
        from electrum.plugin import BasePlugin, hook
       -from electrum.util import NotEnoughFunds, make_aiohttp_session
       +from electrum.util import NotEnoughFunds
        from electrum.storage import STO_EV_USER_PW
        from electrum.network import Network
        
       t@@ -108,14 +109,7 @@ class TrustedCoinCosignerClient(object):
                self.debug = False
                self.user_agent = user_agent
        
       -    def send_request(self, method, relative_url, data=None):
       -        network = Network.get_instance()
       -        if network:
       -            return asyncio.run_coroutine_threadsafe(self._send_request(method, relative_url, data), network.asyncio_loop).result()
       -        else:
       -            raise ErrorConnectingServer('You are offline.')
       -
       -    async def handle_response(self, resp):
       +    async def handle_response(self, resp: ClientResponse):
                if resp.status != 200:
                    try:
                        r = await resp.json()
       t@@ -128,7 +122,10 @@ class TrustedCoinCosignerClient(object):
                except:
                    return await resp.text()
        
       -    async def _send_request(self, method, relative_url, data):
       +    def send_request(self, method, relative_url, data=None):
       +        network = Network.get_instance()
       +        if not network:
       +            raise ErrorConnectingServer('You are offline.')
                url = urljoin(self.base_url, relative_url)
                if self.debug:
                    print('%s %s %s' % (method, url, data))
       t@@ -136,16 +133,12 @@ class TrustedCoinCosignerClient(object):
                if self.user_agent:
                    headers['user-agent'] = self.user_agent
                try:
       -            proxy = Network.get_instance().proxy
       -            async with make_aiohttp_session(proxy) as session:
       -                if method == 'get':
       -                    async with session.get(url, params=data, headers=headers) as resp:
       -                        return await self.handle_response(resp)
       -                elif method == 'post':
       -                    async with session.post(url, json=data, headers=headers) as resp:
       -                        return await self.handle_response(resp)
       -                else:
       -                    assert False
       +            if method == 'get':
       +                return Network.send_http_on_proxy(method, url, params=data, headers=headers, on_finish=self.handle_response)
       +            elif method == 'post':
       +                return Network.send_http_on_proxy(method, url, json=data, headers=headers, on_finish=self.handle_response)
       +            else:
       +                assert False
                except TrustedCoinException:
                    raise
                except Exception as e:
       t@@ -434,7 +427,7 @@ class TrustedCoinPlugin(BasePlugin):
                try:
                    billing_info = server.get(wallet.get_user_id()[1])
                except ErrorConnectingServer as e:
       -            self.print_error('cannot connect to TrustedCoin server: {}'.format(e))
       +            self.print_error('cannot connect to TrustedCoin server: {}'.format(repr(e)))
                    return
                billing_index = billing_info['billing_index']
                billing_address = make_billing_address(wallet, billing_index)