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.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)

60
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):

35
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)

Loading…
Cancel
Save