Browse Source

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
3.3.3.1
Janus 6 years ago
parent
commit
e1f4865844
  1. 36
      electrum/network.py
  2. 60
      electrum/plugins/digitalbitbox/digitalbitbox.py
  3. 35
      electrum/plugins/trustedcoin/trustedcoin.py

36
electrum/network.py

@ -38,9 +38,12 @@ import traceback
import dns import dns
import dns.resolver import dns.resolver
from aiorpcx import TaskGroup from aiorpcx import TaskGroup
from aiohttp import ClientResponse
from . import util 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 .bitcoin import COIN
from . import constants from . import constants
from . import blockchain from . import blockchain
@ -903,3 +906,34 @@ class Network(PrintError):
await self.interface.group.spawn(self._request_fee_estimates, self.interface) await self.interface.group.spawn(self._request_fee_estimates, self.interface)
await asyncio.sleep(0.1) 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)

60
electrum/plugins/digitalbitbox/digitalbitbox.py

@ -3,35 +3,36 @@
# digitalbitbox.com # 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: 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 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 DIGIBOX = True
except ImportError as e: except ImportError as e:
DIGIBOX = False DIGIBOX = False
@ -744,9 +745,10 @@ class DigitalBitboxPlugin(HW_PluginBase):
EncodeAES_base64(key_s, json.dumps(payload).encode('ascii')).decode('ascii'), EncodeAES_base64(key_s, json.dumps(payload).encode('ascii')).decode('ascii'),
) )
try: 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: 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): def get_xpub(self, device_id, derivation, xtype, wizard):

35
electrum/plugins/trustedcoin/trustedcoin.py

@ -31,6 +31,7 @@ import hashlib
from urllib.parse import urljoin from urllib.parse import urljoin
from urllib.parse import quote from urllib.parse import quote
from aiohttp import ClientResponse
from electrum import ecc, constants, keystore, version, bip32 from electrum import ecc, constants, keystore, version, bip32
from electrum.bitcoin import TYPE_ADDRESS, is_new_seed, public_key_to_p2pkh 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.wallet import Multisig_Wallet, Deterministic_Wallet
from electrum.i18n import _ from electrum.i18n import _
from electrum.plugin import BasePlugin, hook 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.storage import STO_EV_USER_PW
from electrum.network import Network from electrum.network import Network
@ -108,14 +109,7 @@ class TrustedCoinCosignerClient(object):
self.debug = False self.debug = False
self.user_agent = user_agent self.user_agent = user_agent
def send_request(self, method, relative_url, data=None): async def handle_response(self, resp: ClientResponse):
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):
if resp.status != 200: if resp.status != 200:
try: try:
r = await resp.json() r = await resp.json()
@ -128,7 +122,10 @@ class TrustedCoinCosignerClient(object):
except: except:
return await resp.text() 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) url = urljoin(self.base_url, relative_url)
if self.debug: if self.debug:
print('%s %s %s' % (method, url, data)) print('%s %s %s' % (method, url, data))
@ -136,16 +133,12 @@ class TrustedCoinCosignerClient(object):
if self.user_agent: if self.user_agent:
headers['user-agent'] = self.user_agent headers['user-agent'] = self.user_agent
try: try:
proxy = Network.get_instance().proxy if method == 'get':
async with make_aiohttp_session(proxy) as session: return Network.send_http_on_proxy(method, url, params=data, headers=headers, on_finish=self.handle_response)
if method == 'get': elif method == 'post':
async with session.get(url, params=data, headers=headers) as resp: return Network.send_http_on_proxy(method, url, json=data, headers=headers, on_finish=self.handle_response)
return await self.handle_response(resp) else:
elif method == 'post': assert False
async with session.post(url, json=data, headers=headers) as resp:
return await self.handle_response(resp)
else:
assert False
except TrustedCoinException: except TrustedCoinException:
raise raise
except Exception as e: except Exception as e:
@ -434,7 +427,7 @@ class TrustedCoinPlugin(BasePlugin):
try: try:
billing_info = server.get(wallet.get_user_id()[1]) billing_info = server.get(wallet.get_user_id()[1])
except ErrorConnectingServer as e: 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 return
billing_index = billing_info['billing_index'] billing_index = billing_info['billing_index']
billing_address = make_billing_address(wallet, billing_index) billing_address = make_billing_address(wallet, billing_index)

Loading…
Cancel
Save