1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-22 22:38:08 +00:00

tx_api: support blockbook, allow url-less operation

Bitcoin Testnet backends were removed.
This broke our tests that work purely on local data but nevertheless
need to know backend URLs. Because the design is less than ideal.

Here, we do a little cleanup:
* blockbook URLs are respected
* Dogecoin is now supported by our blockbook backend so we don't need
  a special tx-api implementation
* it's possible to instantiate a TxApi that is backed by the cache,
  without a known URL
* relevant tests now make use of this feature
This commit is contained in:
matejcik 2018-07-03 17:26:22 +02:00
parent 85a32d01b9
commit 19a0f4cc7b
7 changed files with 23 additions and 56 deletions

View File

@ -17,7 +17,7 @@
import os.path import os.path
import json import json
from .tx_api import TxApiInsight, TxApiBlockCypher from .tx_api import TxApiInsight
COINS_JSON = os.path.join(os.path.dirname(__file__), 'coins.json') COINS_JSON = os.path.join(os.path.dirname(__file__), 'coins.json')
@ -35,11 +35,11 @@ def _load_coins_json():
def _insight_for_coin(coin): def _insight_for_coin(coin):
if not coin['bitcore']: url = next(iter(coin['blockbook'] + coin['bitcore']), None)
if not url:
return None return None
zcash = coin['coin_name'].lower().startswith('zcash') zcash = coin['coin_name'].lower().startswith('zcash')
network = 'insight_{}'.format(coin['coin_name'].lower().replace(' ', '_')) network = 'insight_{}'.format(coin['coin_name'].lower().replace(' ', '_'))
url = coin['bitcore'][0] + '/api/'
return TxApiInsight(network=network, url=url, zcash=zcash) return TxApiInsight(network=network, url=url, zcash=zcash)
@ -54,7 +54,4 @@ except Exception as e:
slip44 = {name: coin['slip44'] for name, coin in by_name.items()} slip44 = {name: coin['slip44'] for name, coin in by_name.items()}
tx_api = {name: _insight_for_coin(coin) tx_api = {name: _insight_for_coin(coin)
for name, coin in by_name.items() for name, coin in by_name.items()
if coin["bitcore"]} if coin["blockbook"] or coin["bitcore"]}
# fixup for Dogecoin
tx_api['Dogecoin'] = TxApiBlockCypher(network='blockcypher_dogecoin', url='https://api.blockcypher.com/v1/doge/main/')

View File

@ -20,12 +20,12 @@ import pytest
from .common import TrezorTest from .common import TrezorTest
from .conftest import TREZOR_VERSION from .conftest import TREZOR_VERSION
from trezorlib import coins
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib.client import CallException from trezorlib.client import CallException
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from trezorlib.tx_api import TxApiInsight
TxApiTestnet = coins.tx_api['Testnet'] TxApiTestnet = TxApiInsight("insight_testnet")
TXHASH_157041 = unhexlify('1570416eb4302cf52979afd5e6909e37d8fdd874301f7cc87e547e509cb1caa6') TXHASH_157041 = unhexlify('1570416eb4302cf52979afd5e6909e37d8fdd874301f7cc87e547e509cb1caa6')

View File

@ -21,12 +21,12 @@ from ..support.ckd_public import deserialize
from .conftest import TREZOR_VERSION from .conftest import TREZOR_VERSION
from .common import TrezorTest from .common import TrezorTest
from trezorlib import coins
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib.client import CallException from trezorlib.client import CallException
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from trezorlib.tx_api import TxApiInsight
TxApiTestnet = coins.tx_api["Testnet"] TxApiTestnet = TxApiInsight("insight_testnet")
class TestMsgSigntxSegwit(TrezorTest): class TestMsgSigntxSegwit(TrezorTest):

View File

@ -18,11 +18,11 @@ from binascii import hexlify, unhexlify
from .common import TrezorTest from .common import TrezorTest
from ..support.ckd_public import deserialize from ..support.ckd_public import deserialize
from trezorlib import coins
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from trezorlib.tx_api import TxApiInsight
TxApiTestnet = coins.tx_api['Testnet'] TxApiTestnet = TxApiInsight("insight_testnet")
class TestMsgSigntxSegwitNative(TrezorTest): class TestMsgSigntxSegwitNative(TrezorTest):

View File

