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:
parent
85a32d01b9
commit
19a0f4cc7b
@ -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/')
|
|
||||||
|
@ -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')
|
||||||
|
@ -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):
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
|
@ -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__))
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
|
Loading…
Reference in New Issue
Block a user