commit e1f4865844ce1bbdbd91a76b8ba245ae04b6300e
parent 0169ec880ca69efe78bc23b40dfcbef82edc0155
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:
3 files changed, 80 insertions(+), 51 deletions(-)
diff --git a/electrum/network.py b/electrum/network.py
@@ -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
@@ -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)
diff --git a/electrum/plugins/digitalbitbox/digitalbitbox.py b/electrum/plugins/digitalbitbox/digitalbitbox.py
@@ -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
@@ -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):
diff --git a/electrum/plugins/trustedcoin/trustedcoin.py b/electrum/plugins/trustedcoin/trustedcoin.py
@@ -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
@@ -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
@@ -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()
@@ -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))
@@ -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:
@@ -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)