@ -19,15 +19,17 @@ from binascii import hexlify, unhexlify
from .common import TrezorTest from .common import TrezorTest
from ..support import ckd_public as bip32 from ..support import ckd_public as bip32
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib.coins import tx_api
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from trezorlib.tx_api import TxApiInsight
TxApiTestnet = TxApiInsight("insight_testnet")
class TestMultisigChange(TrezorTest): class TestMultisigChange(TrezorTest):
def setup_method(self, method): def setup_method(self, method):
super(TestMultisigChange, self).setup_method(method) super(TestMultisigChange, self).setup_method(method)
self.client.set_tx_api(tx_api['Testnet']) self.client.set_tx_api(TxApiTestnet)
node_ext1 = bip32.deserialize('tpubDADHV9u9Y6gkggintTdMjJE3be58zKNLhpxBQyuEM6Pwx3sN9JVLmMCMN4DNVwL9AKec27z5TaWcWuHzMXiGAtcra5DjwWbvppGX4gaEGVN') node_ext1 = bip32.deserialize('tpubDADHV9u9Y6gkggintTdMjJE3be58zKNLhpxBQyuEM6Pwx3sN9JVLmMCMN4DNVwL9AKec27z5TaWcWuHzMXiGAtcra5DjwWbvppGX4gaEGVN')
# m/1 => 02c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e # m/1 => 02c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e

View File

@ -20,7 +20,7 @@ from trezorlib import coins
from trezorlib import tx_api from trezorlib import tx_api
TxApiBitcoin = coins.tx_api['Bitcoin'] TxApiBitcoin = coins.tx_api['Bitcoin']
TxApiTestnet = coins.tx_api['Testnet'] TxApiTestnet = tx_api.TxApiInsight("insight_testnet")
tests_dir = os.path.dirname(os.path.abspath(__file__)) tests_dir = os.path.dirname(os.path.abspath(__file__))

View File

@ -25,10 +25,9 @@ cache_dir = None
class TxApi(object): class TxApi(object):
def __init__(self, network, url): def __init__(self, network, url=None):
self.network = network self.network = network
self.url = url self.url = url
self.pushtx_url = url
def get_url(self, resource, resourceid): def get_url(self, resource, resourceid):
url = '%s%s/%s' % (self.url, resource, resourceid) url = '%s%s/%s' % (self.url, resource, resourceid)
@ -44,6 +43,9 @@ class TxApi(object):
except: except:
pass pass
if not self.url:
raise RuntimeError("No URL specified and tx not in cache")
try: try:
url = self.get_url(resource, resourceid) url = self.get_url(resource, resourceid)
r = requests.get(url, headers={'User-agent': 'Mozilla/5.0'}) r = requests.get(url, headers={'User-agent': 'Mozilla/5.0'})
@ -63,10 +65,11 @@ class TxApi(object):
class TxApiInsight(TxApi): class TxApiInsight(TxApi):
def __init__(self, network, url, zcash=None): def __init__(self, network, url=None, zcash=None):
super(TxApiInsight, self).__init__(network, url) super().__init__(network, url)
self.zcash = zcash self.zcash = zcash
self.pushtx_url = url.replace('/api/', '/tx/send') if url:
self.pushtx_url = url.replace('/api/', '/tx/send')
def get_tx(self, txhash): def get_tx(self, txhash):
@ -112,38 +115,3 @@ class TxApiInsight(TxApi):
t.extra_data = raw[-extra_data_len:] t.extra_data = raw[-extra_data_len:]
return t return t
class TxApiBlockCypher(TxApi):
def __init__(self, network, url, zcash=None):
super(TxApiBlockCypher, self).__init__(network, url)
self.pushtx_url = url.replace('//api.', '//live.').replace('/v1/', '/').replace('/main/', '/pushtx/')
def get_tx(self, txhash):
data = self.fetch_json('txs', txhash)
t = proto.TransactionType()
t.version = data['ver']
t.lock_time = data.get('lock_time', 0)
for vin in data['inputs']:
i = t._add_inputs()
if 'prev_hash' not in vin:
i.prev_hash = b"\0" * 32
i.prev_index = 0xffffffff # signed int -1
i.script_sig = binascii.unhexlify(vin['script'])
i.sequence = vin['sequence']
else:
i.prev_hash = binascii.unhexlify(vin['prev_hash'])
i.prev_index = vin['output_index']
i.script_sig = binascii.unhexlify(vin['script'])
i.sequence = vin['sequence']
for vout in data['outputs']:
o = t._add_bin_outputs()
o.amount = int(str(vout['value']), 10)
o.script_pubkey = binascii.unhexlify(vout['script'])
return t